Show More
@@ -1,390 +1,380 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.comment import CommentsModel |
|
22 | from rhodecode.model.comment import CommentsModel | |
24 | from rhodecode.model.db import UserLog, User, ChangesetComment |
|
23 | from rhodecode.model.db import UserLog, User, ChangesetComment | |
25 | from rhodecode.model.pull_request import PullRequestModel |
|
24 | from rhodecode.model.pull_request import PullRequestModel | |
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_ok) |
|
27 | build_data, api_call, assert_error, assert_ok) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestCommentPullRequest(object): |
|
31 | class TestCommentPullRequest(object): | |
33 | finalizers = [] |
|
32 | finalizers = [] | |
34 |
|
33 | |||
35 | def teardown_method(self, method): |
|
34 | def teardown_method(self, method): | |
36 | if self.finalizers: |
|
35 | if self.finalizers: | |
37 | for finalizer in self.finalizers: |
|
36 | for finalizer in self.finalizers: | |
38 | finalizer() |
|
37 | finalizer() | |
39 | self.finalizers = [] |
|
38 | self.finalizers = [] | |
40 |
|
39 | |||
41 | @pytest.mark.backends("git", "hg") |
|
40 | @pytest.mark.backends("git", "hg") | |
42 | def test_api_comment_pull_request(self, pr_util, no_notifications): |
|
41 | def test_api_comment_pull_request(self, pr_util, no_notifications): | |
43 | pull_request = pr_util.create_pull_request() |
|
42 | pull_request = pr_util.create_pull_request() | |
44 | pull_request_id = pull_request.pull_request_id |
|
43 | pull_request_id = pull_request.pull_request_id | |
45 | author = pull_request.user_id |
|
44 | author = pull_request.user_id | |
46 | repo = pull_request.target_repo.repo_id |
|
45 | repo = pull_request.target_repo.repo_id | |
47 | id_, params = build_data( |
|
46 | id_, params = build_data( | |
48 | self.apikey, 'comment_pull_request', |
|
47 | self.apikey, 'comment_pull_request', | |
49 | repoid=pull_request.target_repo.repo_name, |
|
48 | repoid=pull_request.target_repo.repo_name, | |
50 | pullrequestid=pull_request.pull_request_id, |
|
49 | pullrequestid=pull_request.pull_request_id, | |
51 | message='test message') |
|
50 | message='test message') | |
52 | response = api_call(self.app, params) |
|
51 | response = api_call(self.app, params) | |
53 | pull_request = PullRequestModel().get(pull_request.pull_request_id) |
|
52 | pull_request = PullRequestModel().get(pull_request.pull_request_id) | |
54 |
|
53 | |||
55 | comments = CommentsModel().get_comments( |
|
54 | comments = CommentsModel().get_comments( | |
56 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
55 | pull_request.target_repo.repo_id, pull_request=pull_request) | |
57 |
|
56 | |||
58 | expected = { |
|
57 | expected = { | |
59 | 'pull_request_id': pull_request.pull_request_id, |
|
58 | 'pull_request_id': pull_request.pull_request_id, | |
60 | 'comment_id': comments[-1].comment_id, |
|
59 | 'comment_id': comments[-1].comment_id, | |
61 | 'status': {'given': None, 'was_changed': None} |
|
60 | 'status': {'given': None, 'was_changed': None} | |
62 | } |
|
61 | } | |
63 | assert_ok(id_, expected, response.body) |
|
62 | assert_ok(id_, expected, response.body) | |
64 |
|
63 | |||
65 | journal = UserLog.query()\ |
|
64 | journal = UserLog.query()\ | |
66 | .filter(UserLog.user_id == author)\ |
|
65 | .filter(UserLog.user_id == author)\ | |
67 | .filter(UserLog.repository_id == repo) \ |
|
66 | .filter(UserLog.repository_id == repo) \ | |
68 | .order_by(UserLog.user_log_id.asc()) \ |
|
67 | .order_by(UserLog.user_log_id.asc()) \ | |
69 | .all() |
|
68 | .all() | |
70 | assert journal[-1].action == 'repo.pull_request.comment.create' |
|
69 | assert journal[-1].action == 'repo.pull_request.comment.create' | |
71 |
|
70 | |||
72 | @pytest.mark.backends("git", "hg") |
|
71 | @pytest.mark.backends("git", "hg") | |
73 | def test_api_comment_pull_request_with_extra_recipients(self, pr_util, user_util): |
|
72 | def test_api_comment_pull_request_with_extra_recipients(self, pr_util, user_util): | |
74 | pull_request = pr_util.create_pull_request() |
|
73 | pull_request = pr_util.create_pull_request() | |
75 |
|
74 | |||
76 | user1 = user_util.create_user() |
|
75 | user1 = user_util.create_user() | |
77 | user1_id = user1.user_id |
|
76 | user1_id = user1.user_id | |
78 | user2 = user_util.create_user() |
|
77 | user2 = user_util.create_user() | |
79 | user2_id = user2.user_id |
|
78 | user2_id = user2.user_id | |
80 |
|
79 | |||
81 | id_, params = build_data( |
|
80 | id_, params = build_data( | |
82 | self.apikey, 'comment_pull_request', |
|
81 | self.apikey, 'comment_pull_request', | |
83 | repoid=pull_request.target_repo.repo_name, |
|
82 | repoid=pull_request.target_repo.repo_name, | |
84 | pullrequestid=pull_request.pull_request_id, |
|
83 | pullrequestid=pull_request.pull_request_id, | |
85 | message='test message', |
|
84 | message='test message', | |
86 | extra_recipients=[user1.user_id, user2.username] |
|
85 | extra_recipients=[user1.user_id, user2.username] | |
87 | ) |
|
86 | ) | |
88 | response = api_call(self.app, params) |
|
87 | response = api_call(self.app, params) | |
89 | pull_request = PullRequestModel().get(pull_request.pull_request_id) |
|
88 | pull_request = PullRequestModel().get(pull_request.pull_request_id) | |
90 |
|
89 | |||
91 | comments = CommentsModel().get_comments( |
|
90 | comments = CommentsModel().get_comments( | |
92 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
91 | pull_request.target_repo.repo_id, pull_request=pull_request) | |
93 |
|
92 | |||
94 | expected = { |
|
93 | expected = { | |
95 | 'pull_request_id': pull_request.pull_request_id, |
|
94 | 'pull_request_id': pull_request.pull_request_id, | |
96 | 'comment_id': comments[-1].comment_id, |
|
95 | 'comment_id': comments[-1].comment_id, | |
97 | 'status': {'given': None, 'was_changed': None} |
|
96 | 'status': {'given': None, 'was_changed': None} | |
98 | } |
|
97 | } | |
99 | assert_ok(id_, expected, response.body) |
|
98 | assert_ok(id_, expected, response.body) | |
100 | # check user1/user2 inbox for notification |
|
99 | # check user1/user2 inbox for notification | |
101 | user1 = User.get(user1_id) |
|
100 | user1 = User.get(user1_id) | |
102 | assert 1 == len(user1.notifications) |
|
101 | assert 1 == len(user1.notifications) | |
103 | assert 'test message' in user1.notifications[0].notification.body |
|
102 | assert 'test message' in user1.notifications[0].notification.body | |
104 |
|
103 | |||
105 | user2 = User.get(user2_id) |
|
104 | user2 = User.get(user2_id) | |
106 | assert 1 == len(user2.notifications) |
|
105 | assert 1 == len(user2.notifications) | |
107 | assert 'test message' in user2.notifications[0].notification.body |
|
106 | assert 'test message' in user2.notifications[0].notification.body | |
108 |
|
107 | |||
109 | @pytest.mark.backends("git", "hg") |
|
108 | @pytest.mark.backends("git", "hg") | |
110 | def test_api_comment_pull_request_change_status( |
|
109 | def test_api_comment_pull_request_change_status( | |
111 | self, pr_util, no_notifications): |
|
110 | self, pr_util, no_notifications): | |
112 | pull_request = pr_util.create_pull_request() |
|
111 | pull_request = pr_util.create_pull_request() | |
113 | pull_request_id = pull_request.pull_request_id |
|
112 | pull_request_id = pull_request.pull_request_id | |
114 | id_, params = build_data( |
|
113 | id_, params = build_data( | |
115 | self.apikey, 'comment_pull_request', |
|
114 | self.apikey, 'comment_pull_request', | |
116 | repoid=pull_request.target_repo.repo_name, |
|
115 | repoid=pull_request.target_repo.repo_name, | |
117 | pullrequestid=pull_request.pull_request_id, |
|
116 | pullrequestid=pull_request.pull_request_id, | |
118 | status='rejected') |
|
117 | status='rejected') | |
119 | response = api_call(self.app, params) |
|
118 | response = api_call(self.app, params) | |
120 | pull_request = PullRequestModel().get(pull_request_id) |
|
119 | pull_request = PullRequestModel().get(pull_request_id) | |
121 |
|
120 | |||
122 | comments = CommentsModel().get_comments( |
|
121 | comments = CommentsModel().get_comments( | |
123 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
122 | pull_request.target_repo.repo_id, pull_request=pull_request) | |
124 | expected = { |
|
123 | expected = { | |
125 | 'pull_request_id': pull_request.pull_request_id, |
|
124 | 'pull_request_id': pull_request.pull_request_id, | |
126 | 'comment_id': comments[-1].comment_id, |
|
125 | 'comment_id': comments[-1].comment_id, | |
127 | 'status': {'given': 'rejected', 'was_changed': True} |
|
126 | 'status': {'given': 'rejected', 'was_changed': True} | |
128 | } |
|
127 | } | |
129 | assert_ok(id_, expected, response.body) |
|
128 | assert_ok(id_, expected, response.body) | |
130 |
|
129 | |||
131 | @pytest.mark.backends("git", "hg") |
|
130 | @pytest.mark.backends("git", "hg") | |
132 | def test_api_comment_pull_request_change_status_with_specific_commit_id( |
|
131 | def test_api_comment_pull_request_change_status_with_specific_commit_id_and_test_commit( | |
133 | self, pr_util, no_notifications): |
|
132 | self, pr_util, no_notifications): | |
134 | pull_request = pr_util.create_pull_request() |
|
133 | pull_request = pr_util.create_pull_request() | |
135 | pull_request_id = pull_request.pull_request_id |
|
134 | pull_request_id = pull_request.pull_request_id | |
136 | latest_commit_id = 'test_commit' |
|
135 | latest_commit_id = 'test_commit' | |
|
136 | ||||
137 | # inject additional revision, to fail test the status change on |
|
137 | # inject additional revision, to fail test the status change on | |
138 | # non-latest commit |
|
138 | # non-latest commit | |
139 | pull_request.revisions = pull_request.revisions + ['test_commit'] |
|
139 | pull_request.revisions = pull_request.revisions + ['test_commit'] | |
140 |
|
140 | |||
141 | id_, params = build_data( |
|
141 | id_, params = build_data( | |
142 | self.apikey, 'comment_pull_request', |
|
142 | self.apikey, 'comment_pull_request', | |
|
143 | message='test-change-of-status-not-allowed', | |||
143 | repoid=pull_request.target_repo.repo_name, |
|
144 | repoid=pull_request.target_repo.repo_name, | |
144 | pullrequestid=pull_request.pull_request_id, |
|
145 | pullrequestid=pull_request.pull_request_id, | |
145 | status='approved', commit_id=latest_commit_id) |
|
146 | status='approved', commit_id=latest_commit_id) | |
146 | response = api_call(self.app, params) |
|
147 | response = api_call(self.app, params) | |
147 | pull_request = PullRequestModel().get(pull_request_id) |
|
148 | pull_request = PullRequestModel().get(pull_request_id) | |
|
149 | comments = CommentsModel().get_comments( | |||
|
150 | pull_request.target_repo.repo_id, pull_request=pull_request) | |||
148 |
|
151 | |||
149 | expected = { |
|
152 | expected = { | |
150 | 'pull_request_id': pull_request.pull_request_id, |
|
153 | 'pull_request_id': pull_request.pull_request_id, | |
151 |
'comment_id': |
|
154 | 'comment_id': comments[-1].comment_id, | |
152 | 'status': {'given': 'approved', 'was_changed': False} |
|
155 | 'status': {'given': 'approved', 'was_changed': False} | |
153 | } |
|
156 | } | |
154 | assert_ok(id_, expected, response.body) |
|
157 | assert_ok(id_, expected, response.body) | |
155 |
|
158 | |||
156 | @pytest.mark.backends("git", "hg") |
|
159 | @pytest.mark.backends("git", "hg") | |
157 | def test_api_comment_pull_request_change_status_with_specific_commit_id( |
|
160 | def test_api_comment_pull_request_change_status_with_specific_commit_id( | |
158 | self, pr_util, no_notifications): |
|
161 | self, pr_util, no_notifications): | |
159 | pull_request = pr_util.create_pull_request() |
|
162 | pull_request = pr_util.create_pull_request() | |
160 | pull_request_id = pull_request.pull_request_id |
|
163 | pull_request_id = pull_request.pull_request_id | |
161 | latest_commit_id = pull_request.revisions[0] |
|
164 | latest_commit_id = pull_request.revisions[0] | |
162 |
|
165 | |||
163 | id_, params = build_data( |
|
166 | id_, params = build_data( | |
164 | self.apikey, 'comment_pull_request', |
|
167 | self.apikey, 'comment_pull_request', | |
165 | repoid=pull_request.target_repo.repo_name, |
|
168 | repoid=pull_request.target_repo.repo_name, | |
166 | pullrequestid=pull_request.pull_request_id, |
|
169 | pullrequestid=pull_request.pull_request_id, | |
167 | status='approved', commit_id=latest_commit_id) |
|
170 | status='approved', commit_id=latest_commit_id) | |
168 | response = api_call(self.app, params) |
|
171 | response = api_call(self.app, params) | |
169 | pull_request = PullRequestModel().get(pull_request_id) |
|
172 | pull_request = PullRequestModel().get(pull_request_id) | |
170 |
|
173 | |||
171 | comments = CommentsModel().get_comments( |
|
174 | comments = CommentsModel().get_comments( | |
172 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
175 | pull_request.target_repo.repo_id, pull_request=pull_request) | |
173 | expected = { |
|
176 | expected = { | |
174 | 'pull_request_id': pull_request.pull_request_id, |
|
177 | 'pull_request_id': pull_request.pull_request_id, | |
175 | 'comment_id': comments[-1].comment_id, |
|
178 | 'comment_id': comments[-1].comment_id, | |
176 | 'status': {'given': 'approved', 'was_changed': True} |
|
179 | 'status': {'given': 'approved', 'was_changed': True} | |
177 | } |
|
180 | } | |
178 | assert_ok(id_, expected, response.body) |
|
181 | assert_ok(id_, expected, response.body) | |
179 |
|
182 | |||
180 | @pytest.mark.backends("git", "hg") |
|
183 | @pytest.mark.backends("git", "hg") | |
181 | def test_api_comment_pull_request_missing_params_error(self, pr_util): |
|
184 | def test_api_comment_pull_request_missing_params_error(self, pr_util): | |
182 | pull_request = pr_util.create_pull_request() |
|
185 | pull_request = pr_util.create_pull_request() | |
183 | pull_request_id = pull_request.pull_request_id |
|
186 | pull_request_id = pull_request.pull_request_id | |
184 | pull_request_repo = pull_request.target_repo.repo_name |
|
187 | pull_request_repo = pull_request.target_repo.repo_name | |
185 | id_, params = build_data( |
|
188 | id_, params = build_data( | |
186 | self.apikey, 'comment_pull_request', |
|
189 | self.apikey, 'comment_pull_request', | |
187 | repoid=pull_request_repo, |
|
190 | repoid=pull_request_repo, | |
188 | pullrequestid=pull_request_id) |
|
191 | pullrequestid=pull_request_id) | |
189 | response = api_call(self.app, params) |
|
192 | response = api_call(self.app, params) | |
190 |
|
193 | |||
191 | expected = 'Both message and status parameters are missing. At least one is required.' |
|
194 | expected = 'Both message and status parameters are missing. At least one is required.' | |
192 | assert_error(id_, expected, given=response.body) |
|
195 | assert_error(id_, expected, given=response.body) | |
193 |
|
196 | |||
194 | @pytest.mark.backends("git", "hg") |
|
197 | @pytest.mark.backends("git", "hg") | |
195 | def test_api_comment_pull_request_unknown_status_error(self, pr_util): |
|
198 | def test_api_comment_pull_request_unknown_status_error(self, pr_util): | |
196 | pull_request = pr_util.create_pull_request() |
|
199 | pull_request = pr_util.create_pull_request() | |
197 | pull_request_id = pull_request.pull_request_id |
|
200 | pull_request_id = pull_request.pull_request_id | |
198 | pull_request_repo = pull_request.target_repo.repo_name |
|
201 | pull_request_repo = pull_request.target_repo.repo_name | |
199 | id_, params = build_data( |
|
202 | id_, params = build_data( | |
200 | self.apikey, 'comment_pull_request', |
|
203 | self.apikey, 'comment_pull_request', | |
201 | repoid=pull_request_repo, |
|
204 | repoid=pull_request_repo, | |
202 | pullrequestid=pull_request_id, |
|
205 | pullrequestid=pull_request_id, | |
203 | status='42') |
|
206 | status='42') | |
204 | response = api_call(self.app, params) |
|
207 | response = api_call(self.app, params) | |
205 |
|
208 | |||
206 | expected = 'Unknown comment status: `42`' |
|
209 | expected = 'Unknown comment status: `42`' | |
207 | assert_error(id_, expected, given=response.body) |
|
210 | assert_error(id_, expected, given=response.body) | |
208 |
|
211 | |||
209 | @pytest.mark.backends("git", "hg") |
|
212 | @pytest.mark.backends("git", "hg") | |
210 | def test_api_comment_pull_request_repo_error(self, pr_util): |
|
213 | def test_api_comment_pull_request_repo_error(self, pr_util): | |
211 | pull_request = pr_util.create_pull_request() |
|
214 | pull_request = pr_util.create_pull_request() | |
212 | id_, params = build_data( |
|
215 | id_, params = build_data( | |
213 | self.apikey, 'comment_pull_request', |
|
216 | self.apikey, 'comment_pull_request', | |
214 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
217 | repoid=666, pullrequestid=pull_request.pull_request_id) | |
215 | response = api_call(self.app, params) |
|
218 | response = api_call(self.app, params) | |
216 |
|
219 | |||
217 | expected = 'repository `666` does not exist' |
|
220 | expected = 'repository `666` does not exist' | |
218 | assert_error(id_, expected, given=response.body) |
|
221 | assert_error(id_, expected, given=response.body) | |
219 |
|
222 | |||
220 | @pytest.mark.backends("git", "hg") |
|
223 | @pytest.mark.backends("git", "hg") | |
221 | def test_api_comment_pull_request_non_admin_with_userid_error(self, pr_util): |
|
224 | def test_api_comment_pull_request_non_admin_with_userid_error(self, pr_util): | |
222 | pull_request = pr_util.create_pull_request() |
|
225 | pull_request = pr_util.create_pull_request() | |
223 | id_, params = build_data( |
|
226 | id_, params = build_data( | |
224 | self.apikey_regular, 'comment_pull_request', |
|
227 | self.apikey_regular, 'comment_pull_request', | |
225 | repoid=pull_request.target_repo.repo_name, |
|
228 | repoid=pull_request.target_repo.repo_name, | |
226 | pullrequestid=pull_request.pull_request_id, |
|
229 | pullrequestid=pull_request.pull_request_id, | |
227 | userid=TEST_USER_ADMIN_LOGIN) |
|
230 | userid=TEST_USER_ADMIN_LOGIN) | |
228 | response = api_call(self.app, params) |
|
231 | response = api_call(self.app, params) | |
229 |
|
232 | |||
230 | expected = 'userid is not the same as your user' |
|
233 | expected = 'userid is not the same as your user' | |
231 | assert_error(id_, expected, given=response.body) |
|
234 | assert_error(id_, expected, given=response.body) | |
232 |
|
235 | |||
233 | @pytest.mark.backends("git", "hg") |
|
236 | @pytest.mark.backends("git", "hg") | |
234 | def test_api_comment_pull_request_non_admin_with_userid_error(self, pr_util): |
|
|||
235 | pull_request = pr_util.create_pull_request() |
|
|||
236 | id_, params = build_data( |
|
|||
237 | self.apikey_regular, 'comment_pull_request', |
|
|||
238 | repoid=pull_request.target_repo.repo_name, |
|
|||
239 | pullrequestid=pull_request.pull_request_id, |
|
|||
240 | userid=TEST_USER_ADMIN_LOGIN) |
|
|||
241 | response = api_call(self.app, params) |
|
|||
242 |
|
||||
243 | expected = 'userid is not the same as your user' |
|
|||
244 | assert_error(id_, expected, given=response.body) |
|
|||
245 |
|
||||
246 | @pytest.mark.backends("git", "hg") |
|
|||
247 | def test_api_comment_pull_request_wrong_commit_id_error(self, pr_util): |
|
237 | def test_api_comment_pull_request_wrong_commit_id_error(self, pr_util): | |
248 | pull_request = pr_util.create_pull_request() |
|
238 | pull_request = pr_util.create_pull_request() | |
249 | id_, params = build_data( |
|
239 | id_, params = build_data( | |
250 | self.apikey_regular, 'comment_pull_request', |
|
240 | self.apikey_regular, 'comment_pull_request', | |
251 | repoid=pull_request.target_repo.repo_name, |
|
241 | repoid=pull_request.target_repo.repo_name, | |
252 | status='approved', |
|
242 | status='approved', | |
253 | pullrequestid=pull_request.pull_request_id, |
|
243 | pullrequestid=pull_request.pull_request_id, | |
254 | commit_id='XXX') |
|
244 | commit_id='XXX') | |
255 | response = api_call(self.app, params) |
|
245 | response = api_call(self.app, params) | |
256 |
|
246 | |||
257 | expected = 'Invalid commit_id `XXX` for this pull request.' |
|
247 | expected = 'Invalid commit_id `XXX` for this pull request.' | |
258 | assert_error(id_, expected, given=response.body) |
|
248 | assert_error(id_, expected, given=response.body) | |
259 |
|
249 | |||
260 | @pytest.mark.backends("git", "hg") |
|
250 | @pytest.mark.backends("git", "hg") | |
261 | def test_api_edit_comment(self, pr_util): |
|
251 | def test_api_edit_comment(self, pr_util): | |
262 | pull_request = pr_util.create_pull_request() |
|
252 | pull_request = pr_util.create_pull_request() | |
263 |
|
253 | |||
264 | id_, params = build_data( |
|
254 | id_, params = build_data( | |
265 | self.apikey, |
|
255 | self.apikey, | |
266 | 'comment_pull_request', |
|
256 | 'comment_pull_request', | |
267 | repoid=pull_request.target_repo.repo_name, |
|
257 | repoid=pull_request.target_repo.repo_name, | |
268 | pullrequestid=pull_request.pull_request_id, |
|
258 | pullrequestid=pull_request.pull_request_id, | |
269 | message='test message', |
|
259 | message='test message', | |
270 | ) |
|
260 | ) | |
271 | response = api_call(self.app, params) |
|
261 | response = api_call(self.app, params) | |
272 | json_response = response.json |
|
262 | json_response = response.json | |
273 | comment_id = json_response['result']['comment_id'] |
|
263 | comment_id = json_response['result']['comment_id'] | |
274 |
|
264 | |||
275 | message_after_edit = 'just message' |
|
265 | message_after_edit = 'just message' | |
276 | id_, params = build_data( |
|
266 | id_, params = build_data( | |
277 | self.apikey, |
|
267 | self.apikey, | |
278 | 'edit_comment', |
|
268 | 'edit_comment', | |
279 | comment_id=comment_id, |
|
269 | comment_id=comment_id, | |
280 | message=message_after_edit, |
|
270 | message=message_after_edit, | |
281 | version=0, |
|
271 | version=0, | |
282 | ) |
|
272 | ) | |
283 | response = api_call(self.app, params) |
|
273 | response = api_call(self.app, params) | |
284 | json_response = response.json |
|
274 | json_response = response.json | |
285 | assert json_response['result']['version'] == 1 |
|
275 | assert json_response['result']['version'] == 1 | |
286 |
|
276 | |||
287 | text_form_db = ChangesetComment.get(comment_id).text |
|
277 | text_form_db = ChangesetComment.get(comment_id).text | |
288 | assert message_after_edit == text_form_db |
|
278 | assert message_after_edit == text_form_db | |
289 |
|
279 | |||
290 | @pytest.mark.backends("git", "hg") |
|
280 | @pytest.mark.backends("git", "hg") | |
291 | def test_api_edit_comment_wrong_version(self, pr_util): |
|
281 | def test_api_edit_comment_wrong_version_mismatch(self, pr_util): | |
292 | pull_request = pr_util.create_pull_request() |
|
282 | pull_request = pr_util.create_pull_request() | |
293 |
|
283 | |||
294 | id_, params = build_data( |
|
284 | id_, params = build_data( | |
295 | self.apikey, 'comment_pull_request', |
|
285 | self.apikey, 'comment_pull_request', | |
296 | repoid=pull_request.target_repo.repo_name, |
|
286 | repoid=pull_request.target_repo.repo_name, | |
297 | pullrequestid=pull_request.pull_request_id, |
|
287 | pullrequestid=pull_request.pull_request_id, | |
298 | message='test message') |
|
288 | message='test message') | |
299 | response = api_call(self.app, params) |
|
289 | response = api_call(self.app, params) | |
300 | json_response = response.json |
|
290 | json_response = response.json | |
301 | comment_id = json_response['result']['comment_id'] |
|
291 | comment_id = json_response['result']['comment_id'] | |
302 |
|
292 | |||
303 | message_after_edit = 'just message' |
|
293 | message_after_edit = 'just message' | |
304 | id_, params = build_data( |
|
294 | id_, params = build_data( | |
305 |
self.apikey |
|
295 | self.apikey, | |
306 | 'edit_comment', |
|
296 | 'edit_comment', | |
307 | comment_id=comment_id, |
|
297 | comment_id=comment_id, | |
308 | message=message_after_edit, |
|
298 | message=message_after_edit, | |
309 | version=1, |
|
299 | version=1, | |
310 | ) |
|
300 | ) | |
311 | response = api_call(self.app, params) |
|
301 | response = api_call(self.app, params) | |
312 | expected = 'comment ({}) version ({}) mismatch'.format(comment_id, 1) |
|
302 | expected = 'comment ({}) version ({}) mismatch'.format(comment_id, 1) | |
313 | assert_error(id_, expected, given=response.body) |
|
303 | assert_error(id_, expected, given=response.body) | |
314 |
|
304 | |||
315 | @pytest.mark.backends("git", "hg") |
|
305 | @pytest.mark.backends("git", "hg") | |
316 | def test_api_edit_comment_wrong_version(self, pr_util): |
|
306 | def test_api_edit_comment_wrong_version(self, pr_util): | |
317 | pull_request = pr_util.create_pull_request() |
|
307 | pull_request = pr_util.create_pull_request() | |
318 |
|
308 | |||
319 | id_, params = build_data( |
|
309 | id_, params = build_data( | |
320 | self.apikey, 'comment_pull_request', |
|
310 | self.apikey, 'comment_pull_request', | |
321 | repoid=pull_request.target_repo.repo_name, |
|
311 | repoid=pull_request.target_repo.repo_name, | |
322 | pullrequestid=pull_request.pull_request_id, |
|
312 | pullrequestid=pull_request.pull_request_id, | |
323 | message='test message') |
|
313 | message='test message') | |
324 | response = api_call(self.app, params) |
|
314 | response = api_call(self.app, params) | |
325 | json_response = response.json |
|
315 | json_response = response.json | |
326 | comment_id = json_response['result']['comment_id'] |
|
316 | comment_id = json_response['result']['comment_id'] | |
327 |
|
317 | |||
328 | id_, params = build_data( |
|
318 | id_, params = build_data( | |
329 | self.apikey, |
|
319 | self.apikey, | |
330 | 'edit_comment', |
|
320 | 'edit_comment', | |
331 | comment_id=comment_id, |
|
321 | comment_id=comment_id, | |
332 | message='', |
|
322 | message='', | |
333 | version=0, |
|
323 | version=0, | |
334 | ) |
|
324 | ) | |
335 | response = api_call(self.app, params) |
|
325 | response = api_call(self.app, params) | |
336 |
expected = "comment ({}) can't be changed with empty string" |
|
326 | expected = f"comment ({comment_id}) can't be changed with empty string" | |
337 | assert_error(id_, expected, given=response.body) |
|
327 | assert_error(id_, expected, given=response.body) | |
338 |
|
328 | |||
339 | @pytest.mark.backends("git", "hg") |
|
329 | @pytest.mark.backends("git", "hg") | |
340 | def test_api_edit_comment_wrong_user_set_by_non_admin(self, pr_util): |
|
330 | def test_api_edit_comment_wrong_user_set_by_non_admin(self, pr_util): | |
341 | pull_request = pr_util.create_pull_request() |
|
331 | pull_request = pr_util.create_pull_request() | |
342 | pull_request_id = pull_request.pull_request_id |
|
332 | pull_request_id = pull_request.pull_request_id | |
343 | id_, params = build_data( |
|
333 | id_, params = build_data( | |
344 | self.apikey, |
|
334 | self.apikey, | |
345 | 'comment_pull_request', |
|
335 | 'comment_pull_request', | |
346 | repoid=pull_request.target_repo.repo_name, |
|
336 | repoid=pull_request.target_repo.repo_name, | |
347 | pullrequestid=pull_request_id, |
|
337 | pullrequestid=pull_request_id, | |
348 | message='test message' |
|
338 | message='test message' | |
349 | ) |
|
339 | ) | |
350 | response = api_call(self.app, params) |
|
340 | response = api_call(self.app, params) | |
351 | json_response = response.json |
|
341 | json_response = response.json | |
352 | comment_id = json_response['result']['comment_id'] |
|
342 | comment_id = json_response['result']['comment_id'] | |
353 |
|
343 | |||
354 | id_, params = build_data( |
|
344 | id_, params = build_data( | |
355 | self.apikey_regular, |
|
345 | self.apikey_regular, | |
356 | 'edit_comment', |
|
346 | 'edit_comment', | |
357 | comment_id=comment_id, |
|
347 | comment_id=comment_id, | |
358 | message='just message', |
|
348 | message='just message', | |
359 | version=0, |
|
349 | version=0, | |
360 | userid=TEST_USER_ADMIN_LOGIN |
|
350 | userid=TEST_USER_ADMIN_LOGIN | |
361 | ) |
|
351 | ) | |
362 | response = api_call(self.app, params) |
|
352 | response = api_call(self.app, params) | |
363 | expected = 'userid is not the same as your user' |
|
353 | expected = 'userid is not the same as your user' | |
364 | assert_error(id_, expected, given=response.body) |
|
354 | assert_error(id_, expected, given=response.body) | |
365 |
|
355 | |||
366 | @pytest.mark.backends("git", "hg") |
|
356 | @pytest.mark.backends("git", "hg") | |
367 | def test_api_edit_comment_wrong_user_with_permissions_to_edit_comment(self, pr_util): |
|
357 | def test_api_edit_comment_wrong_user_with_permissions_to_edit_comment(self, pr_util): | |
368 | pull_request = pr_util.create_pull_request() |
|
358 | pull_request = pr_util.create_pull_request() | |
369 | pull_request_id = pull_request.pull_request_id |
|
359 | pull_request_id = pull_request.pull_request_id | |
370 | id_, params = build_data( |
|
360 | id_, params = build_data( | |
371 | self.apikey, |
|
361 | self.apikey, | |
372 | 'comment_pull_request', |
|
362 | 'comment_pull_request', | |
373 | repoid=pull_request.target_repo.repo_name, |
|
363 | repoid=pull_request.target_repo.repo_name, | |
374 | pullrequestid=pull_request_id, |
|
364 | pullrequestid=pull_request_id, | |
375 | message='test message' |
|
365 | message='test message' | |
376 | ) |
|
366 | ) | |
377 | response = api_call(self.app, params) |
|
367 | response = api_call(self.app, params) | |
378 | json_response = response.json |
|
368 | json_response = response.json | |
379 | comment_id = json_response['result']['comment_id'] |
|
369 | comment_id = json_response['result']['comment_id'] | |
380 |
|
370 | |||
381 | id_, params = build_data( |
|
371 | id_, params = build_data( | |
382 | self.apikey_regular, |
|
372 | self.apikey_regular, | |
383 | 'edit_comment', |
|
373 | 'edit_comment', | |
384 | comment_id=comment_id, |
|
374 | comment_id=comment_id, | |
385 | message='just message', |
|
375 | message='just message', | |
386 | version=0, |
|
376 | version=0, | |
387 | ) |
|
377 | ) | |
388 | response = api_call(self.app, params) |
|
378 | response = api_call(self.app, params) | |
389 | expected = "you don't have access to edit this comment" |
|
379 | expected = "you don't have access to edit this comment" | |
390 | assert_error(id_, expected, given=response.body) |
|
380 | assert_error(id_, expected, given=response.body) |
@@ -1,102 +1,101 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.db import Gist |
|
23 | from rhodecode.model.db import Gist | |
25 | from rhodecode.model.gist import GistModel |
|
24 | from rhodecode.model.gist import GistModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok, crash) |
|
26 | build_data, api_call, assert_error, assert_ok, crash) | |
28 | from rhodecode.tests.fixture import Fixture |
|
27 | from rhodecode.tests.fixture import Fixture | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestApiCreateGist(object): |
|
31 | class TestApiCreateGist(object): | |
33 | @pytest.mark.parametrize("lifetime, gist_type, gist_acl_level", [ |
|
32 | @pytest.mark.parametrize("lifetime, gist_type, gist_acl_level", [ | |
34 | (10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC), |
|
33 | (10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC), | |
35 | (20, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PRIVATE), |
|
34 | (20, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PRIVATE), | |
36 | (40, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PUBLIC), |
|
35 | (40, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PUBLIC), | |
37 | (80, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PRIVATE), |
|
36 | (80, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PRIVATE), | |
38 | ]) |
|
37 | ]) | |
39 | def test_api_create_gist(self, lifetime, gist_type, gist_acl_level): |
|
38 | def test_api_create_gist(self, lifetime, gist_type, gist_acl_level): | |
40 | id_, params = build_data( |
|
39 | id_, params = build_data( | |
41 | self.apikey_regular, 'create_gist', |
|
40 | self.apikey_regular, 'create_gist', | |
42 | lifetime=lifetime, |
|
41 | lifetime=lifetime, | |
43 | description='foobar-gist', |
|
42 | description='foobar-gist', | |
44 | gist_type=gist_type, |
|
43 | gist_type=gist_type, | |
45 | acl_level=gist_acl_level, |
|
44 | acl_level=gist_acl_level, | |
46 | files={'foobar_ąć': {'content': 'foo'}}) |
|
45 | files={'foobar_ąć': {'content': 'foo'}}) | |
47 | response = api_call(self.app, params) |
|
46 | response = api_call(self.app, params) | |
48 | response_json = response.json |
|
47 | response_json = response.json | |
49 | gist = response_json['result']['gist'] |
|
48 | gist = response_json['result']['gist'] | |
50 | expected = { |
|
49 | expected = { | |
51 | 'gist': { |
|
50 | 'gist': { | |
52 | 'access_id': gist['access_id'], |
|
51 | 'access_id': gist['access_id'], | |
53 | 'created_on': gist['created_on'], |
|
52 | 'created_on': gist['created_on'], | |
54 | 'modified_at': gist['modified_at'], |
|
53 | 'modified_at': gist['modified_at'], | |
55 | 'description': 'foobar-gist', |
|
54 | 'description': 'foobar-gist', | |
56 | 'expires': gist['expires'], |
|
55 | 'expires': gist['expires'], | |
57 | 'gist_id': gist['gist_id'], |
|
56 | 'gist_id': gist['gist_id'], | |
58 | 'type': gist_type, |
|
57 | 'type': gist_type, | |
59 | 'url': gist['url'], |
|
58 | 'url': gist['url'], | |
60 | # content is empty since we don't show it here |
|
59 | # content is empty since we don't show it here | |
61 | 'content': None, |
|
60 | 'content': None, | |
62 | 'acl_level': gist_acl_level, |
|
61 | 'acl_level': gist_acl_level, | |
63 | }, |
|
62 | }, | |
64 | 'msg': 'created new gist' |
|
63 | 'msg': 'created new gist' | |
65 | } |
|
64 | } | |
66 | try: |
|
65 | try: | |
67 | assert_ok(id_, expected, given=response.body) |
|
66 | assert_ok(id_, expected, given=response.body) | |
68 | finally: |
|
67 | finally: | |
69 | Fixture().destroy_gists() |
|
68 | Fixture().destroy_gists() | |
70 |
|
69 | |||
71 | @pytest.mark.parametrize("expected, lifetime, gist_type, gist_acl_level, files", [ |
|
70 | @pytest.mark.parametrize("expected, lifetime, gist_type, gist_acl_level, files", [ | |
72 | ({'gist_type': '"ups" is not one of private, public'}, |
|
71 | ({'gist_type': '"ups" is not one of private, public'}, | |
73 | 10, 'ups', Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}), |
|
72 | 10, 'ups', Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}), | |
74 |
|
73 | |||
75 | ({'lifetime': '-120 is less than minimum value -1'}, |
|
74 | ({'lifetime': '-120 is less than minimum value -1'}, | |
76 | -120, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}), |
|
75 | -120, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}), | |
77 |
|
76 | |||
78 | ({'0.content': 'Required'}, |
|
77 | ({'0.content': 'Required'}, | |
79 | 10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'x': 'f'}}), |
|
78 | 10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'x': 'f'}}), | |
80 | ]) |
|
79 | ]) | |
81 | def test_api_try_create_gist( |
|
80 | def test_api_try_create_gist( | |
82 | self, expected, lifetime, gist_type, gist_acl_level, files): |
|
81 | self, expected, lifetime, gist_type, gist_acl_level, files): | |
83 | id_, params = build_data( |
|
82 | id_, params = build_data( | |
84 | self.apikey_regular, 'create_gist', |
|
83 | self.apikey_regular, 'create_gist', | |
85 | lifetime=lifetime, |
|
84 | lifetime=lifetime, | |
86 | description='foobar-gist', |
|
85 | description='foobar-gist', | |
87 | gist_type=gist_type, |
|
86 | gist_type=gist_type, | |
88 | acl_level=gist_acl_level, |
|
87 | acl_level=gist_acl_level, | |
89 | files=files) |
|
88 | files=files) | |
90 | response = api_call(self.app, params) |
|
89 | response = api_call(self.app, params) | |
91 |
|
90 | |||
92 | try: |
|
91 | try: | |
93 | assert_error(id_, expected, given=response.body) |
|
92 | assert_error(id_, expected, given=response.body) | |
94 | finally: |
|
93 | finally: | |
95 | Fixture().destroy_gists() |
|
94 | Fixture().destroy_gists() | |
96 |
|
95 | |||
97 | @mock.patch.object(GistModel, 'create', crash) |
|
96 | @mock.patch.object(GistModel, 'create', crash) | |
98 | def test_api_create_gist_exception_occurred(self): |
|
97 | def test_api_create_gist_exception_occurred(self): | |
99 | id_, params = build_data(self.apikey_regular, 'create_gist', files={}) |
|
98 | id_, params = build_data(self.apikey_regular, 'create_gist', files={}) | |
100 | response = api_call(self.app, params) |
|
99 | response = api_call(self.app, params) | |
101 | expected = 'failed to create gist' |
|
100 | expected = 'failed to create gist' | |
102 | assert_error(id_, expected, given=response.body) |
|
101 | assert_error(id_, expected, given=response.body) |
@@ -1,368 +1,367 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.db import User |
|
22 | from rhodecode.model.db import User | |
24 | from rhodecode.model.pull_request import PullRequestModel |
|
23 | from rhodecode.model.pull_request import PullRequestModel | |
25 | from rhodecode.model.repo import RepoModel |
|
24 | from rhodecode.model.repo import RepoModel | |
26 | from rhodecode.model.user import UserModel |
|
25 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN |
|
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN | |
28 | from rhodecode.api.tests.utils import build_data, api_call, assert_error |
|
27 | from rhodecode.api.tests.utils import build_data, api_call, assert_error | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestCreatePullRequestApi(object): |
|
31 | class TestCreatePullRequestApi(object): | |
33 | finalizers = [] |
|
32 | finalizers = [] | |
34 |
|
33 | |||
35 | def teardown_method(self, method): |
|
34 | def teardown_method(self, method): | |
36 | if self.finalizers: |
|
35 | if self.finalizers: | |
37 | for finalizer in self.finalizers: |
|
36 | for finalizer in self.finalizers: | |
38 | finalizer() |
|
37 | finalizer() | |
39 | self.finalizers = [] |
|
38 | self.finalizers = [] | |
40 |
|
39 | |||
41 | def test_create_with_wrong_data(self): |
|
40 | def test_create_with_wrong_data(self): | |
42 | required_data = { |
|
41 | required_data = { | |
43 | 'source_repo': 'tests/source_repo', |
|
42 | 'source_repo': 'tests/source_repo', | |
44 | 'target_repo': 'tests/target_repo', |
|
43 | 'target_repo': 'tests/target_repo', | |
45 | 'source_ref': 'branch:default:initial', |
|
44 | 'source_ref': 'branch:default:initial', | |
46 | 'target_ref': 'branch:default:new-feature', |
|
45 | 'target_ref': 'branch:default:new-feature', | |
47 | } |
|
46 | } | |
48 | for key in required_data: |
|
47 | for key in required_data: | |
49 | data = required_data.copy() |
|
48 | data = required_data.copy() | |
50 | data.pop(key) |
|
49 | data.pop(key) | |
51 | id_, params = build_data( |
|
50 | id_, params = build_data( | |
52 | self.apikey, 'create_pull_request', **data) |
|
51 | self.apikey, 'create_pull_request', **data) | |
53 | response = api_call(self.app, params) |
|
52 | response = api_call(self.app, params) | |
54 |
|
53 | |||
55 | expected = 'Missing non optional `{}` arg in JSON DATA'.format(key) |
|
54 | expected = 'Missing non optional `{}` arg in JSON DATA'.format(key) | |
56 | assert_error(id_, expected, given=response.body) |
|
55 | assert_error(id_, expected, given=response.body) | |
57 |
|
56 | |||
58 | @pytest.mark.backends("git", "hg") |
|
57 | @pytest.mark.backends("git", "hg") | |
59 | @pytest.mark.parametrize('source_ref', [ |
|
58 | @pytest.mark.parametrize('source_ref', [ | |
60 | 'bookmarg:default:initial' |
|
59 | 'bookmarg:default:initial' | |
61 | ]) |
|
60 | ]) | |
62 | def test_create_with_wrong_refs_data(self, backend, source_ref): |
|
61 | def test_create_with_wrong_refs_data(self, backend, source_ref): | |
63 |
|
62 | |||
64 | data = self._prepare_data(backend) |
|
63 | data = self._prepare_data(backend) | |
65 | data['source_ref'] = source_ref |
|
64 | data['source_ref'] = source_ref | |
66 |
|
65 | |||
67 | id_, params = build_data( |
|
66 | id_, params = build_data( | |
68 | self.apikey_regular, 'create_pull_request', **data) |
|
67 | self.apikey_regular, 'create_pull_request', **data) | |
69 |
|
68 | |||
70 | response = api_call(self.app, params) |
|
69 | response = api_call(self.app, params) | |
71 |
|
70 | |||
72 | expected = "Ref `{}` type is not allowed. " \ |
|
71 | expected = "Ref `{}` type is not allowed. " \ | |
73 | "Only:['bookmark', 'book', 'tag', 'branch'] " \ |
|
72 | "Only:['bookmark', 'book', 'tag', 'branch'] " \ | |
74 | "are possible.".format(source_ref) |
|
73 | "are possible.".format(source_ref) | |
75 | assert_error(id_, expected, given=response.body) |
|
74 | assert_error(id_, expected, given=response.body) | |
76 |
|
75 | |||
77 | @pytest.mark.backends("git", "hg") |
|
76 | @pytest.mark.backends("git", "hg") | |
78 | def test_create_with_correct_data(self, backend): |
|
77 | def test_create_with_correct_data(self, backend): | |
79 | data = self._prepare_data(backend) |
|
78 | data = self._prepare_data(backend) | |
80 | RepoModel().revoke_user_permission( |
|
79 | RepoModel().revoke_user_permission( | |
81 | self.source.repo_name, User.DEFAULT_USER) |
|
80 | self.source.repo_name, User.DEFAULT_USER) | |
82 | id_, params = build_data( |
|
81 | id_, params = build_data( | |
83 | self.apikey_regular, 'create_pull_request', **data) |
|
82 | self.apikey_regular, 'create_pull_request', **data) | |
84 | response = api_call(self.app, params) |
|
83 | response = api_call(self.app, params) | |
85 | expected_message = "Created new pull request `{title}`".format( |
|
84 | expected_message = "Created new pull request `{title}`".format( | |
86 | title=data['title']) |
|
85 | title=data['title']) | |
87 | result = response.json |
|
86 | result = response.json | |
88 | assert result['error'] is None |
|
87 | assert result['error'] is None | |
89 | assert result['result']['msg'] == expected_message |
|
88 | assert result['result']['msg'] == expected_message | |
90 | pull_request_id = result['result']['pull_request_id'] |
|
89 | pull_request_id = result['result']['pull_request_id'] | |
91 | pull_request = PullRequestModel().get(pull_request_id) |
|
90 | pull_request = PullRequestModel().get(pull_request_id) | |
92 | assert pull_request.title == data['title'] |
|
91 | assert pull_request.title == data['title'] | |
93 | assert pull_request.description == data['description'] |
|
92 | assert pull_request.description == data['description'] | |
94 | assert pull_request.source_ref == data['source_ref'] |
|
93 | assert pull_request.source_ref == data['source_ref'] | |
95 | assert pull_request.target_ref == data['target_ref'] |
|
94 | assert pull_request.target_ref == data['target_ref'] | |
96 | assert pull_request.source_repo.repo_name == data['source_repo'] |
|
95 | assert pull_request.source_repo.repo_name == data['source_repo'] | |
97 | assert pull_request.target_repo.repo_name == data['target_repo'] |
|
96 | assert pull_request.target_repo.repo_name == data['target_repo'] | |
98 | assert pull_request.revisions == [self.commit_ids['change']] |
|
97 | assert pull_request.revisions == [self.commit_ids['change']] | |
99 | assert len(pull_request.reviewers) == 1 |
|
98 | assert len(pull_request.reviewers) == 1 | |
100 |
|
99 | |||
101 | @pytest.mark.backends("git", "hg") |
|
100 | @pytest.mark.backends("git", "hg") | |
102 | def test_create_with_empty_description(self, backend): |
|
101 | def test_create_with_empty_description(self, backend): | |
103 | data = self._prepare_data(backend) |
|
102 | data = self._prepare_data(backend) | |
104 | data.pop('description') |
|
103 | data.pop('description') | |
105 | id_, params = build_data( |
|
104 | id_, params = build_data( | |
106 | self.apikey_regular, 'create_pull_request', **data) |
|
105 | self.apikey_regular, 'create_pull_request', **data) | |
107 | response = api_call(self.app, params) |
|
106 | response = api_call(self.app, params) | |
108 | expected_message = "Created new pull request `{title}`".format( |
|
107 | expected_message = "Created new pull request `{title}`".format( | |
109 | title=data['title']) |
|
108 | title=data['title']) | |
110 | result = response.json |
|
109 | result = response.json | |
111 | assert result['error'] is None |
|
110 | assert result['error'] is None | |
112 | assert result['result']['msg'] == expected_message |
|
111 | assert result['result']['msg'] == expected_message | |
113 | pull_request_id = result['result']['pull_request_id'] |
|
112 | pull_request_id = result['result']['pull_request_id'] | |
114 | pull_request = PullRequestModel().get(pull_request_id) |
|
113 | pull_request = PullRequestModel().get(pull_request_id) | |
115 | assert pull_request.description == '' |
|
114 | assert pull_request.description == '' | |
116 |
|
115 | |||
117 | @pytest.mark.backends("git", "hg") |
|
116 | @pytest.mark.backends("git", "hg") | |
118 | def test_create_with_empty_title(self, backend): |
|
117 | def test_create_with_empty_title(self, backend): | |
119 | data = self._prepare_data(backend) |
|
118 | data = self._prepare_data(backend) | |
120 | data.pop('title') |
|
119 | data.pop('title') | |
121 | id_, params = build_data( |
|
120 | id_, params = build_data( | |
122 | self.apikey_regular, 'create_pull_request', **data) |
|
121 | self.apikey_regular, 'create_pull_request', **data) | |
123 | response = api_call(self.app, params) |
|
122 | response = api_call(self.app, params) | |
124 | result = response.json |
|
123 | result = response.json | |
125 | pull_request_id = result['result']['pull_request_id'] |
|
124 | pull_request_id = result['result']['pull_request_id'] | |
126 | pull_request = PullRequestModel().get(pull_request_id) |
|
125 | pull_request = PullRequestModel().get(pull_request_id) | |
127 | data['ref'] = backend.default_branch_name |
|
126 | data['ref'] = backend.default_branch_name | |
128 | title = '{source_repo}#{ref} to {target_repo}'.format(**data) |
|
127 | title = '{source_repo}#{ref} to {target_repo}'.format(**data) | |
129 | assert pull_request.title == title |
|
128 | assert pull_request.title == title | |
130 |
|
129 | |||
131 | @pytest.mark.backends("git", "hg") |
|
130 | @pytest.mark.backends("git", "hg") | |
132 | def test_create_with_reviewers_specified_by_names( |
|
131 | def test_create_with_reviewers_specified_by_names( | |
133 | self, backend, no_notifications): |
|
132 | self, backend, no_notifications): | |
134 | data = self._prepare_data(backend) |
|
133 | data = self._prepare_data(backend) | |
135 | reviewers = [ |
|
134 | reviewers = [ | |
136 | {'username': TEST_USER_REGULAR_LOGIN, |
|
135 | {'username': TEST_USER_REGULAR_LOGIN, | |
137 | 'reasons': ['{} added manually'.format(TEST_USER_REGULAR_LOGIN)]}, |
|
136 | 'reasons': ['{} added manually'.format(TEST_USER_REGULAR_LOGIN)]}, | |
138 | {'username': TEST_USER_ADMIN_LOGIN, |
|
137 | {'username': TEST_USER_ADMIN_LOGIN, | |
139 | 'reasons': ['{} added manually'.format(TEST_USER_ADMIN_LOGIN)], |
|
138 | 'reasons': ['{} added manually'.format(TEST_USER_ADMIN_LOGIN)], | |
140 | 'mandatory': True}, |
|
139 | 'mandatory': True}, | |
141 | ] |
|
140 | ] | |
142 | data['reviewers'] = reviewers |
|
141 | data['reviewers'] = reviewers | |
143 |
|
142 | |||
144 | id_, params = build_data( |
|
143 | id_, params = build_data( | |
145 | self.apikey_regular, 'create_pull_request', **data) |
|
144 | self.apikey_regular, 'create_pull_request', **data) | |
146 | response = api_call(self.app, params) |
|
145 | response = api_call(self.app, params) | |
147 |
|
146 | |||
148 | expected_message = "Created new pull request `{title}`".format( |
|
147 | expected_message = "Created new pull request `{title}`".format( | |
149 | title=data['title']) |
|
148 | title=data['title']) | |
150 | result = response.json |
|
149 | result = response.json | |
151 | assert result['error'] is None |
|
150 | assert result['error'] is None | |
152 | assert result['result']['msg'] == expected_message |
|
151 | assert result['result']['msg'] == expected_message | |
153 | pull_request_id = result['result']['pull_request_id'] |
|
152 | pull_request_id = result['result']['pull_request_id'] | |
154 | pull_request = PullRequestModel().get(pull_request_id) |
|
153 | pull_request = PullRequestModel().get(pull_request_id) | |
155 |
|
154 | |||
156 | actual_reviewers = [] |
|
155 | actual_reviewers = [] | |
157 | for rev in pull_request.reviewers: |
|
156 | for rev in pull_request.reviewers: | |
158 | entry = { |
|
157 | entry = { | |
159 | 'username': rev.user.username, |
|
158 | 'username': rev.user.username, | |
160 | 'reasons': rev.reasons, |
|
159 | 'reasons': rev.reasons, | |
161 | } |
|
160 | } | |
162 | if rev.mandatory: |
|
161 | if rev.mandatory: | |
163 | entry['mandatory'] = rev.mandatory |
|
162 | entry['mandatory'] = rev.mandatory | |
164 | actual_reviewers.append(entry) |
|
163 | actual_reviewers.append(entry) | |
165 |
|
164 | |||
166 | owner_username = pull_request.target_repo.user.username |
|
165 | owner_username = pull_request.target_repo.user.username | |
167 | for spec_reviewer in reviewers[::]: |
|
166 | for spec_reviewer in reviewers[::]: | |
168 | # default reviewer will be added who is an owner of the repo |
|
167 | # default reviewer will be added who is an owner of the repo | |
169 | # this get's overridden by a add owner to reviewers rule |
|
168 | # this get's overridden by a add owner to reviewers rule | |
170 | if spec_reviewer['username'] == owner_username: |
|
169 | if spec_reviewer['username'] == owner_username: | |
171 | spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner'] |
|
170 | spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner'] | |
172 | # since owner is more important, we don't inherit mandatory flag |
|
171 | # since owner is more important, we don't inherit mandatory flag | |
173 | del spec_reviewer['mandatory'] |
|
172 | del spec_reviewer['mandatory'] | |
174 |
|
173 | |||
175 | assert sorted(actual_reviewers, key=lambda e: e['username']) \ |
|
174 | assert sorted(actual_reviewers, key=lambda e: e['username']) \ | |
176 | == sorted(reviewers, key=lambda e: e['username']) |
|
175 | == sorted(reviewers, key=lambda e: e['username']) | |
177 |
|
176 | |||
178 | @pytest.mark.backends("git", "hg") |
|
177 | @pytest.mark.backends("git", "hg") | |
179 | def test_create_with_reviewers_specified_by_ids( |
|
178 | def test_create_with_reviewers_specified_by_ids( | |
180 | self, backend, no_notifications): |
|
179 | self, backend, no_notifications): | |
181 | data = self._prepare_data(backend) |
|
180 | data = self._prepare_data(backend) | |
182 | reviewers = [ |
|
181 | reviewers = [ | |
183 | {'username': UserModel().get_by_username( |
|
182 | {'username': UserModel().get_by_username( | |
184 | TEST_USER_REGULAR_LOGIN).user_id, |
|
183 | TEST_USER_REGULAR_LOGIN).user_id, | |
185 | 'reasons': ['added manually']}, |
|
184 | 'reasons': ['added manually']}, | |
186 | {'username': UserModel().get_by_username( |
|
185 | {'username': UserModel().get_by_username( | |
187 | TEST_USER_ADMIN_LOGIN).user_id, |
|
186 | TEST_USER_ADMIN_LOGIN).user_id, | |
188 | 'reasons': ['added manually']}, |
|
187 | 'reasons': ['added manually']}, | |
189 | ] |
|
188 | ] | |
190 |
|
189 | |||
191 | data['reviewers'] = reviewers |
|
190 | data['reviewers'] = reviewers | |
192 | id_, params = build_data( |
|
191 | id_, params = build_data( | |
193 | self.apikey_regular, 'create_pull_request', **data) |
|
192 | self.apikey_regular, 'create_pull_request', **data) | |
194 | response = api_call(self.app, params) |
|
193 | response = api_call(self.app, params) | |
195 |
|
194 | |||
196 | expected_message = "Created new pull request `{title}`".format( |
|
195 | expected_message = "Created new pull request `{title}`".format( | |
197 | title=data['title']) |
|
196 | title=data['title']) | |
198 | result = response.json |
|
197 | result = response.json | |
199 | assert result['error'] is None |
|
198 | assert result['error'] is None | |
200 | assert result['result']['msg'] == expected_message |
|
199 | assert result['result']['msg'] == expected_message | |
201 | pull_request_id = result['result']['pull_request_id'] |
|
200 | pull_request_id = result['result']['pull_request_id'] | |
202 | pull_request = PullRequestModel().get(pull_request_id) |
|
201 | pull_request = PullRequestModel().get(pull_request_id) | |
203 |
|
202 | |||
204 | actual_reviewers = [] |
|
203 | actual_reviewers = [] | |
205 | for rev in pull_request.reviewers: |
|
204 | for rev in pull_request.reviewers: | |
206 | entry = { |
|
205 | entry = { | |
207 | 'username': rev.user.user_id, |
|
206 | 'username': rev.user.user_id, | |
208 | 'reasons': rev.reasons, |
|
207 | 'reasons': rev.reasons, | |
209 | } |
|
208 | } | |
210 | if rev.mandatory: |
|
209 | if rev.mandatory: | |
211 | entry['mandatory'] = rev.mandatory |
|
210 | entry['mandatory'] = rev.mandatory | |
212 | actual_reviewers.append(entry) |
|
211 | actual_reviewers.append(entry) | |
213 |
|
212 | |||
214 | owner_user_id = pull_request.target_repo.user.user_id |
|
213 | owner_user_id = pull_request.target_repo.user.user_id | |
215 | for spec_reviewer in reviewers[::]: |
|
214 | for spec_reviewer in reviewers[::]: | |
216 | # default reviewer will be added who is an owner of the repo |
|
215 | # default reviewer will be added who is an owner of the repo | |
217 | # this get's overridden by a add owner to reviewers rule |
|
216 | # this get's overridden by a add owner to reviewers rule | |
218 | if spec_reviewer['username'] == owner_user_id: |
|
217 | if spec_reviewer['username'] == owner_user_id: | |
219 | spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner'] |
|
218 | spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner'] | |
220 |
|
219 | |||
221 | assert sorted(actual_reviewers, key=lambda e: e['username']) \ |
|
220 | assert sorted(actual_reviewers, key=lambda e: e['username']) \ | |
222 | == sorted(reviewers, key=lambda e: e['username']) |
|
221 | == sorted(reviewers, key=lambda e: e['username']) | |
223 |
|
222 | |||
224 | @pytest.mark.backends("git", "hg") |
|
223 | @pytest.mark.backends("git", "hg") | |
225 | def test_create_fails_when_the_reviewer_is_not_found(self, backend): |
|
224 | def test_create_fails_when_the_reviewer_is_not_found(self, backend): | |
226 | data = self._prepare_data(backend) |
|
225 | data = self._prepare_data(backend) | |
227 | data['reviewers'] = [{'username': 'somebody'}] |
|
226 | data['reviewers'] = [{'username': 'somebody'}] | |
228 | id_, params = build_data( |
|
227 | id_, params = build_data( | |
229 | self.apikey_regular, 'create_pull_request', **data) |
|
228 | self.apikey_regular, 'create_pull_request', **data) | |
230 | response = api_call(self.app, params) |
|
229 | response = api_call(self.app, params) | |
231 | expected_message = 'user `somebody` does not exist' |
|
230 | expected_message = 'user `somebody` does not exist' | |
232 | assert_error(id_, expected_message, given=response.body) |
|
231 | assert_error(id_, expected_message, given=response.body) | |
233 |
|
232 | |||
234 | @pytest.mark.backends("git", "hg") |
|
233 | @pytest.mark.backends("git", "hg") | |
235 | def test_cannot_create_with_reviewers_in_wrong_format(self, backend): |
|
234 | def test_cannot_create_with_reviewers_in_wrong_format(self, backend): | |
236 | data = self._prepare_data(backend) |
|
235 | data = self._prepare_data(backend) | |
237 | reviewers = ','.join([TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN]) |
|
236 | reviewers = ','.join([TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN]) | |
238 | data['reviewers'] = reviewers |
|
237 | data['reviewers'] = reviewers | |
239 | id_, params = build_data( |
|
238 | id_, params = build_data( | |
240 | self.apikey_regular, 'create_pull_request', **data) |
|
239 | self.apikey_regular, 'create_pull_request', **data) | |
241 | response = api_call(self.app, params) |
|
240 | response = api_call(self.app, params) | |
242 | expected_message = {u'': '"test_regular,test_admin" is not iterable'} |
|
241 | expected_message = {u'': '"test_regular,test_admin" is not iterable'} | |
243 | assert_error(id_, expected_message, given=response.body) |
|
242 | assert_error(id_, expected_message, given=response.body) | |
244 |
|
243 | |||
245 | @pytest.mark.backends("git", "hg") |
|
244 | @pytest.mark.backends("git", "hg") | |
246 | def test_create_with_no_commit_hashes(self, backend): |
|
245 | def test_create_with_no_commit_hashes(self, backend): | |
247 | data = self._prepare_data(backend) |
|
246 | data = self._prepare_data(backend) | |
248 | expected_source_ref = data['source_ref'] |
|
247 | expected_source_ref = data['source_ref'] | |
249 | expected_target_ref = data['target_ref'] |
|
248 | expected_target_ref = data['target_ref'] | |
250 | data['source_ref'] = 'branch:{}'.format(backend.default_branch_name) |
|
249 | data['source_ref'] = 'branch:{}'.format(backend.default_branch_name) | |
251 | data['target_ref'] = 'branch:{}'.format(backend.default_branch_name) |
|
250 | data['target_ref'] = 'branch:{}'.format(backend.default_branch_name) | |
252 | id_, params = build_data( |
|
251 | id_, params = build_data( | |
253 | self.apikey_regular, 'create_pull_request', **data) |
|
252 | self.apikey_regular, 'create_pull_request', **data) | |
254 | response = api_call(self.app, params) |
|
253 | response = api_call(self.app, params) | |
255 | expected_message = "Created new pull request `{title}`".format( |
|
254 | expected_message = "Created new pull request `{title}`".format( | |
256 | title=data['title']) |
|
255 | title=data['title']) | |
257 | result = response.json |
|
256 | result = response.json | |
258 | assert result['result']['msg'] == expected_message |
|
257 | assert result['result']['msg'] == expected_message | |
259 | pull_request_id = result['result']['pull_request_id'] |
|
258 | pull_request_id = result['result']['pull_request_id'] | |
260 | pull_request = PullRequestModel().get(pull_request_id) |
|
259 | pull_request = PullRequestModel().get(pull_request_id) | |
261 | assert pull_request.source_ref == expected_source_ref |
|
260 | assert pull_request.source_ref == expected_source_ref | |
262 | assert pull_request.target_ref == expected_target_ref |
|
261 | assert pull_request.target_ref == expected_target_ref | |
263 |
|
262 | |||
264 | @pytest.mark.backends("git", "hg") |
|
263 | @pytest.mark.backends("git", "hg") | |
265 | @pytest.mark.parametrize("data_key", ["source_repo", "target_repo"]) |
|
264 | @pytest.mark.parametrize("data_key", ["source_repo", "target_repo"]) | |
266 | def test_create_fails_with_wrong_repo(self, backend, data_key): |
|
265 | def test_create_fails_with_wrong_repo(self, backend, data_key): | |
267 | repo_name = 'fake-repo' |
|
266 | repo_name = 'fake-repo' | |
268 | data = self._prepare_data(backend) |
|
267 | data = self._prepare_data(backend) | |
269 | data[data_key] = repo_name |
|
268 | data[data_key] = repo_name | |
270 | id_, params = build_data( |
|
269 | id_, params = build_data( | |
271 | self.apikey_regular, 'create_pull_request', **data) |
|
270 | self.apikey_regular, 'create_pull_request', **data) | |
272 | response = api_call(self.app, params) |
|
271 | response = api_call(self.app, params) | |
273 | expected_message = 'repository `{}` does not exist'.format(repo_name) |
|
272 | expected_message = 'repository `{}` does not exist'.format(repo_name) | |
274 | assert_error(id_, expected_message, given=response.body) |
|
273 | assert_error(id_, expected_message, given=response.body) | |
275 |
|
274 | |||
276 | @pytest.mark.backends("git", "hg") |
|
275 | @pytest.mark.backends("git", "hg") | |
277 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) |
|
276 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) | |
278 | def test_create_fails_with_non_existing_branch(self, backend, data_key): |
|
277 | def test_create_fails_with_non_existing_branch(self, backend, data_key): | |
279 | branch_name = 'test-branch' |
|
278 | branch_name = 'test-branch' | |
280 | data = self._prepare_data(backend) |
|
279 | data = self._prepare_data(backend) | |
281 | data[data_key] = "branch:{}".format(branch_name) |
|
280 | data[data_key] = "branch:{}".format(branch_name) | |
282 | id_, params = build_data( |
|
281 | id_, params = build_data( | |
283 | self.apikey_regular, 'create_pull_request', **data) |
|
282 | self.apikey_regular, 'create_pull_request', **data) | |
284 | response = api_call(self.app, params) |
|
283 | response = api_call(self.app, params) | |
285 | expected_message = 'The specified value:{type}:`{name}` ' \ |
|
284 | expected_message = 'The specified value:{type}:`{name}` ' \ | |
286 | 'does not exist, or is not allowed.'.format(type='branch', |
|
285 | 'does not exist, or is not allowed.'.format(type='branch', | |
287 | name=branch_name) |
|
286 | name=branch_name) | |
288 | assert_error(id_, expected_message, given=response.body) |
|
287 | assert_error(id_, expected_message, given=response.body) | |
289 |
|
288 | |||
290 | @pytest.mark.backends("git", "hg") |
|
289 | @pytest.mark.backends("git", "hg") | |
291 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) |
|
290 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) | |
292 | def test_create_fails_with_ref_in_a_wrong_format(self, backend, data_key): |
|
291 | def test_create_fails_with_ref_in_a_wrong_format(self, backend, data_key): | |
293 | data = self._prepare_data(backend) |
|
292 | data = self._prepare_data(backend) | |
294 | ref = 'stange-ref' |
|
293 | ref = 'stange-ref' | |
295 | data[data_key] = ref |
|
294 | data[data_key] = ref | |
296 | id_, params = build_data( |
|
295 | id_, params = build_data( | |
297 | self.apikey_regular, 'create_pull_request', **data) |
|
296 | self.apikey_regular, 'create_pull_request', **data) | |
298 | response = api_call(self.app, params) |
|
297 | response = api_call(self.app, params) | |
299 | expected_message = ( |
|
298 | expected_message = ( | |
300 | 'Ref `{ref}` given in a wrong format. Please check the API' |
|
299 | 'Ref `{ref}` given in a wrong format. Please check the API' | |
301 | ' documentation for more details'.format(ref=ref)) |
|
300 | ' documentation for more details'.format(ref=ref)) | |
302 | assert_error(id_, expected_message, given=response.body) |
|
301 | assert_error(id_, expected_message, given=response.body) | |
303 |
|
302 | |||
304 | @pytest.mark.backends("git", "hg") |
|
303 | @pytest.mark.backends("git", "hg") | |
305 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) |
|
304 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) | |
306 | def test_create_fails_with_non_existing_ref(self, backend, data_key): |
|
305 | def test_create_fails_with_non_existing_ref(self, backend, data_key): | |
307 | commit_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
306 | commit_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' | |
308 | ref = self._get_full_ref(backend, commit_id) |
|
307 | ref = self._get_full_ref(backend, commit_id) | |
309 | data = self._prepare_data(backend) |
|
308 | data = self._prepare_data(backend) | |
310 | data[data_key] = ref |
|
309 | data[data_key] = ref | |
311 | id_, params = build_data( |
|
310 | id_, params = build_data( | |
312 | self.apikey_regular, 'create_pull_request', **data) |
|
311 | self.apikey_regular, 'create_pull_request', **data) | |
313 | response = api_call(self.app, params) |
|
312 | response = api_call(self.app, params) | |
314 | expected_message = 'Ref `{}` does not exist'.format(ref) |
|
313 | expected_message = 'Ref `{}` does not exist'.format(ref) | |
315 | assert_error(id_, expected_message, given=response.body) |
|
314 | assert_error(id_, expected_message, given=response.body) | |
316 |
|
315 | |||
317 | @pytest.mark.backends("git", "hg") |
|
316 | @pytest.mark.backends("git", "hg") | |
318 | def test_create_fails_when_no_revisions(self, backend): |
|
317 | def test_create_fails_when_no_revisions(self, backend): | |
319 | data = self._prepare_data(backend, source_head='initial') |
|
318 | data = self._prepare_data(backend, source_head='initial') | |
320 | id_, params = build_data( |
|
319 | id_, params = build_data( | |
321 | self.apikey_regular, 'create_pull_request', **data) |
|
320 | self.apikey_regular, 'create_pull_request', **data) | |
322 | response = api_call(self.app, params) |
|
321 | response = api_call(self.app, params) | |
323 | expected_message = 'no commits found for merge between specified references' |
|
322 | expected_message = 'no commits found for merge between specified references' | |
324 | assert_error(id_, expected_message, given=response.body) |
|
323 | assert_error(id_, expected_message, given=response.body) | |
325 |
|
324 | |||
326 | @pytest.mark.backends("git", "hg") |
|
325 | @pytest.mark.backends("git", "hg") | |
327 | def test_create_fails_when_no_permissions(self, backend): |
|
326 | def test_create_fails_when_no_permissions(self, backend): | |
328 | data = self._prepare_data(backend) |
|
327 | data = self._prepare_data(backend) | |
329 | RepoModel().revoke_user_permission( |
|
328 | RepoModel().revoke_user_permission( | |
330 | self.source.repo_name, self.test_user) |
|
329 | self.source.repo_name, self.test_user) | |
331 | RepoModel().revoke_user_permission( |
|
330 | RepoModel().revoke_user_permission( | |
332 | self.source.repo_name, User.DEFAULT_USER) |
|
331 | self.source.repo_name, User.DEFAULT_USER) | |
333 |
|
332 | |||
334 | id_, params = build_data( |
|
333 | id_, params = build_data( | |
335 | self.apikey_regular, 'create_pull_request', **data) |
|
334 | self.apikey_regular, 'create_pull_request', **data) | |
336 | response = api_call(self.app, params) |
|
335 | response = api_call(self.app, params) | |
337 | expected_message = 'repository `{}` does not exist'.format( |
|
336 | expected_message = 'repository `{}` does not exist'.format( | |
338 | self.source.repo_name) |
|
337 | self.source.repo_name) | |
339 | assert_error(id_, expected_message, given=response.body) |
|
338 | assert_error(id_, expected_message, given=response.body) | |
340 |
|
339 | |||
341 | def _prepare_data( |
|
340 | def _prepare_data( | |
342 | self, backend, source_head='change', target_head='initial'): |
|
341 | self, backend, source_head='change', target_head='initial'): | |
343 | commits = [ |
|
342 | commits = [ | |
344 | {'message': 'initial'}, |
|
343 | {'message': 'initial'}, | |
345 | {'message': 'change'}, |
|
344 | {'message': 'change'}, | |
346 | {'message': 'new-feature', 'parents': ['initial']}, |
|
345 | {'message': 'new-feature', 'parents': ['initial']}, | |
347 | ] |
|
346 | ] | |
348 | self.commit_ids = backend.create_master_repo(commits) |
|
347 | self.commit_ids = backend.create_master_repo(commits) | |
349 | self.source = backend.create_repo(heads=[source_head]) |
|
348 | self.source = backend.create_repo(heads=[source_head]) | |
350 | self.target = backend.create_repo(heads=[target_head]) |
|
349 | self.target = backend.create_repo(heads=[target_head]) | |
351 |
|
350 | |||
352 | data = { |
|
351 | data = { | |
353 | 'source_repo': self.source.repo_name, |
|
352 | 'source_repo': self.source.repo_name, | |
354 | 'target_repo': self.target.repo_name, |
|
353 | 'target_repo': self.target.repo_name, | |
355 | 'source_ref': self._get_full_ref( |
|
354 | 'source_ref': self._get_full_ref( | |
356 | backend, self.commit_ids[source_head]), |
|
355 | backend, self.commit_ids[source_head]), | |
357 | 'target_ref': self._get_full_ref( |
|
356 | 'target_ref': self._get_full_ref( | |
358 | backend, self.commit_ids[target_head]), |
|
357 | backend, self.commit_ids[target_head]), | |
359 | 'title': 'Test PR 1', |
|
358 | 'title': 'Test PR 1', | |
360 | 'description': 'Test' |
|
359 | 'description': 'Test' | |
361 | } |
|
360 | } | |
362 | RepoModel().grant_user_permission( |
|
361 | RepoModel().grant_user_permission( | |
363 | self.source.repo_name, self.TEST_USER_LOGIN, 'repository.read') |
|
362 | self.source.repo_name, self.TEST_USER_LOGIN, 'repository.read') | |
364 | return data |
|
363 | return data | |
365 |
|
364 | |||
366 | def _get_full_ref(self, backend, commit_id): |
|
365 | def _get_full_ref(self, backend, commit_id): | |
367 | return 'branch:{branch}:{commit_id}'.format( |
|
366 | return 'branch:{branch}:{commit_id}'.format( | |
368 | branch=backend.default_branch_name, commit_id=commit_id) |
|
367 | branch=backend.default_branch_name, commit_id=commit_id) |
@@ -1,350 +1,348 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import json |
|
|||
22 |
|
||||
23 | import mock |
|
20 | import mock | |
24 | import pytest |
|
21 | import pytest | |
25 |
|
22 | |||
26 | from rhodecode.lib.utils2 import safe_unicode |
|
|||
27 | from rhodecode.lib.vcs import settings |
|
23 | from rhodecode.lib.vcs import settings | |
28 | from rhodecode.model.meta import Session |
|
24 | from rhodecode.model.meta import Session | |
29 | from rhodecode.model.repo import RepoModel |
|
25 | from rhodecode.model.repo import RepoModel | |
30 | from rhodecode.model.user import UserModel |
|
26 | from rhodecode.model.user import UserModel | |
31 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
27 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
32 | from rhodecode.api.tests.utils import ( |
|
28 | from rhodecode.api.tests.utils import ( | |
33 | build_data, api_call, assert_ok, assert_error, crash) |
|
29 | build_data, api_call, assert_ok, assert_error, crash) | |
34 | from rhodecode.tests.fixture import Fixture |
|
30 | from rhodecode.tests.fixture import Fixture | |
|
31 | from rhodecode.lib.ext_json import json | |||
|
32 | from rhodecode.lib.str_utils import safe_str | |||
35 |
|
33 | |||
36 |
|
34 | |||
37 | fixture = Fixture() |
|
35 | fixture = Fixture() | |
38 |
|
36 | |||
39 |
|
37 | |||
40 | @pytest.mark.usefixtures("testuser_api", "app") |
|
38 | @pytest.mark.usefixtures("testuser_api", "app") | |
41 | class TestCreateRepo(object): |
|
39 | class TestCreateRepo(object): | |
42 |
|
40 | |||
43 | @pytest.mark.parametrize('given, expected_name, expected_exc', [ |
|
41 | @pytest.mark.parametrize('given, expected_name, expected_exc', [ | |
44 | ('api repo-1', 'api-repo-1', False), |
|
42 | ('api repo-1', 'api-repo-1', False), | |
45 | ('api-repo 1-ąć', 'api-repo-1-ąć', False), |
|
43 | ('api-repo 1-ąć', 'api-repo-1-ąć', False), | |
46 | (u'unicode-ąć', u'unicode-ąć', False), |
|
44 | (u'unicode-ąć', u'unicode-ąć', False), | |
47 | ('some repo v1.2', 'some-repo-v1.2', False), |
|
45 | ('some repo v1.2', 'some-repo-v1.2', False), | |
48 | ('v2.0', 'v2.0', False), |
|
46 | ('v2.0', 'v2.0', False), | |
49 | ]) |
|
47 | ]) | |
50 | def test_api_create_repo(self, backend, given, expected_name, expected_exc): |
|
48 | def test_api_create_repo(self, backend, given, expected_name, expected_exc): | |
51 |
|
49 | |||
52 | id_, params = build_data( |
|
50 | id_, params = build_data( | |
53 | self.apikey, |
|
51 | self.apikey, | |
54 | 'create_repo', |
|
52 | 'create_repo', | |
55 | repo_name=given, |
|
53 | repo_name=given, | |
56 | owner=TEST_USER_ADMIN_LOGIN, |
|
54 | owner=TEST_USER_ADMIN_LOGIN, | |
57 | repo_type=backend.alias, |
|
55 | repo_type=backend.alias, | |
58 | ) |
|
56 | ) | |
59 | response = api_call(self.app, params) |
|
57 | response = api_call(self.app, params) | |
60 |
|
58 | |||
61 | ret = { |
|
59 | ret = { | |
62 | 'msg': 'Created new repository `%s`' % (expected_name,), |
|
60 | 'msg': 'Created new repository `%s`' % (expected_name,), | |
63 | 'success': True, |
|
61 | 'success': True, | |
64 | 'task': None, |
|
62 | 'task': None, | |
65 | } |
|
63 | } | |
66 | expected = ret |
|
64 | expected = ret | |
67 | assert_ok(id_, expected, given=response.body) |
|
65 | assert_ok(id_, expected, given=response.body) | |
68 |
|
66 | |||
69 |
repo = RepoModel().get_by_repo_name(safe_ |
|
67 | repo = RepoModel().get_by_repo_name(safe_str(expected_name)) | |
70 | assert repo is not None |
|
68 | assert repo is not None | |
71 |
|
69 | |||
72 | id_, params = build_data(self.apikey, 'get_repo', repoid=expected_name) |
|
70 | id_, params = build_data(self.apikey, 'get_repo', repoid=expected_name) | |
73 | response = api_call(self.app, params) |
|
71 | response = api_call(self.app, params) | |
74 | body = json.loads(response.body) |
|
72 | body = json.loads(response.body) | |
75 |
|
73 | |||
76 | assert body['result']['enable_downloads'] is False |
|
74 | assert body['result']['enable_downloads'] is False | |
77 | assert body['result']['enable_locking'] is False |
|
75 | assert body['result']['enable_locking'] is False | |
78 | assert body['result']['enable_statistics'] is False |
|
76 | assert body['result']['enable_statistics'] is False | |
79 |
|
77 | |||
80 |
fixture.destroy_repo(safe_ |
|
78 | fixture.destroy_repo(safe_str(expected_name)) | |
81 |
|
79 | |||
82 | def test_api_create_restricted_repo_type(self, backend): |
|
80 | def test_api_create_restricted_repo_type(self, backend): | |
83 | repo_name = 'api-repo-type-{0}'.format(backend.alias) |
|
81 | repo_name = 'api-repo-type-{0}'.format(backend.alias) | |
84 | id_, params = build_data( |
|
82 | id_, params = build_data( | |
85 | self.apikey, |
|
83 | self.apikey, | |
86 | 'create_repo', |
|
84 | 'create_repo', | |
87 | repo_name=repo_name, |
|
85 | repo_name=repo_name, | |
88 | owner=TEST_USER_ADMIN_LOGIN, |
|
86 | owner=TEST_USER_ADMIN_LOGIN, | |
89 | repo_type=backend.alias, |
|
87 | repo_type=backend.alias, | |
90 | ) |
|
88 | ) | |
91 | git_backend = settings.BACKENDS['git'] |
|
89 | git_backend = settings.BACKENDS['git'] | |
92 | with mock.patch( |
|
90 | with mock.patch( | |
93 | 'rhodecode.lib.vcs.settings.BACKENDS', {'git': git_backend}): |
|
91 | 'rhodecode.lib.vcs.settings.BACKENDS', {'git': git_backend}): | |
94 | response = api_call(self.app, params) |
|
92 | response = api_call(self.app, params) | |
95 |
|
93 | |||
96 | repo = RepoModel().get_by_repo_name(repo_name) |
|
94 | repo = RepoModel().get_by_repo_name(repo_name) | |
97 |
|
95 | |||
98 | if backend.alias == 'git': |
|
96 | if backend.alias == 'git': | |
99 | assert repo is not None |
|
97 | assert repo is not None | |
100 | expected = { |
|
98 | expected = { | |
101 | 'msg': 'Created new repository `{0}`'.format(repo_name,), |
|
99 | 'msg': 'Created new repository `{0}`'.format(repo_name,), | |
102 | 'success': True, |
|
100 | 'success': True, | |
103 | 'task': None, |
|
101 | 'task': None, | |
104 | } |
|
102 | } | |
105 | assert_ok(id_, expected, given=response.body) |
|
103 | assert_ok(id_, expected, given=response.body) | |
106 | else: |
|
104 | else: | |
107 | assert repo is None |
|
105 | assert repo is None | |
108 |
|
106 | |||
109 | fixture.destroy_repo(repo_name) |
|
107 | fixture.destroy_repo(repo_name) | |
110 |
|
108 | |||
111 | def test_api_create_repo_with_booleans(self, backend): |
|
109 | def test_api_create_repo_with_booleans(self, backend): | |
112 | repo_name = 'api-repo-2' |
|
110 | repo_name = 'api-repo-2' | |
113 | id_, params = build_data( |
|
111 | id_, params = build_data( | |
114 | self.apikey, |
|
112 | self.apikey, | |
115 | 'create_repo', |
|
113 | 'create_repo', | |
116 | repo_name=repo_name, |
|
114 | repo_name=repo_name, | |
117 | owner=TEST_USER_ADMIN_LOGIN, |
|
115 | owner=TEST_USER_ADMIN_LOGIN, | |
118 | repo_type=backend.alias, |
|
116 | repo_type=backend.alias, | |
119 | enable_statistics=True, |
|
117 | enable_statistics=True, | |
120 | enable_locking=True, |
|
118 | enable_locking=True, | |
121 | enable_downloads=True |
|
119 | enable_downloads=True | |
122 | ) |
|
120 | ) | |
123 | response = api_call(self.app, params) |
|
121 | response = api_call(self.app, params) | |
124 |
|
122 | |||
125 | repo = RepoModel().get_by_repo_name(repo_name) |
|
123 | repo = RepoModel().get_by_repo_name(repo_name) | |
126 |
|
124 | |||
127 | assert repo is not None |
|
125 | assert repo is not None | |
128 | ret = { |
|
126 | ret = { | |
129 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
127 | 'msg': 'Created new repository `%s`' % (repo_name,), | |
130 | 'success': True, |
|
128 | 'success': True, | |
131 | 'task': None, |
|
129 | 'task': None, | |
132 | } |
|
130 | } | |
133 | expected = ret |
|
131 | expected = ret | |
134 | assert_ok(id_, expected, given=response.body) |
|
132 | assert_ok(id_, expected, given=response.body) | |
135 |
|
133 | |||
136 | id_, params = build_data(self.apikey, 'get_repo', repoid=repo_name) |
|
134 | id_, params = build_data(self.apikey, 'get_repo', repoid=repo_name) | |
137 | response = api_call(self.app, params) |
|
135 | response = api_call(self.app, params) | |
138 | body = json.loads(response.body) |
|
136 | body = json.loads(response.body) | |
139 |
|
137 | |||
140 | assert body['result']['enable_downloads'] is True |
|
138 | assert body['result']['enable_downloads'] is True | |
141 | assert body['result']['enable_locking'] is True |
|
139 | assert body['result']['enable_locking'] is True | |
142 | assert body['result']['enable_statistics'] is True |
|
140 | assert body['result']['enable_statistics'] is True | |
143 |
|
141 | |||
144 | fixture.destroy_repo(repo_name) |
|
142 | fixture.destroy_repo(repo_name) | |
145 |
|
143 | |||
146 | def test_api_create_repo_in_group(self, backend): |
|
144 | def test_api_create_repo_in_group(self, backend): | |
147 | repo_group_name = 'my_gr' |
|
145 | repo_group_name = 'my_gr' | |
148 | # create the parent |
|
146 | # create the parent | |
149 | fixture.create_repo_group(repo_group_name) |
|
147 | fixture.create_repo_group(repo_group_name) | |
150 |
|
148 | |||
151 | repo_name = '%s/api-repo-gr' % (repo_group_name,) |
|
149 | repo_name = '%s/api-repo-gr' % (repo_group_name,) | |
152 | id_, params = build_data( |
|
150 | id_, params = build_data( | |
153 | self.apikey, 'create_repo', |
|
151 | self.apikey, 'create_repo', | |
154 | repo_name=repo_name, |
|
152 | repo_name=repo_name, | |
155 | owner=TEST_USER_ADMIN_LOGIN, |
|
153 | owner=TEST_USER_ADMIN_LOGIN, | |
156 | repo_type=backend.alias,) |
|
154 | repo_type=backend.alias,) | |
157 | response = api_call(self.app, params) |
|
155 | response = api_call(self.app, params) | |
158 | repo = RepoModel().get_by_repo_name(repo_name) |
|
156 | repo = RepoModel().get_by_repo_name(repo_name) | |
159 | assert repo is not None |
|
157 | assert repo is not None | |
160 | assert repo.group is not None |
|
158 | assert repo.group is not None | |
161 |
|
159 | |||
162 | ret = { |
|
160 | ret = { | |
163 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
161 | 'msg': 'Created new repository `%s`' % (repo_name,), | |
164 | 'success': True, |
|
162 | 'success': True, | |
165 | 'task': None, |
|
163 | 'task': None, | |
166 | } |
|
164 | } | |
167 | expected = ret |
|
165 | expected = ret | |
168 | assert_ok(id_, expected, given=response.body) |
|
166 | assert_ok(id_, expected, given=response.body) | |
169 | fixture.destroy_repo(repo_name) |
|
167 | fixture.destroy_repo(repo_name) | |
170 | fixture.destroy_repo_group(repo_group_name) |
|
168 | fixture.destroy_repo_group(repo_group_name) | |
171 |
|
169 | |||
172 | def test_create_repo_in_group_that_doesnt_exist(self, backend, user_util): |
|
170 | def test_create_repo_in_group_that_doesnt_exist(self, backend, user_util): | |
173 | repo_group_name = 'fake_group' |
|
171 | repo_group_name = 'fake_group' | |
174 |
|
172 | |||
175 | repo_name = '%s/api-repo-gr' % (repo_group_name,) |
|
173 | repo_name = '%s/api-repo-gr' % (repo_group_name,) | |
176 | id_, params = build_data( |
|
174 | id_, params = build_data( | |
177 | self.apikey, 'create_repo', |
|
175 | self.apikey, 'create_repo', | |
178 | repo_name=repo_name, |
|
176 | repo_name=repo_name, | |
179 | owner=TEST_USER_ADMIN_LOGIN, |
|
177 | owner=TEST_USER_ADMIN_LOGIN, | |
180 | repo_type=backend.alias,) |
|
178 | repo_type=backend.alias,) | |
181 | response = api_call(self.app, params) |
|
179 | response = api_call(self.app, params) | |
182 |
|
180 | |||
183 | expected = {'repo_group': 'Repository group `{}` does not exist'.format( |
|
181 | expected = {'repo_group': 'Repository group `{}` does not exist'.format( | |
184 | repo_group_name)} |
|
182 | repo_group_name)} | |
185 | assert_error(id_, expected, given=response.body) |
|
183 | assert_error(id_, expected, given=response.body) | |
186 |
|
184 | |||
187 | def test_api_create_repo_unknown_owner(self, backend): |
|
185 | def test_api_create_repo_unknown_owner(self, backend): | |
188 | repo_name = 'api-repo-2' |
|
186 | repo_name = 'api-repo-2' | |
189 | owner = 'i-dont-exist' |
|
187 | owner = 'i-dont-exist' | |
190 | id_, params = build_data( |
|
188 | id_, params = build_data( | |
191 | self.apikey, 'create_repo', |
|
189 | self.apikey, 'create_repo', | |
192 | repo_name=repo_name, |
|
190 | repo_name=repo_name, | |
193 | owner=owner, |
|
191 | owner=owner, | |
194 | repo_type=backend.alias) |
|
192 | repo_type=backend.alias) | |
195 | response = api_call(self.app, params) |
|
193 | response = api_call(self.app, params) | |
196 | expected = 'user `%s` does not exist' % (owner,) |
|
194 | expected = 'user `%s` does not exist' % (owner,) | |
197 | assert_error(id_, expected, given=response.body) |
|
195 | assert_error(id_, expected, given=response.body) | |
198 |
|
196 | |||
199 | def test_api_create_repo_dont_specify_owner(self, backend): |
|
197 | def test_api_create_repo_dont_specify_owner(self, backend): | |
200 | repo_name = 'api-repo-3' |
|
198 | repo_name = 'api-repo-3' | |
201 | id_, params = build_data( |
|
199 | id_, params = build_data( | |
202 | self.apikey, 'create_repo', |
|
200 | self.apikey, 'create_repo', | |
203 | repo_name=repo_name, |
|
201 | repo_name=repo_name, | |
204 | repo_type=backend.alias) |
|
202 | repo_type=backend.alias) | |
205 | response = api_call(self.app, params) |
|
203 | response = api_call(self.app, params) | |
206 |
|
204 | |||
207 | repo = RepoModel().get_by_repo_name(repo_name) |
|
205 | repo = RepoModel().get_by_repo_name(repo_name) | |
208 | assert repo is not None |
|
206 | assert repo is not None | |
209 | ret = { |
|
207 | ret = { | |
210 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
208 | 'msg': 'Created new repository `%s`' % (repo_name,), | |
211 | 'success': True, |
|
209 | 'success': True, | |
212 | 'task': None, |
|
210 | 'task': None, | |
213 | } |
|
211 | } | |
214 | expected = ret |
|
212 | expected = ret | |
215 | assert_ok(id_, expected, given=response.body) |
|
213 | assert_ok(id_, expected, given=response.body) | |
216 | fixture.destroy_repo(repo_name) |
|
214 | fixture.destroy_repo(repo_name) | |
217 |
|
215 | |||
218 | def test_api_create_repo_by_non_admin(self, backend): |
|
216 | def test_api_create_repo_by_non_admin(self, backend): | |
219 | repo_name = 'api-repo-4' |
|
217 | repo_name = 'api-repo-4' | |
220 | id_, params = build_data( |
|
218 | id_, params = build_data( | |
221 | self.apikey_regular, 'create_repo', |
|
219 | self.apikey_regular, 'create_repo', | |
222 | repo_name=repo_name, |
|
220 | repo_name=repo_name, | |
223 | repo_type=backend.alias) |
|
221 | repo_type=backend.alias) | |
224 | response = api_call(self.app, params) |
|
222 | response = api_call(self.app, params) | |
225 |
|
223 | |||
226 | repo = RepoModel().get_by_repo_name(repo_name) |
|
224 | repo = RepoModel().get_by_repo_name(repo_name) | |
227 | assert repo is not None |
|
225 | assert repo is not None | |
228 | ret = { |
|
226 | ret = { | |
229 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
227 | 'msg': 'Created new repository `%s`' % (repo_name,), | |
230 | 'success': True, |
|
228 | 'success': True, | |
231 | 'task': None, |
|
229 | 'task': None, | |
232 | } |
|
230 | } | |
233 | expected = ret |
|
231 | expected = ret | |
234 | assert_ok(id_, expected, given=response.body) |
|
232 | assert_ok(id_, expected, given=response.body) | |
235 | fixture.destroy_repo(repo_name) |
|
233 | fixture.destroy_repo(repo_name) | |
236 |
|
234 | |||
237 | def test_api_create_repo_by_non_admin_specify_owner(self, backend): |
|
235 | def test_api_create_repo_by_non_admin_specify_owner(self, backend): | |
238 | repo_name = 'api-repo-5' |
|
236 | repo_name = 'api-repo-5' | |
239 | owner = 'i-dont-exist' |
|
237 | owner = 'i-dont-exist' | |
240 | id_, params = build_data( |
|
238 | id_, params = build_data( | |
241 | self.apikey_regular, 'create_repo', |
|
239 | self.apikey_regular, 'create_repo', | |
242 | repo_name=repo_name, |
|
240 | repo_name=repo_name, | |
243 | repo_type=backend.alias, |
|
241 | repo_type=backend.alias, | |
244 | owner=owner) |
|
242 | owner=owner) | |
245 | response = api_call(self.app, params) |
|
243 | response = api_call(self.app, params) | |
246 |
|
244 | |||
247 | expected = 'Only RhodeCode super-admin can specify `owner` param' |
|
245 | expected = 'Only RhodeCode super-admin can specify `owner` param' | |
248 | assert_error(id_, expected, given=response.body) |
|
246 | assert_error(id_, expected, given=response.body) | |
249 | fixture.destroy_repo(repo_name) |
|
247 | fixture.destroy_repo(repo_name) | |
250 |
|
248 | |||
251 | def test_api_create_repo_by_non_admin_no_parent_group_perms(self, backend): |
|
249 | def test_api_create_repo_by_non_admin_no_parent_group_perms(self, backend): | |
252 | repo_group_name = 'no-access' |
|
250 | repo_group_name = 'no-access' | |
253 | fixture.create_repo_group(repo_group_name) |
|
251 | fixture.create_repo_group(repo_group_name) | |
254 | repo_name = 'no-access/api-repo' |
|
252 | repo_name = 'no-access/api-repo' | |
255 |
|
253 | |||
256 | id_, params = build_data( |
|
254 | id_, params = build_data( | |
257 | self.apikey_regular, 'create_repo', |
|
255 | self.apikey_regular, 'create_repo', | |
258 | repo_name=repo_name, |
|
256 | repo_name=repo_name, | |
259 | repo_type=backend.alias) |
|
257 | repo_type=backend.alias) | |
260 | response = api_call(self.app, params) |
|
258 | response = api_call(self.app, params) | |
261 |
|
259 | |||
262 | expected = {'repo_group': 'Repository group `{}` does not exist'.format( |
|
260 | expected = {'repo_group': 'Repository group `{}` does not exist'.format( | |
263 | repo_group_name)} |
|
261 | repo_group_name)} | |
264 | assert_error(id_, expected, given=response.body) |
|
262 | assert_error(id_, expected, given=response.body) | |
265 | fixture.destroy_repo_group(repo_group_name) |
|
263 | fixture.destroy_repo_group(repo_group_name) | |
266 | fixture.destroy_repo(repo_name) |
|
264 | fixture.destroy_repo(repo_name) | |
267 |
|
265 | |||
268 | def test_api_create_repo_non_admin_no_permission_to_create_to_root_level( |
|
266 | def test_api_create_repo_non_admin_no_permission_to_create_to_root_level( | |
269 | self, backend, user_util): |
|
267 | self, backend, user_util): | |
270 |
|
268 | |||
271 | regular_user = user_util.create_user() |
|
269 | regular_user = user_util.create_user() | |
272 | regular_user_api_key = regular_user.api_key |
|
270 | regular_user_api_key = regular_user.api_key | |
273 |
|
271 | |||
274 | usr = UserModel().get_by_username(regular_user.username) |
|
272 | usr = UserModel().get_by_username(regular_user.username) | |
275 | usr.inherit_default_permissions = False |
|
273 | usr.inherit_default_permissions = False | |
276 | Session().add(usr) |
|
274 | Session().add(usr) | |
277 |
|
275 | |||
278 | repo_name = backend.new_repo_name() |
|
276 | repo_name = backend.new_repo_name() | |
279 | id_, params = build_data( |
|
277 | id_, params = build_data( | |
280 | regular_user_api_key, 'create_repo', |
|
278 | regular_user_api_key, 'create_repo', | |
281 | repo_name=repo_name, |
|
279 | repo_name=repo_name, | |
282 | repo_type=backend.alias) |
|
280 | repo_type=backend.alias) | |
283 | response = api_call(self.app, params) |
|
281 | response = api_call(self.app, params) | |
284 | expected = { |
|
282 | expected = { | |
285 | "repo_name": "You do not have the permission to " |
|
283 | "repo_name": "You do not have the permission to " | |
286 | "store repositories in the root location."} |
|
284 | "store repositories in the root location."} | |
287 | assert_error(id_, expected, given=response.body) |
|
285 | assert_error(id_, expected, given=response.body) | |
288 |
|
286 | |||
289 | def test_api_create_repo_exists(self, backend): |
|
287 | def test_api_create_repo_exists(self, backend): | |
290 | repo_name = backend.repo_name |
|
288 | repo_name = backend.repo_name | |
291 | id_, params = build_data( |
|
289 | id_, params = build_data( | |
292 | self.apikey, 'create_repo', |
|
290 | self.apikey, 'create_repo', | |
293 | repo_name=repo_name, |
|
291 | repo_name=repo_name, | |
294 | owner=TEST_USER_ADMIN_LOGIN, |
|
292 | owner=TEST_USER_ADMIN_LOGIN, | |
295 | repo_type=backend.alias,) |
|
293 | repo_type=backend.alias,) | |
296 | response = api_call(self.app, params) |
|
294 | response = api_call(self.app, params) | |
297 | expected = { |
|
295 | expected = { | |
298 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( |
|
296 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( | |
299 | repo_name)} |
|
297 | repo_name)} | |
300 | assert_error(id_, expected, given=response.body) |
|
298 | assert_error(id_, expected, given=response.body) | |
301 |
|
299 | |||
302 | @mock.patch.object(RepoModel, 'create', crash) |
|
300 | @mock.patch.object(RepoModel, 'create', crash) | |
303 | def test_api_create_repo_exception_occurred(self, backend): |
|
301 | def test_api_create_repo_exception_occurred(self, backend): | |
304 | repo_name = 'api-repo-6' |
|
302 | repo_name = 'api-repo-6' | |
305 | id_, params = build_data( |
|
303 | id_, params = build_data( | |
306 | self.apikey, 'create_repo', |
|
304 | self.apikey, 'create_repo', | |
307 | repo_name=repo_name, |
|
305 | repo_name=repo_name, | |
308 | owner=TEST_USER_ADMIN_LOGIN, |
|
306 | owner=TEST_USER_ADMIN_LOGIN, | |
309 | repo_type=backend.alias,) |
|
307 | repo_type=backend.alias,) | |
310 | response = api_call(self.app, params) |
|
308 | response = api_call(self.app, params) | |
311 | expected = 'failed to create repository `%s`' % (repo_name,) |
|
309 | expected = 'failed to create repository `%s`' % (repo_name,) | |
312 | assert_error(id_, expected, given=response.body) |
|
310 | assert_error(id_, expected, given=response.body) | |
313 |
|
311 | |||
314 | @pytest.mark.parametrize('parent_group, dirty_name, expected_name', [ |
|
312 | @pytest.mark.parametrize('parent_group, dirty_name, expected_name', [ | |
315 | (None, 'foo bar x', 'foo-bar-x'), |
|
313 | (None, 'foo bar x', 'foo-bar-x'), | |
316 | ('foo', '/foo//bar x', 'foo/bar-x'), |
|
314 | ('foo', '/foo//bar x', 'foo/bar-x'), | |
317 | ('foo-bar', 'foo-bar //bar x', 'foo-bar/bar-x'), |
|
315 | ('foo-bar', 'foo-bar //bar x', 'foo-bar/bar-x'), | |
318 | ]) |
|
316 | ]) | |
319 | def test_create_repo_with_extra_slashes_in_name( |
|
317 | def test_create_repo_with_extra_slashes_in_name( | |
320 | self, backend, parent_group, dirty_name, expected_name): |
|
318 | self, backend, parent_group, dirty_name, expected_name): | |
321 |
|
319 | |||
322 | if parent_group: |
|
320 | if parent_group: | |
323 | gr = fixture.create_repo_group(parent_group) |
|
321 | gr = fixture.create_repo_group(parent_group) | |
324 | assert gr.group_name == parent_group |
|
322 | assert gr.group_name == parent_group | |
325 |
|
323 | |||
326 | id_, params = build_data( |
|
324 | id_, params = build_data( | |
327 | self.apikey, 'create_repo', |
|
325 | self.apikey, 'create_repo', | |
328 | repo_name=dirty_name, |
|
326 | repo_name=dirty_name, | |
329 | repo_type=backend.alias, |
|
327 | repo_type=backend.alias, | |
330 | owner=TEST_USER_ADMIN_LOGIN,) |
|
328 | owner=TEST_USER_ADMIN_LOGIN,) | |
331 | response = api_call(self.app, params) |
|
329 | response = api_call(self.app, params) | |
332 | expected ={ |
|
330 | expected ={ | |
333 | "msg": "Created new repository `{}`".format(expected_name), |
|
331 | "msg": "Created new repository `{}`".format(expected_name), | |
334 | "task": None, |
|
332 | "task": None, | |
335 | "success": True |
|
333 | "success": True | |
336 | } |
|
334 | } | |
337 | assert_ok(id_, expected, response.body) |
|
335 | assert_ok(id_, expected, response.body) | |
338 |
|
336 | |||
339 | repo = RepoModel().get_by_repo_name(expected_name) |
|
337 | repo = RepoModel().get_by_repo_name(expected_name) | |
340 | assert repo is not None |
|
338 | assert repo is not None | |
341 |
|
339 | |||
342 | expected = { |
|
340 | expected = { | |
343 | 'msg': 'Created new repository `%s`' % (expected_name,), |
|
341 | 'msg': 'Created new repository `%s`' % (expected_name,), | |
344 | 'success': True, |
|
342 | 'success': True, | |
345 | 'task': None, |
|
343 | 'task': None, | |
346 | } |
|
344 | } | |
347 | assert_ok(id_, expected, given=response.body) |
|
345 | assert_ok(id_, expected, given=response.body) | |
348 | fixture.destroy_repo(expected_name) |
|
346 | fixture.destroy_repo(expected_name) | |
349 | if parent_group: |
|
347 | if parent_group: | |
350 | fixture.destroy_repo_group(parent_group) |
|
348 | fixture.destroy_repo_group(parent_group) |
@@ -1,289 +1,288 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.model.repo_group import RepoGroupModel |
|
24 | from rhodecode.model.repo_group import RepoGroupModel | |
26 | from rhodecode.model.user import UserModel |
|
25 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
28 | from rhodecode.api.tests.utils import ( |
|
27 | from rhodecode.api.tests.utils import ( | |
29 | build_data, api_call, assert_ok, assert_error, crash) |
|
28 | build_data, api_call, assert_ok, assert_error, crash) | |
30 | from rhodecode.tests.fixture import Fixture |
|
29 | from rhodecode.tests.fixture import Fixture | |
31 |
|
30 | |||
32 |
|
31 | |||
33 | fixture = Fixture() |
|
32 | fixture = Fixture() | |
34 |
|
33 | |||
35 |
|
34 | |||
36 | @pytest.mark.usefixtures("testuser_api", "app") |
|
35 | @pytest.mark.usefixtures("testuser_api", "app") | |
37 | class TestCreateRepoGroup(object): |
|
36 | class TestCreateRepoGroup(object): | |
38 | def test_api_create_repo_group(self): |
|
37 | def test_api_create_repo_group(self): | |
39 | repo_group_name = 'api-repo-group' |
|
38 | repo_group_name = 'api-repo-group' | |
40 |
|
39 | |||
41 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
40 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
42 | assert repo_group is None |
|
41 | assert repo_group is None | |
43 |
|
42 | |||
44 | id_, params = build_data( |
|
43 | id_, params = build_data( | |
45 | self.apikey, 'create_repo_group', |
|
44 | self.apikey, 'create_repo_group', | |
46 | group_name=repo_group_name, |
|
45 | group_name=repo_group_name, | |
47 | owner=TEST_USER_ADMIN_LOGIN,) |
|
46 | owner=TEST_USER_ADMIN_LOGIN,) | |
48 | response = api_call(self.app, params) |
|
47 | response = api_call(self.app, params) | |
49 |
|
48 | |||
50 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
49 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
51 | assert repo_group is not None |
|
50 | assert repo_group is not None | |
52 | ret = { |
|
51 | ret = { | |
53 | 'msg': 'Created new repo group `%s`' % (repo_group_name,), |
|
52 | 'msg': 'Created new repo group `%s`' % (repo_group_name,), | |
54 | 'repo_group': repo_group.get_api_data() |
|
53 | 'repo_group': repo_group.get_api_data() | |
55 | } |
|
54 | } | |
56 | expected = ret |
|
55 | expected = ret | |
57 | try: |
|
56 | try: | |
58 | assert_ok(id_, expected, given=response.body) |
|
57 | assert_ok(id_, expected, given=response.body) | |
59 | finally: |
|
58 | finally: | |
60 | fixture.destroy_repo_group(repo_group_name) |
|
59 | fixture.destroy_repo_group(repo_group_name) | |
61 |
|
60 | |||
62 | def test_api_create_repo_group_in_another_group(self): |
|
61 | def test_api_create_repo_group_in_another_group(self): | |
63 | repo_group_name = 'api-repo-group' |
|
62 | repo_group_name = 'api-repo-group' | |
64 |
|
63 | |||
65 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
64 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
66 | assert repo_group is None |
|
65 | assert repo_group is None | |
67 | # create the parent |
|
66 | # create the parent | |
68 | fixture.create_repo_group(repo_group_name) |
|
67 | fixture.create_repo_group(repo_group_name) | |
69 |
|
68 | |||
70 | full_repo_group_name = repo_group_name+'/'+repo_group_name |
|
69 | full_repo_group_name = repo_group_name+'/'+repo_group_name | |
71 | id_, params = build_data( |
|
70 | id_, params = build_data( | |
72 | self.apikey, 'create_repo_group', |
|
71 | self.apikey, 'create_repo_group', | |
73 | group_name=full_repo_group_name, |
|
72 | group_name=full_repo_group_name, | |
74 | owner=TEST_USER_ADMIN_LOGIN, |
|
73 | owner=TEST_USER_ADMIN_LOGIN, | |
75 | copy_permissions=True) |
|
74 | copy_permissions=True) | |
76 | response = api_call(self.app, params) |
|
75 | response = api_call(self.app, params) | |
77 |
|
76 | |||
78 | repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name) |
|
77 | repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name) | |
79 | assert repo_group is not None |
|
78 | assert repo_group is not None | |
80 | ret = { |
|
79 | ret = { | |
81 | 'msg': 'Created new repo group `%s`' % (full_repo_group_name,), |
|
80 | 'msg': 'Created new repo group `%s`' % (full_repo_group_name,), | |
82 | 'repo_group': repo_group.get_api_data() |
|
81 | 'repo_group': repo_group.get_api_data() | |
83 | } |
|
82 | } | |
84 | expected = ret |
|
83 | expected = ret | |
85 | try: |
|
84 | try: | |
86 | assert_ok(id_, expected, given=response.body) |
|
85 | assert_ok(id_, expected, given=response.body) | |
87 | finally: |
|
86 | finally: | |
88 | fixture.destroy_repo_group(full_repo_group_name) |
|
87 | fixture.destroy_repo_group(full_repo_group_name) | |
89 | fixture.destroy_repo_group(repo_group_name) |
|
88 | fixture.destroy_repo_group(repo_group_name) | |
90 |
|
89 | |||
91 | def test_api_create_repo_group_in_another_group_not_existing(self): |
|
90 | def test_api_create_repo_group_in_another_group_not_existing(self): | |
92 | repo_group_name = 'api-repo-group-no' |
|
91 | repo_group_name = 'api-repo-group-no' | |
93 |
|
92 | |||
94 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
93 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
95 | assert repo_group is None |
|
94 | assert repo_group is None | |
96 |
|
95 | |||
97 | full_repo_group_name = repo_group_name+'/'+repo_group_name |
|
96 | full_repo_group_name = repo_group_name+'/'+repo_group_name | |
98 | id_, params = build_data( |
|
97 | id_, params = build_data( | |
99 | self.apikey, 'create_repo_group', |
|
98 | self.apikey, 'create_repo_group', | |
100 | group_name=full_repo_group_name, |
|
99 | group_name=full_repo_group_name, | |
101 | owner=TEST_USER_ADMIN_LOGIN, |
|
100 | owner=TEST_USER_ADMIN_LOGIN, | |
102 | copy_permissions=True) |
|
101 | copy_permissions=True) | |
103 | response = api_call(self.app, params) |
|
102 | response = api_call(self.app, params) | |
104 | expected = { |
|
103 | expected = { | |
105 | 'repo_group': |
|
104 | 'repo_group': | |
106 | 'Parent repository group `{}` does not exist'.format( |
|
105 | 'Parent repository group `{}` does not exist'.format( | |
107 | repo_group_name)} |
|
106 | repo_group_name)} | |
108 | assert_error(id_, expected, given=response.body) |
|
107 | assert_error(id_, expected, given=response.body) | |
109 |
|
108 | |||
110 | def test_api_create_repo_group_that_exists(self): |
|
109 | def test_api_create_repo_group_that_exists(self): | |
111 | repo_group_name = 'api-repo-group' |
|
110 | repo_group_name = 'api-repo-group' | |
112 |
|
111 | |||
113 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
112 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
114 | assert repo_group is None |
|
113 | assert repo_group is None | |
115 |
|
114 | |||
116 | fixture.create_repo_group(repo_group_name) |
|
115 | fixture.create_repo_group(repo_group_name) | |
117 | id_, params = build_data( |
|
116 | id_, params = build_data( | |
118 | self.apikey, 'create_repo_group', |
|
117 | self.apikey, 'create_repo_group', | |
119 | group_name=repo_group_name, |
|
118 | group_name=repo_group_name, | |
120 | owner=TEST_USER_ADMIN_LOGIN,) |
|
119 | owner=TEST_USER_ADMIN_LOGIN,) | |
121 | response = api_call(self.app, params) |
|
120 | response = api_call(self.app, params) | |
122 | expected = { |
|
121 | expected = { | |
123 | 'unique_repo_group_name': |
|
122 | 'unique_repo_group_name': | |
124 | 'Repository group with name `{}` already exists'.format( |
|
123 | 'Repository group with name `{}` already exists'.format( | |
125 | repo_group_name)} |
|
124 | repo_group_name)} | |
126 | try: |
|
125 | try: | |
127 | assert_error(id_, expected, given=response.body) |
|
126 | assert_error(id_, expected, given=response.body) | |
128 | finally: |
|
127 | finally: | |
129 | fixture.destroy_repo_group(repo_group_name) |
|
128 | fixture.destroy_repo_group(repo_group_name) | |
130 |
|
129 | |||
131 | def test_api_create_repo_group_regular_user_wit_root_location_perms( |
|
130 | def test_api_create_repo_group_regular_user_wit_root_location_perms( | |
132 | self, user_util): |
|
131 | self, user_util): | |
133 | regular_user = user_util.create_user() |
|
132 | regular_user = user_util.create_user() | |
134 | regular_user_api_key = regular_user.api_key |
|
133 | regular_user_api_key = regular_user.api_key | |
135 |
|
134 | |||
136 | repo_group_name = 'api-repo-group-by-regular-user' |
|
135 | repo_group_name = 'api-repo-group-by-regular-user' | |
137 |
|
136 | |||
138 | usr = UserModel().get_by_username(regular_user.username) |
|
137 | usr = UserModel().get_by_username(regular_user.username) | |
139 | usr.inherit_default_permissions = False |
|
138 | usr.inherit_default_permissions = False | |
140 | Session().add(usr) |
|
139 | Session().add(usr) | |
141 |
|
140 | |||
142 | UserModel().grant_perm( |
|
141 | UserModel().grant_perm( | |
143 | regular_user.username, 'hg.repogroup.create.true') |
|
142 | regular_user.username, 'hg.repogroup.create.true') | |
144 | Session().commit() |
|
143 | Session().commit() | |
145 |
|
144 | |||
146 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
145 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
147 | assert repo_group is None |
|
146 | assert repo_group is None | |
148 |
|
147 | |||
149 | id_, params = build_data( |
|
148 | id_, params = build_data( | |
150 | regular_user_api_key, 'create_repo_group', |
|
149 | regular_user_api_key, 'create_repo_group', | |
151 | group_name=repo_group_name) |
|
150 | group_name=repo_group_name) | |
152 | response = api_call(self.app, params) |
|
151 | response = api_call(self.app, params) | |
153 |
|
152 | |||
154 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
153 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
155 | assert repo_group is not None |
|
154 | assert repo_group is not None | |
156 | expected = { |
|
155 | expected = { | |
157 | 'msg': 'Created new repo group `%s`' % (repo_group_name,), |
|
156 | 'msg': 'Created new repo group `%s`' % (repo_group_name,), | |
158 | 'repo_group': repo_group.get_api_data() |
|
157 | 'repo_group': repo_group.get_api_data() | |
159 | } |
|
158 | } | |
160 | try: |
|
159 | try: | |
161 | assert_ok(id_, expected, given=response.body) |
|
160 | assert_ok(id_, expected, given=response.body) | |
162 | finally: |
|
161 | finally: | |
163 | fixture.destroy_repo_group(repo_group_name) |
|
162 | fixture.destroy_repo_group(repo_group_name) | |
164 |
|
163 | |||
165 | def test_api_create_repo_group_regular_user_with_admin_perms_to_parent( |
|
164 | def test_api_create_repo_group_regular_user_with_admin_perms_to_parent( | |
166 | self, user_util): |
|
165 | self, user_util): | |
167 |
|
166 | |||
168 | repo_group_name = 'api-repo-group-parent' |
|
167 | repo_group_name = 'api-repo-group-parent' | |
169 |
|
168 | |||
170 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
169 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
171 | assert repo_group is None |
|
170 | assert repo_group is None | |
172 | # create the parent |
|
171 | # create the parent | |
173 | fixture.create_repo_group(repo_group_name) |
|
172 | fixture.create_repo_group(repo_group_name) | |
174 |
|
173 | |||
175 | # user perms |
|
174 | # user perms | |
176 | regular_user = user_util.create_user() |
|
175 | regular_user = user_util.create_user() | |
177 | regular_user_api_key = regular_user.api_key |
|
176 | regular_user_api_key = regular_user.api_key | |
178 |
|
177 | |||
179 | usr = UserModel().get_by_username(regular_user.username) |
|
178 | usr = UserModel().get_by_username(regular_user.username) | |
180 | usr.inherit_default_permissions = False |
|
179 | usr.inherit_default_permissions = False | |
181 | Session().add(usr) |
|
180 | Session().add(usr) | |
182 |
|
181 | |||
183 | RepoGroupModel().grant_user_permission( |
|
182 | RepoGroupModel().grant_user_permission( | |
184 | repo_group_name, regular_user.username, 'group.admin') |
|
183 | repo_group_name, regular_user.username, 'group.admin') | |
185 | Session().commit() |
|
184 | Session().commit() | |
186 |
|
185 | |||
187 | full_repo_group_name = repo_group_name + '/' + repo_group_name |
|
186 | full_repo_group_name = repo_group_name + '/' + repo_group_name | |
188 | id_, params = build_data( |
|
187 | id_, params = build_data( | |
189 | regular_user_api_key, 'create_repo_group', |
|
188 | regular_user_api_key, 'create_repo_group', | |
190 | group_name=full_repo_group_name) |
|
189 | group_name=full_repo_group_name) | |
191 | response = api_call(self.app, params) |
|
190 | response = api_call(self.app, params) | |
192 |
|
191 | |||
193 | repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name) |
|
192 | repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name) | |
194 | assert repo_group is not None |
|
193 | assert repo_group is not None | |
195 | expected = { |
|
194 | expected = { | |
196 | 'msg': 'Created new repo group `{}`'.format(full_repo_group_name), |
|
195 | 'msg': 'Created new repo group `{}`'.format(full_repo_group_name), | |
197 | 'repo_group': repo_group.get_api_data() |
|
196 | 'repo_group': repo_group.get_api_data() | |
198 | } |
|
197 | } | |
199 | try: |
|
198 | try: | |
200 | assert_ok(id_, expected, given=response.body) |
|
199 | assert_ok(id_, expected, given=response.body) | |
201 | finally: |
|
200 | finally: | |
202 | fixture.destroy_repo_group(full_repo_group_name) |
|
201 | fixture.destroy_repo_group(full_repo_group_name) | |
203 | fixture.destroy_repo_group(repo_group_name) |
|
202 | fixture.destroy_repo_group(repo_group_name) | |
204 |
|
203 | |||
205 | def test_api_create_repo_group_regular_user_no_permission_to_create_to_root_level(self): |
|
204 | def test_api_create_repo_group_regular_user_no_permission_to_create_to_root_level(self): | |
206 | repo_group_name = 'api-repo-group' |
|
205 | repo_group_name = 'api-repo-group' | |
207 |
|
206 | |||
208 | id_, params = build_data( |
|
207 | id_, params = build_data( | |
209 | self.apikey_regular, 'create_repo_group', |
|
208 | self.apikey_regular, 'create_repo_group', | |
210 | group_name=repo_group_name) |
|
209 | group_name=repo_group_name) | |
211 | response = api_call(self.app, params) |
|
210 | response = api_call(self.app, params) | |
212 |
|
211 | |||
213 | expected = { |
|
212 | expected = { | |
214 | 'repo_group': |
|
213 | 'repo_group': | |
215 | u'You do not have the permission to store ' |
|
214 | u'You do not have the permission to store ' | |
216 | u'repository groups in the root location.'} |
|
215 | u'repository groups in the root location.'} | |
217 | assert_error(id_, expected, given=response.body) |
|
216 | assert_error(id_, expected, given=response.body) | |
218 |
|
217 | |||
219 | def test_api_create_repo_group_regular_user_no_parent_group_perms(self): |
|
218 | def test_api_create_repo_group_regular_user_no_parent_group_perms(self): | |
220 | repo_group_name = 'api-repo-group-regular-user' |
|
219 | repo_group_name = 'api-repo-group-regular-user' | |
221 |
|
220 | |||
222 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
221 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
223 | assert repo_group is None |
|
222 | assert repo_group is None | |
224 | # create the parent |
|
223 | # create the parent | |
225 | fixture.create_repo_group(repo_group_name) |
|
224 | fixture.create_repo_group(repo_group_name) | |
226 |
|
225 | |||
227 | full_repo_group_name = repo_group_name+'/'+repo_group_name |
|
226 | full_repo_group_name = repo_group_name+'/'+repo_group_name | |
228 |
|
227 | |||
229 | id_, params = build_data( |
|
228 | id_, params = build_data( | |
230 | self.apikey_regular, 'create_repo_group', |
|
229 | self.apikey_regular, 'create_repo_group', | |
231 | group_name=full_repo_group_name) |
|
230 | group_name=full_repo_group_name) | |
232 | response = api_call(self.app, params) |
|
231 | response = api_call(self.app, params) | |
233 |
|
232 | |||
234 | expected = { |
|
233 | expected = { | |
235 | 'repo_group': |
|
234 | 'repo_group': | |
236 | u"You do not have the permissions to store " |
|
235 | u"You do not have the permissions to store " | |
237 | u"repository groups inside repository group `{}`".format(repo_group_name)} |
|
236 | u"repository groups inside repository group `{}`".format(repo_group_name)} | |
238 | try: |
|
237 | try: | |
239 | assert_error(id_, expected, given=response.body) |
|
238 | assert_error(id_, expected, given=response.body) | |
240 | finally: |
|
239 | finally: | |
241 | fixture.destroy_repo_group(repo_group_name) |
|
240 | fixture.destroy_repo_group(repo_group_name) | |
242 |
|
241 | |||
243 | def test_api_create_repo_group_regular_user_no_permission_to_specify_owner( |
|
242 | def test_api_create_repo_group_regular_user_no_permission_to_specify_owner( | |
244 | self): |
|
243 | self): | |
245 | repo_group_name = 'api-repo-group' |
|
244 | repo_group_name = 'api-repo-group' | |
246 |
|
245 | |||
247 | id_, params = build_data( |
|
246 | id_, params = build_data( | |
248 | self.apikey_regular, 'create_repo_group', |
|
247 | self.apikey_regular, 'create_repo_group', | |
249 | group_name=repo_group_name, |
|
248 | group_name=repo_group_name, | |
250 | owner=TEST_USER_ADMIN_LOGIN,) |
|
249 | owner=TEST_USER_ADMIN_LOGIN,) | |
251 | response = api_call(self.app, params) |
|
250 | response = api_call(self.app, params) | |
252 |
|
251 | |||
253 | expected = "Only RhodeCode super-admin can specify `owner` param" |
|
252 | expected = "Only RhodeCode super-admin can specify `owner` param" | |
254 | assert_error(id_, expected, given=response.body) |
|
253 | assert_error(id_, expected, given=response.body) | |
255 |
|
254 | |||
256 | @mock.patch.object(RepoGroupModel, 'create', crash) |
|
255 | @mock.patch.object(RepoGroupModel, 'create', crash) | |
257 | def test_api_create_repo_group_exception_occurred(self): |
|
256 | def test_api_create_repo_group_exception_occurred(self): | |
258 | repo_group_name = 'api-repo-group' |
|
257 | repo_group_name = 'api-repo-group' | |
259 |
|
258 | |||
260 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
259 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) | |
261 | assert repo_group is None |
|
260 | assert repo_group is None | |
262 |
|
261 | |||
263 | id_, params = build_data( |
|
262 | id_, params = build_data( | |
264 | self.apikey, 'create_repo_group', |
|
263 | self.apikey, 'create_repo_group', | |
265 | group_name=repo_group_name, |
|
264 | group_name=repo_group_name, | |
266 | owner=TEST_USER_ADMIN_LOGIN,) |
|
265 | owner=TEST_USER_ADMIN_LOGIN,) | |
267 | response = api_call(self.app, params) |
|
266 | response = api_call(self.app, params) | |
268 | expected = 'failed to create repo group `%s`' % (repo_group_name,) |
|
267 | expected = 'failed to create repo group `%s`' % (repo_group_name,) | |
269 | assert_error(id_, expected, given=response.body) |
|
268 | assert_error(id_, expected, given=response.body) | |
270 |
|
269 | |||
271 | def test_create_group_with_extra_slashes_in_name(self, user_util): |
|
270 | def test_create_group_with_extra_slashes_in_name(self, user_util): | |
272 | existing_repo_group = user_util.create_repo_group() |
|
271 | existing_repo_group = user_util.create_repo_group() | |
273 | dirty_group_name = '//{}//group2//'.format( |
|
272 | dirty_group_name = '//{}//group2//'.format( | |
274 | existing_repo_group.group_name) |
|
273 | existing_repo_group.group_name) | |
275 | cleaned_group_name = '{}/group2'.format( |
|
274 | cleaned_group_name = '{}/group2'.format( | |
276 | existing_repo_group.group_name) |
|
275 | existing_repo_group.group_name) | |
277 |
|
276 | |||
278 | id_, params = build_data( |
|
277 | id_, params = build_data( | |
279 | self.apikey, 'create_repo_group', |
|
278 | self.apikey, 'create_repo_group', | |
280 | group_name=dirty_group_name, |
|
279 | group_name=dirty_group_name, | |
281 | owner=TEST_USER_ADMIN_LOGIN,) |
|
280 | owner=TEST_USER_ADMIN_LOGIN,) | |
282 | response = api_call(self.app, params) |
|
281 | response = api_call(self.app, params) | |
283 | repo_group = RepoGroupModel.cls.get_by_group_name(cleaned_group_name) |
|
282 | repo_group = RepoGroupModel.cls.get_by_group_name(cleaned_group_name) | |
284 | expected = { |
|
283 | expected = { | |
285 | 'msg': 'Created new repo group `%s`' % (cleaned_group_name,), |
|
284 | 'msg': 'Created new repo group `%s`' % (cleaned_group_name,), | |
286 | 'repo_group': repo_group.get_api_data() |
|
285 | 'repo_group': repo_group.get_api_data() | |
287 | } |
|
286 | } | |
288 | assert_ok(id_, expected, given=response.body) |
|
287 | assert_ok(id_, expected, given=response.body) | |
289 | fixture.destroy_repo_group(cleaned_group_name) |
|
288 | fixture.destroy_repo_group(cleaned_group_name) |
@@ -1,207 +1,206 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.lib.auth import check_password |
|
23 | from rhodecode.lib.auth import check_password | |
25 | from rhodecode.model.user import UserModel |
|
24 | from rhodecode.model.user import UserModel | |
26 | from rhodecode.tests import ( |
|
25 | from rhodecode.tests import ( | |
27 | TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_EMAIL) |
|
26 | TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_EMAIL) | |
28 | from rhodecode.api.tests.utils import ( |
|
27 | from rhodecode.api.tests.utils import ( | |
29 | build_data, api_call, assert_ok, assert_error, jsonify, crash) |
|
28 | build_data, api_call, assert_ok, assert_error, jsonify, crash) | |
30 | from rhodecode.tests.fixture import Fixture |
|
29 | from rhodecode.tests.fixture import Fixture | |
31 | from rhodecode.model.db import RepoGroup |
|
30 | from rhodecode.model.db import RepoGroup | |
32 |
|
31 | |||
33 |
|
32 | |||
34 | # TODO: mikhail: remove fixture from here |
|
33 | # TODO: mikhail: remove fixture from here | |
35 | fixture = Fixture() |
|
34 | fixture = Fixture() | |
36 |
|
35 | |||
37 |
|
36 | |||
38 | @pytest.mark.usefixtures("testuser_api", "app") |
|
37 | @pytest.mark.usefixtures("testuser_api", "app") | |
39 | class TestCreateUser(object): |
|
38 | class TestCreateUser(object): | |
40 | def test_api_create_existing_user(self): |
|
39 | def test_api_create_existing_user(self): | |
41 | id_, params = build_data( |
|
40 | id_, params = build_data( | |
42 | self.apikey, 'create_user', |
|
41 | self.apikey, 'create_user', | |
43 | username=TEST_USER_ADMIN_LOGIN, |
|
42 | username=TEST_USER_ADMIN_LOGIN, | |
44 | email='test@foo.com', |
|
43 | email='test@foo.com', | |
45 | password='trololo') |
|
44 | password='trololo') | |
46 | response = api_call(self.app, params) |
|
45 | response = api_call(self.app, params) | |
47 |
|
46 | |||
48 | expected = "user `%s` already exist" % (TEST_USER_ADMIN_LOGIN,) |
|
47 | expected = "user `%s` already exist" % (TEST_USER_ADMIN_LOGIN,) | |
49 | assert_error(id_, expected, given=response.body) |
|
48 | assert_error(id_, expected, given=response.body) | |
50 |
|
49 | |||
51 | def test_api_create_user_with_existing_email(self): |
|
50 | def test_api_create_user_with_existing_email(self): | |
52 | id_, params = build_data( |
|
51 | id_, params = build_data( | |
53 | self.apikey, 'create_user', |
|
52 | self.apikey, 'create_user', | |
54 | username=TEST_USER_ADMIN_LOGIN + 'new', |
|
53 | username=TEST_USER_ADMIN_LOGIN + 'new', | |
55 | email=TEST_USER_REGULAR_EMAIL, |
|
54 | email=TEST_USER_REGULAR_EMAIL, | |
56 | password='trololo') |
|
55 | password='trololo') | |
57 | response = api_call(self.app, params) |
|
56 | response = api_call(self.app, params) | |
58 |
|
57 | |||
59 | expected = "email `%s` already exist" % (TEST_USER_REGULAR_EMAIL,) |
|
58 | expected = "email `%s` already exist" % (TEST_USER_REGULAR_EMAIL,) | |
60 | assert_error(id_, expected, given=response.body) |
|
59 | assert_error(id_, expected, given=response.body) | |
61 |
|
60 | |||
62 | def test_api_create_user_with_wrong_username(self): |
|
61 | def test_api_create_user_with_wrong_username(self): | |
63 | bad_username = '<> HELLO WORLD <>' |
|
62 | bad_username = '<> HELLO WORLD <>' | |
64 | id_, params = build_data( |
|
63 | id_, params = build_data( | |
65 | self.apikey, 'create_user', |
|
64 | self.apikey, 'create_user', | |
66 | username=bad_username, |
|
65 | username=bad_username, | |
67 | email='new@email.com', |
|
66 | email='new@email.com', | |
68 | password='trololo') |
|
67 | password='trololo') | |
69 | response = api_call(self.app, params) |
|
68 | response = api_call(self.app, params) | |
70 |
|
69 | |||
71 | expected = {'username': |
|
70 | expected = {'username': | |
72 | "Username may only contain alphanumeric characters " |
|
71 | "Username may only contain alphanumeric characters " | |
73 | "underscores, periods or dashes and must begin with " |
|
72 | "underscores, periods or dashes and must begin with " | |
74 | "alphanumeric character or underscore"} |
|
73 | "alphanumeric character or underscore"} | |
75 | assert_error(id_, expected, given=response.body) |
|
74 | assert_error(id_, expected, given=response.body) | |
76 |
|
75 | |||
77 | def test_api_create_user(self): |
|
76 | def test_api_create_user(self): | |
78 | username = 'test_new_api_user' |
|
77 | username = 'test_new_api_user' | |
79 | email = username + "@foo.com" |
|
78 | email = username + "@foo.com" | |
80 |
|
79 | |||
81 | id_, params = build_data( |
|
80 | id_, params = build_data( | |
82 | self.apikey, 'create_user', |
|
81 | self.apikey, 'create_user', | |
83 | username=username, |
|
82 | username=username, | |
84 | email=email, |
|
83 | email=email, | |
85 | description='CTO of Things', |
|
84 | description='CTO of Things', | |
86 | password='example') |
|
85 | password='example') | |
87 | response = api_call(self.app, params) |
|
86 | response = api_call(self.app, params) | |
88 |
|
87 | |||
89 | usr = UserModel().get_by_username(username) |
|
88 | usr = UserModel().get_by_username(username) | |
90 | ret = { |
|
89 | ret = { | |
91 | 'msg': 'created new user `%s`' % (username,), |
|
90 | 'msg': 'created new user `%s`' % (username,), | |
92 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
91 | 'user': jsonify(usr.get_api_data(include_secrets=True)), | |
93 | } |
|
92 | } | |
94 | try: |
|
93 | try: | |
95 | expected = ret |
|
94 | expected = ret | |
96 | assert check_password('example', usr.password) |
|
95 | assert check_password('example', usr.password) | |
97 | assert_ok(id_, expected, given=response.body) |
|
96 | assert_ok(id_, expected, given=response.body) | |
98 | finally: |
|
97 | finally: | |
99 | fixture.destroy_user(usr.user_id) |
|
98 | fixture.destroy_user(usr.user_id) | |
100 |
|
99 | |||
101 | def test_api_create_user_without_password(self): |
|
100 | def test_api_create_user_without_password(self): | |
102 | username = 'test_new_api_user_passwordless' |
|
101 | username = 'test_new_api_user_passwordless' | |
103 | email = username + "@foo.com" |
|
102 | email = username + "@foo.com" | |
104 |
|
103 | |||
105 | id_, params = build_data( |
|
104 | id_, params = build_data( | |
106 | self.apikey, 'create_user', |
|
105 | self.apikey, 'create_user', | |
107 | username=username, |
|
106 | username=username, | |
108 | email=email) |
|
107 | email=email) | |
109 | response = api_call(self.app, params) |
|
108 | response = api_call(self.app, params) | |
110 |
|
109 | |||
111 | usr = UserModel().get_by_username(username) |
|
110 | usr = UserModel().get_by_username(username) | |
112 | ret = { |
|
111 | ret = { | |
113 | 'msg': 'created new user `%s`' % (username,), |
|
112 | 'msg': 'created new user `%s`' % (username,), | |
114 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
113 | 'user': jsonify(usr.get_api_data(include_secrets=True)), | |
115 | } |
|
114 | } | |
116 | try: |
|
115 | try: | |
117 | expected = ret |
|
116 | expected = ret | |
118 | assert_ok(id_, expected, given=response.body) |
|
117 | assert_ok(id_, expected, given=response.body) | |
119 | finally: |
|
118 | finally: | |
120 | fixture.destroy_user(usr.user_id) |
|
119 | fixture.destroy_user(usr.user_id) | |
121 |
|
120 | |||
122 | def test_api_create_user_with_extern_name(self): |
|
121 | def test_api_create_user_with_extern_name(self): | |
123 | username = 'test_new_api_user_passwordless' |
|
122 | username = 'test_new_api_user_passwordless' | |
124 | email = username + "@foo.com" |
|
123 | email = username + "@foo.com" | |
125 |
|
124 | |||
126 | id_, params = build_data( |
|
125 | id_, params = build_data( | |
127 | self.apikey, 'create_user', |
|
126 | self.apikey, 'create_user', | |
128 | username=username, |
|
127 | username=username, | |
129 | email=email, extern_name='rhodecode') |
|
128 | email=email, extern_name='rhodecode') | |
130 | response = api_call(self.app, params) |
|
129 | response = api_call(self.app, params) | |
131 |
|
130 | |||
132 | usr = UserModel().get_by_username(username) |
|
131 | usr = UserModel().get_by_username(username) | |
133 | ret = { |
|
132 | ret = { | |
134 | 'msg': 'created new user `%s`' % (username,), |
|
133 | 'msg': 'created new user `%s`' % (username,), | |
135 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
134 | 'user': jsonify(usr.get_api_data(include_secrets=True)), | |
136 | } |
|
135 | } | |
137 | try: |
|
136 | try: | |
138 | expected = ret |
|
137 | expected = ret | |
139 | assert_ok(id_, expected, given=response.body) |
|
138 | assert_ok(id_, expected, given=response.body) | |
140 | finally: |
|
139 | finally: | |
141 | fixture.destroy_user(usr.user_id) |
|
140 | fixture.destroy_user(usr.user_id) | |
142 |
|
141 | |||
143 | def test_api_create_user_with_password_change(self): |
|
142 | def test_api_create_user_with_password_change(self): | |
144 | username = 'test_new_api_user_password_change' |
|
143 | username = 'test_new_api_user_password_change' | |
145 | email = username + "@foo.com" |
|
144 | email = username + "@foo.com" | |
146 |
|
145 | |||
147 | id_, params = build_data( |
|
146 | id_, params = build_data( | |
148 | self.apikey, 'create_user', |
|
147 | self.apikey, 'create_user', | |
149 | username=username, |
|
148 | username=username, | |
150 | email=email, extern_name='rhodecode', |
|
149 | email=email, extern_name='rhodecode', | |
151 | force_password_change=True) |
|
150 | force_password_change=True) | |
152 | response = api_call(self.app, params) |
|
151 | response = api_call(self.app, params) | |
153 |
|
152 | |||
154 | usr = UserModel().get_by_username(username) |
|
153 | usr = UserModel().get_by_username(username) | |
155 | ret = { |
|
154 | ret = { | |
156 | 'msg': 'created new user `%s`' % (username,), |
|
155 | 'msg': 'created new user `%s`' % (username,), | |
157 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
156 | 'user': jsonify(usr.get_api_data(include_secrets=True)), | |
158 | } |
|
157 | } | |
159 | try: |
|
158 | try: | |
160 | expected = ret |
|
159 | expected = ret | |
161 | assert_ok(id_, expected, given=response.body) |
|
160 | assert_ok(id_, expected, given=response.body) | |
162 | finally: |
|
161 | finally: | |
163 | fixture.destroy_user(usr.user_id) |
|
162 | fixture.destroy_user(usr.user_id) | |
164 |
|
163 | |||
165 | def test_api_create_user_with_personal_repo_group(self): |
|
164 | def test_api_create_user_with_personal_repo_group(self): | |
166 | username = 'test_new_api_user_personal_group' |
|
165 | username = 'test_new_api_user_personal_group' | |
167 | email = username + "@foo.com" |
|
166 | email = username + "@foo.com" | |
168 |
|
167 | |||
169 | id_, params = build_data( |
|
168 | id_, params = build_data( | |
170 | self.apikey, 'create_user', |
|
169 | self.apikey, 'create_user', | |
171 | username=username, |
|
170 | username=username, | |
172 | email=email, extern_name='rhodecode', |
|
171 | email=email, extern_name='rhodecode', | |
173 | create_personal_repo_group=True) |
|
172 | create_personal_repo_group=True) | |
174 | response = api_call(self.app, params) |
|
173 | response = api_call(self.app, params) | |
175 |
|
174 | |||
176 | usr = UserModel().get_by_username(username) |
|
175 | usr = UserModel().get_by_username(username) | |
177 | ret = { |
|
176 | ret = { | |
178 | 'msg': 'created new user `%s`' % (username,), |
|
177 | 'msg': 'created new user `%s`' % (username,), | |
179 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
178 | 'user': jsonify(usr.get_api_data(include_secrets=True)), | |
180 | } |
|
179 | } | |
181 |
|
180 | |||
182 | personal_group = RepoGroup.get_by_group_name(username) |
|
181 | personal_group = RepoGroup.get_by_group_name(username) | |
183 | assert personal_group |
|
182 | assert personal_group | |
184 | assert personal_group.personal == True |
|
183 | assert personal_group.personal == True | |
185 | assert personal_group.user.username == username |
|
184 | assert personal_group.user.username == username | |
186 |
|
185 | |||
187 | try: |
|
186 | try: | |
188 | expected = ret |
|
187 | expected = ret | |
189 | assert_ok(id_, expected, given=response.body) |
|
188 | assert_ok(id_, expected, given=response.body) | |
190 | finally: |
|
189 | finally: | |
191 | fixture.destroy_repo_group(username) |
|
190 | fixture.destroy_repo_group(username) | |
192 | fixture.destroy_user(usr.user_id) |
|
191 | fixture.destroy_user(usr.user_id) | |
193 |
|
192 | |||
194 | @mock.patch.object(UserModel, 'create_or_update', crash) |
|
193 | @mock.patch.object(UserModel, 'create_or_update', crash) | |
195 | def test_api_create_user_when_exception_happened(self): |
|
194 | def test_api_create_user_when_exception_happened(self): | |
196 |
|
195 | |||
197 | username = 'test_new_api_user' |
|
196 | username = 'test_new_api_user' | |
198 | email = username + "@foo.com" |
|
197 | email = username + "@foo.com" | |
199 |
|
198 | |||
200 | id_, params = build_data( |
|
199 | id_, params = build_data( | |
201 | self.apikey, 'create_user', |
|
200 | self.apikey, 'create_user', | |
202 | username=username, |
|
201 | username=username, | |
203 | email=email, |
|
202 | email=email, | |
204 | password='trololo') |
|
203 | password='trololo') | |
205 | response = api_call(self.app, params) |
|
204 | response = api_call(self.app, params) | |
206 | expected = 'failed to create user `%s`' % (username,) |
|
205 | expected = 'failed to create user `%s`' % (username,) | |
207 | assert_error(id_, expected, given=response.body) |
|
206 | assert_error(id_, expected, given=response.body) |
@@ -1,127 +1,126 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.model.user import UserModel |
|
24 | from rhodecode.model.user import UserModel | |
26 | from rhodecode.model.user_group import UserGroupModel |
|
25 | from rhodecode.model.user_group import UserGroupModel | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_ok, crash, jsonify) |
|
27 | build_data, api_call, assert_error, assert_ok, crash, jsonify) | |
29 | from rhodecode.tests.fixture import Fixture |
|
28 | from rhodecode.tests.fixture import Fixture | |
30 |
|
29 | |||
31 |
|
30 | |||
32 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | @pytest.mark.usefixtures("testuser_api", "app") | |
33 | class TestCreateUserGroup(object): |
|
32 | class TestCreateUserGroup(object): | |
34 | fixture = Fixture() |
|
33 | fixture = Fixture() | |
35 |
|
34 | |||
36 | def test_api_create_user_group(self): |
|
35 | def test_api_create_user_group(self): | |
37 | group_name = 'some_new_group' |
|
36 | group_name = 'some_new_group' | |
38 | id_, params = build_data( |
|
37 | id_, params = build_data( | |
39 | self.apikey, 'create_user_group', group_name=group_name) |
|
38 | self.apikey, 'create_user_group', group_name=group_name) | |
40 | response = api_call(self.app, params) |
|
39 | response = api_call(self.app, params) | |
41 |
|
40 | |||
42 | ret = { |
|
41 | ret = { | |
43 | 'msg': 'created new user group `%s`' % (group_name,), |
|
42 | 'msg': 'created new user group `%s`' % (group_name,), | |
44 | 'user_group': jsonify( |
|
43 | 'user_group': jsonify( | |
45 | UserGroupModel() |
|
44 | UserGroupModel() | |
46 | .get_by_name(group_name) |
|
45 | .get_by_name(group_name) | |
47 | .get_api_data() |
|
46 | .get_api_data() | |
48 | ) |
|
47 | ) | |
49 | } |
|
48 | } | |
50 | expected = ret |
|
49 | expected = ret | |
51 | assert_ok(id_, expected, given=response.body) |
|
50 | assert_ok(id_, expected, given=response.body) | |
52 | self.fixture.destroy_user_group(group_name) |
|
51 | self.fixture.destroy_user_group(group_name) | |
53 |
|
52 | |||
54 | def test_api_create_user_group_regular_user(self): |
|
53 | def test_api_create_user_group_regular_user(self): | |
55 | group_name = 'some_new_group' |
|
54 | group_name = 'some_new_group' | |
56 |
|
55 | |||
57 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
56 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
58 | usr.inherit_default_permissions = False |
|
57 | usr.inherit_default_permissions = False | |
59 | Session().add(usr) |
|
58 | Session().add(usr) | |
60 | UserModel().grant_perm( |
|
59 | UserModel().grant_perm( | |
61 | self.TEST_USER_LOGIN, 'hg.usergroup.create.true') |
|
60 | self.TEST_USER_LOGIN, 'hg.usergroup.create.true') | |
62 | Session().commit() |
|
61 | Session().commit() | |
63 |
|
62 | |||
64 | id_, params = build_data( |
|
63 | id_, params = build_data( | |
65 | self.apikey_regular, 'create_user_group', group_name=group_name) |
|
64 | self.apikey_regular, 'create_user_group', group_name=group_name) | |
66 | response = api_call(self.app, params) |
|
65 | response = api_call(self.app, params) | |
67 |
|
66 | |||
68 | expected = { |
|
67 | expected = { | |
69 | 'msg': 'created new user group `%s`' % (group_name,), |
|
68 | 'msg': 'created new user group `%s`' % (group_name,), | |
70 | 'user_group': jsonify( |
|
69 | 'user_group': jsonify( | |
71 | UserGroupModel() |
|
70 | UserGroupModel() | |
72 | .get_by_name(group_name) |
|
71 | .get_by_name(group_name) | |
73 | .get_api_data() |
|
72 | .get_api_data() | |
74 | ) |
|
73 | ) | |
75 | } |
|
74 | } | |
76 | try: |
|
75 | try: | |
77 | assert_ok(id_, expected, given=response.body) |
|
76 | assert_ok(id_, expected, given=response.body) | |
78 | finally: |
|
77 | finally: | |
79 | self.fixture.destroy_user_group(group_name) |
|
78 | self.fixture.destroy_user_group(group_name) | |
80 | UserModel().revoke_perm( |
|
79 | UserModel().revoke_perm( | |
81 | self.TEST_USER_LOGIN, 'hg.usergroup.create.true') |
|
80 | self.TEST_USER_LOGIN, 'hg.usergroup.create.true') | |
82 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
81 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
83 | usr.inherit_default_permissions = True |
|
82 | usr.inherit_default_permissions = True | |
84 | Session().add(usr) |
|
83 | Session().add(usr) | |
85 | Session().commit() |
|
84 | Session().commit() | |
86 |
|
85 | |||
87 | def test_api_create_user_group_regular_user_no_permission(self): |
|
86 | def test_api_create_user_group_regular_user_no_permission(self): | |
88 | group_name = 'some_new_group' |
|
87 | group_name = 'some_new_group' | |
89 | id_, params = build_data( |
|
88 | id_, params = build_data( | |
90 | self.apikey_regular, 'create_user_group', group_name=group_name) |
|
89 | self.apikey_regular, 'create_user_group', group_name=group_name) | |
91 | response = api_call(self.app, params) |
|
90 | response = api_call(self.app, params) | |
92 | expected = "Access was denied to this resource." |
|
91 | expected = "Access was denied to this resource." | |
93 | assert_error(id_, expected, given=response.body) |
|
92 | assert_error(id_, expected, given=response.body) | |
94 |
|
93 | |||
95 | def test_api_create_user_group_that_exist(self, user_util): |
|
94 | def test_api_create_user_group_that_exist(self, user_util): | |
96 | group = user_util.create_user_group() |
|
95 | group = user_util.create_user_group() | |
97 | group_name = group.users_group_name |
|
96 | group_name = group.users_group_name | |
98 |
|
97 | |||
99 | id_, params = build_data( |
|
98 | id_, params = build_data( | |
100 | self.apikey, 'create_user_group', group_name=group_name) |
|
99 | self.apikey, 'create_user_group', group_name=group_name) | |
101 | response = api_call(self.app, params) |
|
100 | response = api_call(self.app, params) | |
102 |
|
101 | |||
103 | expected = "user group `%s` already exist" % (group_name,) |
|
102 | expected = "user group `%s` already exist" % (group_name,) | |
104 | assert_error(id_, expected, given=response.body) |
|
103 | assert_error(id_, expected, given=response.body) | |
105 |
|
104 | |||
106 | @mock.patch.object(UserGroupModel, 'create', crash) |
|
105 | @mock.patch.object(UserGroupModel, 'create', crash) | |
107 | def test_api_create_user_group_exception_occurred(self): |
|
106 | def test_api_create_user_group_exception_occurred(self): | |
108 | group_name = 'exception_happens' |
|
107 | group_name = 'exception_happens' | |
109 | id_, params = build_data( |
|
108 | id_, params = build_data( | |
110 | self.apikey, 'create_user_group', group_name=group_name) |
|
109 | self.apikey, 'create_user_group', group_name=group_name) | |
111 | response = api_call(self.app, params) |
|
110 | response = api_call(self.app, params) | |
112 |
|
111 | |||
113 | expected = 'failed to create group `%s`' % (group_name,) |
|
112 | expected = 'failed to create group `%s`' % (group_name,) | |
114 | assert_error(id_, expected, given=response.body) |
|
113 | assert_error(id_, expected, given=response.body) | |
115 |
|
114 | |||
116 | def test_api_create_user_group_with_wrong_name(self, user_util): |
|
115 | def test_api_create_user_group_with_wrong_name(self, user_util): | |
117 |
|
116 | |||
118 | group_name = 'wrong NAME <>' |
|
117 | group_name = 'wrong NAME <>' | |
119 | id_, params = build_data( |
|
118 | id_, params = build_data( | |
120 | self.apikey, 'create_user_group', group_name=group_name) |
|
119 | self.apikey, 'create_user_group', group_name=group_name) | |
121 | response = api_call(self.app, params) |
|
120 | response = api_call(self.app, params) | |
122 |
|
121 | |||
123 | expected = {"user_group_name": |
|
122 | expected = {"user_group_name": | |
124 | "Allowed in name are letters, numbers, and `-`, `_`, " |
|
123 | "Allowed in name are letters, numbers, and `-`, `_`, " | |
125 | "`.` Name must start with a letter or number. " |
|
124 | "`.` Name must start with a letter or number. " | |
126 | "Got `{}`".format(group_name)} |
|
125 | "Got `{}`".format(group_name)} | |
127 | assert_error(id_, expected, given=response.body) |
|
126 | assert_error(id_, expected, given=response.body) |
@@ -1,61 +1,60 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.gist import GistModel |
|
23 | from rhodecode.model.gist import GistModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestApiDeleteGist(object): |
|
29 | class TestApiDeleteGist(object): | |
31 | def test_api_delete_gist(self, gist_util): |
|
30 | def test_api_delete_gist(self, gist_util): | |
32 | gist_id = gist_util.create_gist().gist_access_id |
|
31 | gist_id = gist_util.create_gist().gist_access_id | |
33 | id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id) |
|
32 | id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id) | |
34 | response = api_call(self.app, params) |
|
33 | response = api_call(self.app, params) | |
35 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)} |
|
34 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)} | |
36 | assert_ok(id_, expected, given=response.body) |
|
35 | assert_ok(id_, expected, given=response.body) | |
37 |
|
36 | |||
38 | def test_api_delete_gist_regular_user(self, gist_util): |
|
37 | def test_api_delete_gist_regular_user(self, gist_util): | |
39 | gist_id = gist_util.create_gist( |
|
38 | gist_id = gist_util.create_gist( | |
40 | owner=self.TEST_USER_LOGIN).gist_access_id |
|
39 | owner=self.TEST_USER_LOGIN).gist_access_id | |
41 | id_, params = build_data( |
|
40 | id_, params = build_data( | |
42 | self.apikey_regular, 'delete_gist', gistid=gist_id) |
|
41 | self.apikey_regular, 'delete_gist', gistid=gist_id) | |
43 | response = api_call(self.app, params) |
|
42 | response = api_call(self.app, params) | |
44 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)} |
|
43 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)} | |
45 | assert_ok(id_, expected, given=response.body) |
|
44 | assert_ok(id_, expected, given=response.body) | |
46 |
|
45 | |||
47 | def test_api_delete_gist_regular_user_no_permission(self, gist_util): |
|
46 | def test_api_delete_gist_regular_user_no_permission(self, gist_util): | |
48 | gist_id = gist_util.create_gist().gist_access_id |
|
47 | gist_id = gist_util.create_gist().gist_access_id | |
49 | id_, params = build_data( |
|
48 | id_, params = build_data( | |
50 | self.apikey_regular, 'delete_gist', gistid=gist_id) |
|
49 | self.apikey_regular, 'delete_gist', gistid=gist_id) | |
51 | response = api_call(self.app, params) |
|
50 | response = api_call(self.app, params) | |
52 | expected = 'gist `%s` does not exist' % (gist_id,) |
|
51 | expected = 'gist `%s` does not exist' % (gist_id,) | |
53 | assert_error(id_, expected, given=response.body) |
|
52 | assert_error(id_, expected, given=response.body) | |
54 |
|
53 | |||
55 | @mock.patch.object(GistModel, 'delete', crash) |
|
54 | @mock.patch.object(GistModel, 'delete', crash) | |
56 | def test_api_delete_gist_exception_occurred(self, gist_util): |
|
55 | def test_api_delete_gist_exception_occurred(self, gist_util): | |
57 | gist_id = gist_util.create_gist().gist_access_id |
|
56 | gist_id = gist_util.create_gist().gist_access_id | |
58 | id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id) |
|
57 | id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id) | |
59 | response = api_call(self.app, params) |
|
58 | response = api_call(self.app, params) | |
60 | expected = 'failed to delete gist ID:%s' % (gist_id,) |
|
59 | expected = 'failed to delete gist ID:%s' % (gist_id,) | |
61 | assert_error(id_, expected, given=response.body) |
|
60 | assert_error(id_, expected, given=response.body) |
@@ -1,74 +1,73 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestApiDeleteRepo(object): |
|
29 | class TestApiDeleteRepo(object): | |
31 | def test_api_delete_repo(self, backend): |
|
30 | def test_api_delete_repo(self, backend): | |
32 | repo = backend.create_repo() |
|
31 | repo = backend.create_repo() | |
33 | repo_name = repo.repo_name |
|
32 | repo_name = repo.repo_name | |
34 | id_, params = build_data( |
|
33 | id_, params = build_data( | |
35 | self.apikey, 'delete_repo', repoid=repo.repo_name, ) |
|
34 | self.apikey, 'delete_repo', repoid=repo.repo_name, ) | |
36 | response = api_call(self.app, params) |
|
35 | response = api_call(self.app, params) | |
37 |
|
36 | |||
38 | expected = { |
|
37 | expected = { | |
39 | 'msg': 'Deleted repository `%s`' % (repo_name,), |
|
38 | 'msg': 'Deleted repository `%s`' % (repo_name,), | |
40 | 'success': True |
|
39 | 'success': True | |
41 | } |
|
40 | } | |
42 | assert_ok(id_, expected, given=response.body) |
|
41 | assert_ok(id_, expected, given=response.body) | |
43 |
|
42 | |||
44 | def test_api_delete_repo_by_non_admin(self, backend, user_regular): |
|
43 | def test_api_delete_repo_by_non_admin(self, backend, user_regular): | |
45 | repo = backend.create_repo(cur_user=user_regular.username) |
|
44 | repo = backend.create_repo(cur_user=user_regular.username) | |
46 | repo_name = repo.repo_name |
|
45 | repo_name = repo.repo_name | |
47 | id_, params = build_data( |
|
46 | id_, params = build_data( | |
48 | user_regular.api_key, 'delete_repo', repoid=repo.repo_name, ) |
|
47 | user_regular.api_key, 'delete_repo', repoid=repo.repo_name, ) | |
49 | response = api_call(self.app, params) |
|
48 | response = api_call(self.app, params) | |
50 |
|
49 | |||
51 | expected = { |
|
50 | expected = { | |
52 | 'msg': 'Deleted repository `%s`' % (repo_name,), |
|
51 | 'msg': 'Deleted repository `%s`' % (repo_name,), | |
53 | 'success': True |
|
52 | 'success': True | |
54 | } |
|
53 | } | |
55 | assert_ok(id_, expected, given=response.body) |
|
54 | assert_ok(id_, expected, given=response.body) | |
56 |
|
55 | |||
57 | def test_api_delete_repo_by_non_admin_no_permission(self, backend): |
|
56 | def test_api_delete_repo_by_non_admin_no_permission(self, backend): | |
58 | repo = backend.create_repo() |
|
57 | repo = backend.create_repo() | |
59 | repo_name = repo.repo_name |
|
58 | repo_name = repo.repo_name | |
60 | id_, params = build_data( |
|
59 | id_, params = build_data( | |
61 | self.apikey_regular, 'delete_repo', repoid=repo.repo_name, ) |
|
60 | self.apikey_regular, 'delete_repo', repoid=repo.repo_name, ) | |
62 | response = api_call(self.app, params) |
|
61 | response = api_call(self.app, params) | |
63 | expected = 'repository `%s` does not exist' % (repo_name) |
|
62 | expected = 'repository `%s` does not exist' % (repo_name) | |
64 | assert_error(id_, expected, given=response.body) |
|
63 | assert_error(id_, expected, given=response.body) | |
65 |
|
64 | |||
66 | def test_api_delete_repo_exception_occurred(self, backend): |
|
65 | def test_api_delete_repo_exception_occurred(self, backend): | |
67 | repo = backend.create_repo() |
|
66 | repo = backend.create_repo() | |
68 | repo_name = repo.repo_name |
|
67 | repo_name = repo.repo_name | |
69 | id_, params = build_data( |
|
68 | id_, params = build_data( | |
70 | self.apikey, 'delete_repo', repoid=repo.repo_name, ) |
|
69 | self.apikey, 'delete_repo', repoid=repo.repo_name, ) | |
71 | with mock.patch.object(RepoModel, 'delete', crash): |
|
70 | with mock.patch.object(RepoModel, 'delete', crash): | |
72 | response = api_call(self.app, params) |
|
71 | response = api_call(self.app, params) | |
73 | expected = 'failed to delete repository `%s`' % (repo_name,) |
|
72 | expected = 'failed to delete repository `%s`' % (repo_name,) | |
74 | assert_error(id_, expected, given=response.body) |
|
73 | assert_error(id_, expected, given=response.body) |
@@ -1,86 +1,85 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo_group import RepoGroupModel |
|
23 | from rhodecode.model.repo_group import RepoGroupModel | |
25 | from rhodecode.model.user import UserModel |
|
24 | from rhodecode.model.user import UserModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok) |
|
26 | build_data, api_call, assert_error, assert_ok) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestApiDeleteRepoGroup(object): |
|
30 | class TestApiDeleteRepoGroup(object): | |
32 | def test_api_delete_repo_group(self, user_util): |
|
31 | def test_api_delete_repo_group(self, user_util): | |
33 | repo_group = user_util.create_repo_group(auto_cleanup=False) |
|
32 | repo_group = user_util.create_repo_group(auto_cleanup=False) | |
34 | repo_group_name = repo_group.group_name |
|
33 | repo_group_name = repo_group.group_name | |
35 | repo_group_id = repo_group.group_id |
|
34 | repo_group_id = repo_group.group_id | |
36 | id_, params = build_data( |
|
35 | id_, params = build_data( | |
37 | self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) |
|
36 | self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) | |
38 | response = api_call(self.app, params) |
|
37 | response = api_call(self.app, params) | |
39 |
|
38 | |||
40 | ret = { |
|
39 | ret = { | |
41 | 'msg': 'deleted repo group ID:%s %s' % ( |
|
40 | 'msg': 'deleted repo group ID:%s %s' % ( | |
42 | repo_group_id, repo_group_name |
|
41 | repo_group_id, repo_group_name | |
43 | ), |
|
42 | ), | |
44 | 'repo_group': None |
|
43 | 'repo_group': None | |
45 | } |
|
44 | } | |
46 | expected = ret |
|
45 | expected = ret | |
47 | assert_ok(id_, expected, given=response.body) |
|
46 | assert_ok(id_, expected, given=response.body) | |
48 | gr = RepoGroupModel()._get_repo_group(repo_group_name) |
|
47 | gr = RepoGroupModel()._get_repo_group(repo_group_name) | |
49 | assert gr is None |
|
48 | assert gr is None | |
50 |
|
49 | |||
51 | def test_api_delete_repo_group_regular_user(self, user_util): |
|
50 | def test_api_delete_repo_group_regular_user(self, user_util): | |
52 | repo_group = user_util.create_repo_group(auto_cleanup=False) |
|
51 | repo_group = user_util.create_repo_group(auto_cleanup=False) | |
53 | repo_group_name = repo_group.group_name |
|
52 | repo_group_name = repo_group.group_name | |
54 | repo_group_id = repo_group.group_id |
|
53 | repo_group_id = repo_group.group_id | |
55 |
|
54 | |||
56 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
55 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
57 | user_util.grant_user_permission_to_repo_group( |
|
56 | user_util.grant_user_permission_to_repo_group( | |
58 | repo_group, user, 'group.admin') |
|
57 | repo_group, user, 'group.admin') | |
59 |
|
58 | |||
60 | id_, params = build_data( |
|
59 | id_, params = build_data( | |
61 | self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) |
|
60 | self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) | |
62 | response = api_call(self.app, params) |
|
61 | response = api_call(self.app, params) | |
63 |
|
62 | |||
64 | ret = { |
|
63 | ret = { | |
65 | 'msg': 'deleted repo group ID:%s %s' % ( |
|
64 | 'msg': 'deleted repo group ID:%s %s' % ( | |
66 | repo_group_id, repo_group_name |
|
65 | repo_group_id, repo_group_name | |
67 | ), |
|
66 | ), | |
68 | 'repo_group': None |
|
67 | 'repo_group': None | |
69 | } |
|
68 | } | |
70 | expected = ret |
|
69 | expected = ret | |
71 | assert_ok(id_, expected, given=response.body) |
|
70 | assert_ok(id_, expected, given=response.body) | |
72 | gr = RepoGroupModel()._get_repo_group(repo_group_name) |
|
71 | gr = RepoGroupModel()._get_repo_group(repo_group_name) | |
73 | assert gr is None |
|
72 | assert gr is None | |
74 |
|
73 | |||
75 | def test_api_delete_repo_group_regular_user_no_permission(self, user_util): |
|
74 | def test_api_delete_repo_group_regular_user_no_permission(self, user_util): | |
76 | repo_group = user_util.create_repo_group() |
|
75 | repo_group = user_util.create_repo_group() | |
77 | repo_group_name = repo_group.group_name |
|
76 | repo_group_name = repo_group.group_name | |
78 |
|
77 | |||
79 | id_, params = build_data( |
|
78 | id_, params = build_data( | |
80 | self.apikey_regular, 'delete_repo_group', |
|
79 | self.apikey_regular, 'delete_repo_group', | |
81 | repogroupid=repo_group_name, ) |
|
80 | repogroupid=repo_group_name, ) | |
82 | response = api_call(self.app, params) |
|
81 | response = api_call(self.app, params) | |
83 |
|
82 | |||
84 | expected = 'repository group `%s` does not exist' % ( |
|
83 | expected = 'repository group `%s` does not exist' % ( | |
85 | repo_group_name,) |
|
84 | repo_group_name,) | |
86 | assert_error(id_, expected, given=response.body) |
|
85 | assert_error(id_, expected, given=response.body) |
@@ -1,57 +1,56 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import mock |
|
21 | import mock | |
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.model.user import UserModel |
|
24 | from rhodecode.model.user import UserModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_ok, assert_error, crash) |
|
26 | build_data, api_call, assert_ok, assert_error, crash) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestDeleteUser(object): |
|
30 | class TestDeleteUser(object): | |
32 | def test_api_delete_user(self, user_util): |
|
31 | def test_api_delete_user(self, user_util): | |
33 | usr = user_util.create_user(auto_cleanup=False) |
|
32 | usr = user_util.create_user(auto_cleanup=False) | |
34 |
|
33 | |||
35 | username = usr.username |
|
34 | username = usr.username | |
36 | usr_id = usr.user_id |
|
35 | usr_id = usr.user_id | |
37 |
|
36 | |||
38 | id_, params = build_data(self.apikey, 'delete_user', userid=username) |
|
37 | id_, params = build_data(self.apikey, 'delete_user', userid=username) | |
39 | response = api_call(self.app, params) |
|
38 | response = api_call(self.app, params) | |
40 |
|
39 | |||
41 | ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username), |
|
40 | ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username), | |
42 | 'user': None} |
|
41 | 'user': None} | |
43 | expected = ret |
|
42 | expected = ret | |
44 | assert_ok(id_, expected, given=response.body) |
|
43 | assert_ok(id_, expected, given=response.body) | |
45 |
|
44 | |||
46 | @mock.patch.object(UserModel, 'delete', crash) |
|
45 | @mock.patch.object(UserModel, 'delete', crash) | |
47 | def test_api_delete_user_when_exception_happened(self, user_util): |
|
46 | def test_api_delete_user_when_exception_happened(self, user_util): | |
48 | usr = user_util.create_user() |
|
47 | usr = user_util.create_user() | |
49 | username = usr.username |
|
48 | username = usr.username | |
50 |
|
49 | |||
51 | id_, params = build_data( |
|
50 | id_, params = build_data( | |
52 | self.apikey, 'delete_user', userid=username, ) |
|
51 | self.apikey, 'delete_user', userid=username, ) | |
53 | response = api_call(self.app, params) |
|
52 | response = api_call(self.app, params) | |
54 | ret = 'failed to delete user ID:%s %s' % (usr.user_id, |
|
53 | ret = 'failed to delete user ID:%s %s' % (usr.user_id, | |
55 | usr.username) |
|
54 | usr.username) | |
56 | expected = ret |
|
55 | expected = ret | |
57 | assert_error(id_, expected, given=response.body) |
|
56 | assert_error(id_, expected, given=response.body) |
@@ -1,106 +1,105 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import mock |
|
21 | import mock | |
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.model.user import UserModel |
|
24 | from rhodecode.model.user import UserModel | |
26 | from rhodecode.model.user_group import UserGroupModel |
|
25 | from rhodecode.model.user_group import UserGroupModel | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | build_data, api_call, assert_error, assert_ok, crash) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestDeleteUserGroup(object): |
|
31 | class TestDeleteUserGroup(object): | |
33 | def test_api_delete_user_group(self, user_util): |
|
32 | def test_api_delete_user_group(self, user_util): | |
34 | user_group = user_util.create_user_group(auto_cleanup=False) |
|
33 | user_group = user_util.create_user_group(auto_cleanup=False) | |
35 | group_name = user_group.users_group_name |
|
34 | group_name = user_group.users_group_name | |
36 | group_id = user_group.users_group_id |
|
35 | group_id = user_group.users_group_id | |
37 | id_, params = build_data( |
|
36 | id_, params = build_data( | |
38 | self.apikey, 'delete_user_group', usergroupid=group_name) |
|
37 | self.apikey, 'delete_user_group', usergroupid=group_name) | |
39 | response = api_call(self.app, params) |
|
38 | response = api_call(self.app, params) | |
40 |
|
39 | |||
41 | expected = { |
|
40 | expected = { | |
42 | 'user_group': None, |
|
41 | 'user_group': None, | |
43 | 'msg': 'deleted user group ID:%s %s' % (group_id, group_name) |
|
42 | 'msg': 'deleted user group ID:%s %s' % (group_id, group_name) | |
44 | } |
|
43 | } | |
45 | assert_ok(id_, expected, given=response.body) |
|
44 | assert_ok(id_, expected, given=response.body) | |
46 |
|
45 | |||
47 | def test_api_delete_user_group_regular_user(self, user_util): |
|
46 | def test_api_delete_user_group_regular_user(self, user_util): | |
48 | ugroup = user_util.create_user_group(auto_cleanup=False) |
|
47 | ugroup = user_util.create_user_group(auto_cleanup=False) | |
49 | group_name = ugroup.users_group_name |
|
48 | group_name = ugroup.users_group_name | |
50 | group_id = ugroup.users_group_id |
|
49 | group_id = ugroup.users_group_id | |
51 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
50 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
52 |
|
51 | |||
53 | user_util.grant_user_permission_to_user_group( |
|
52 | user_util.grant_user_permission_to_user_group( | |
54 | ugroup, user, 'usergroup.admin') |
|
53 | ugroup, user, 'usergroup.admin') | |
55 |
|
54 | |||
56 | id_, params = build_data( |
|
55 | id_, params = build_data( | |
57 | self.apikey_regular, 'delete_user_group', usergroupid=group_name) |
|
56 | self.apikey_regular, 'delete_user_group', usergroupid=group_name) | |
58 | response = api_call(self.app, params) |
|
57 | response = api_call(self.app, params) | |
59 |
|
58 | |||
60 | expected = { |
|
59 | expected = { | |
61 | 'user_group': None, |
|
60 | 'user_group': None, | |
62 | 'msg': 'deleted user group ID:%s %s' % (group_id, group_name) |
|
61 | 'msg': 'deleted user group ID:%s %s' % (group_id, group_name) | |
63 | } |
|
62 | } | |
64 | assert_ok(id_, expected, given=response.body) |
|
63 | assert_ok(id_, expected, given=response.body) | |
65 |
|
64 | |||
66 | def test_api_delete_user_group_regular_user_no_permission(self, user_util): |
|
65 | def test_api_delete_user_group_regular_user_no_permission(self, user_util): | |
67 | user_group = user_util.create_user_group() |
|
66 | user_group = user_util.create_user_group() | |
68 | group_name = user_group.users_group_name |
|
67 | group_name = user_group.users_group_name | |
69 |
|
68 | |||
70 | id_, params = build_data( |
|
69 | id_, params = build_data( | |
71 | self.apikey_regular, 'delete_user_group', usergroupid=group_name) |
|
70 | self.apikey_regular, 'delete_user_group', usergroupid=group_name) | |
72 | response = api_call(self.app, params) |
|
71 | response = api_call(self.app, params) | |
73 |
|
72 | |||
74 | expected = 'user group `%s` does not exist' % (group_name) |
|
73 | expected = 'user group `%s` does not exist' % (group_name) | |
75 | assert_error(id_, expected, given=response.body) |
|
74 | assert_error(id_, expected, given=response.body) | |
76 |
|
75 | |||
77 | def test_api_delete_user_group_that_is_assigned(self, backend, user_util): |
|
76 | def test_api_delete_user_group_that_is_assigned(self, backend, user_util): | |
78 | ugroup = user_util.create_user_group() |
|
77 | ugroup = user_util.create_user_group() | |
79 | group_name = ugroup.users_group_name |
|
78 | group_name = ugroup.users_group_name | |
80 | repo = backend.create_repo() |
|
79 | repo = backend.create_repo() | |
81 |
|
80 | |||
82 | ugr_to_perm = user_util.grant_user_group_permission_to_repo( |
|
81 | ugr_to_perm = user_util.grant_user_group_permission_to_repo( | |
83 | repo, ugroup, 'repository.write') |
|
82 | repo, ugroup, 'repository.write') | |
84 | msg = 'UserGroup assigned to %s' % (ugr_to_perm.repository) |
|
83 | msg = 'UserGroup assigned to %s' % (ugr_to_perm.repository) | |
85 |
|
84 | |||
86 | id_, params = build_data( |
|
85 | id_, params = build_data( | |
87 | self.apikey, 'delete_user_group', |
|
86 | self.apikey, 'delete_user_group', | |
88 | usergroupid=group_name) |
|
87 | usergroupid=group_name) | |
89 | response = api_call(self.app, params) |
|
88 | response = api_call(self.app, params) | |
90 |
|
89 | |||
91 | expected = msg |
|
90 | expected = msg | |
92 | assert_error(id_, expected, given=response.body) |
|
91 | assert_error(id_, expected, given=response.body) | |
93 |
|
92 | |||
94 | def test_api_delete_user_group_exception_occurred(self, user_util): |
|
93 | def test_api_delete_user_group_exception_occurred(self, user_util): | |
95 | ugroup = user_util.create_user_group() |
|
94 | ugroup = user_util.create_user_group() | |
96 | group_name = ugroup.users_group_name |
|
95 | group_name = ugroup.users_group_name | |
97 | group_id = ugroup.users_group_id |
|
96 | group_id = ugroup.users_group_id | |
98 | id_, params = build_data( |
|
97 | id_, params = build_data( | |
99 | self.apikey, 'delete_user_group', |
|
98 | self.apikey, 'delete_user_group', | |
100 | usergroupid=group_name) |
|
99 | usergroupid=group_name) | |
101 |
|
100 | |||
102 | with mock.patch.object(UserGroupModel, 'delete', crash): |
|
101 | with mock.patch.object(UserGroupModel, 'delete', crash): | |
103 | response = api_call(self.app, params) |
|
102 | response = api_call(self.app, params) | |
104 | expected = 'failed to delete user group ID:%s %s' % ( |
|
103 | expected = 'failed to delete user group ID:%s %s' % ( | |
105 | group_id, group_name) |
|
104 | group_id, group_name) | |
106 | assert_error(id_, expected, given=response.body) |
|
105 | assert_error(id_, expected, given=response.body) |
@@ -1,79 +1,78 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.api.views import deprecated_api |
|
23 | from rhodecode.api.views import deprecated_api | |
25 | from rhodecode.lib.ext_json import json |
|
24 | from rhodecode.lib.ext_json import json | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call) |
|
26 | build_data, api_call) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestCommitComment(object): |
|
30 | class TestCommitComment(object): | |
32 | def test_deprecated_message_in_docstring(self): |
|
31 | def test_deprecated_message_in_docstring(self): | |
33 | docstring = deprecated_api.changeset_comment.__doc__ |
|
32 | docstring = deprecated_api.changeset_comment.__doc__ | |
34 | assert '.. deprecated:: 3.4.0' in docstring |
|
33 | assert '.. deprecated:: 3.4.0' in docstring | |
35 | assert 'Please use method `comment_commit` instead.' in docstring |
|
34 | assert 'Please use method `comment_commit` instead.' in docstring | |
36 |
|
35 | |||
37 | def test_deprecated_message_in_retvalue(self): |
|
36 | def test_deprecated_message_in_retvalue(self): | |
38 |
|
37 | |||
39 | id_, params = build_data( |
|
38 | id_, params = build_data( | |
40 | self.apikey, 'show_ip') |
|
39 | self.apikey, 'show_ip') | |
41 | response = api_call(self.app, params) |
|
40 | response = api_call(self.app, params) | |
42 |
|
41 | |||
43 | expected = { |
|
42 | expected = { | |
44 | 'id': id_, |
|
43 | 'id': id_, | |
45 | 'error': None, |
|
44 | 'error': None, | |
46 | 'result': json.loads(response.body)['result'], |
|
45 | 'result': json.loads(response.body)['result'], | |
47 | 'DEPRECATION_WARNING': |
|
46 | 'DEPRECATION_WARNING': | |
48 | 'DEPRECATED METHOD Please use method `get_ip` instead.' |
|
47 | 'DEPRECATED METHOD Please use method `get_ip` instead.' | |
49 | } |
|
48 | } | |
50 | assert expected == json.loads(response.body) |
|
49 | assert expected == json.loads(response.body) | |
51 |
|
50 | |||
52 | # def test_calls_comment_commit(self, backend, no_notifications): |
|
51 | # def test_calls_comment_commit(self, backend, no_notifications): | |
53 | # data = { |
|
52 | # data = { | |
54 | # 'repoid': backend.repo_name, |
|
53 | # 'repoid': backend.repo_name, | |
55 | # 'status': ChangesetStatus.STATUS_APPROVED, |
|
54 | # 'status': ChangesetStatus.STATUS_APPROVED, | |
56 | # 'message': 'Approved', |
|
55 | # 'message': 'Approved', | |
57 | # 'revision': 'tip' |
|
56 | # 'revision': 'tip' | |
58 | # } |
|
57 | # } | |
59 | # with patch.object(repo_api, 'changeset_commit') as comment_mock: |
|
58 | # with patch.object(repo_api, 'changeset_commit') as comment_mock: | |
60 | # id_, params = build_data(self.apikey, 'comment_commit', **data) |
|
59 | # id_, params = build_data(self.apikey, 'comment_commit', **data) | |
61 | # api_call(self.app, params) |
|
60 | # api_call(self.app, params) | |
62 | # |
|
61 | # | |
63 | # _, call_args = comment_mock.call_args |
|
62 | # _, call_args = comment_mock.call_args | |
64 | # data['commit_id'] = data.pop('revision') |
|
63 | # data['commit_id'] = data.pop('revision') | |
65 | # for key in data: |
|
64 | # for key in data: | |
66 | # assert call_args[key] == data[key] |
|
65 | # assert call_args[key] == data[key] | |
67 |
|
66 | |||
68 | # def test_warning_log_contains_deprecation_message(self): |
|
67 | # def test_warning_log_contains_deprecation_message(self): | |
69 | # api = self.SampleApi() |
|
68 | # api = self.SampleApi() | |
70 | # with patch.object(utils, 'log') as log_mock: |
|
69 | # with patch.object(utils, 'log') as log_mock: | |
71 | # api.api_method() |
|
70 | # api.api_method() | |
72 | # |
|
71 | # | |
73 | # assert log_mock.warning.call_count == 1 |
|
72 | # assert log_mock.warning.call_count == 1 | |
74 | # call_args = log_mock.warning.call_args[0] |
|
73 | # call_args = log_mock.warning.call_args[0] | |
75 | # assert ( |
|
74 | # assert ( | |
76 | # call_args[0] == |
|
75 | # call_args[0] == | |
77 | # 'DEPRECATED API CALL on function %s, please use `%s` instead') |
|
76 | # 'DEPRECATED API CALL on function %s, please use `%s` instead') | |
78 | # assert call_args[1].__name__ == 'api_method' |
|
77 | # assert call_args[1].__name__ == 'api_method' | |
79 | # assert call_args[2] == 'new_method' No newline at end of file |
|
78 | # assert call_args[2] == 'new_method' |
@@ -1,279 +1,278 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import mock |
|
21 | import mock | |
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.model.meta import Session |
|
24 | from rhodecode.model.meta import Session | |
26 | from rhodecode.model.repo import RepoModel |
|
25 | from rhodecode.model.repo import RepoModel | |
27 | from rhodecode.model.repo_group import RepoGroupModel |
|
26 | from rhodecode.model.repo_group import RepoGroupModel | |
28 | from rhodecode.model.user import UserModel |
|
27 | from rhodecode.model.user import UserModel | |
29 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
28 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
30 | from rhodecode.api.tests.utils import ( |
|
29 | from rhodecode.api.tests.utils import ( | |
31 | build_data, api_call, assert_error, assert_ok, crash) |
|
30 | build_data, api_call, assert_error, assert_ok, crash) | |
32 | from rhodecode.tests.fixture import Fixture |
|
31 | from rhodecode.tests.fixture import Fixture | |
33 |
|
32 | |||
34 |
|
33 | |||
35 | fixture = Fixture() |
|
34 | fixture = Fixture() | |
36 |
|
35 | |||
37 |
|
36 | |||
38 | @pytest.mark.usefixtures("testuser_api", "app") |
|
37 | @pytest.mark.usefixtures("testuser_api", "app") | |
39 | class TestApiForkRepo(object): |
|
38 | class TestApiForkRepo(object): | |
40 | def test_api_fork_repo(self, backend): |
|
39 | def test_api_fork_repo(self, backend): | |
41 | source_name = backend['minimal'].repo_name |
|
40 | source_name = backend['minimal'].repo_name | |
42 | fork_name = backend.new_repo_name() |
|
41 | fork_name = backend.new_repo_name() | |
43 |
|
42 | |||
44 | id_, params = build_data( |
|
43 | id_, params = build_data( | |
45 | self.apikey, 'fork_repo', |
|
44 | self.apikey, 'fork_repo', | |
46 | repoid=source_name, |
|
45 | repoid=source_name, | |
47 | fork_name=fork_name, |
|
46 | fork_name=fork_name, | |
48 | owner=TEST_USER_ADMIN_LOGIN) |
|
47 | owner=TEST_USER_ADMIN_LOGIN) | |
49 | response = api_call(self.app, params) |
|
48 | response = api_call(self.app, params) | |
50 |
|
49 | |||
51 | expected = { |
|
50 | expected = { | |
52 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
51 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), | |
53 | 'success': True, |
|
52 | 'success': True, | |
54 | 'task': None, |
|
53 | 'task': None, | |
55 | } |
|
54 | } | |
56 | try: |
|
55 | try: | |
57 | assert_ok(id_, expected, given=response.body) |
|
56 | assert_ok(id_, expected, given=response.body) | |
58 | finally: |
|
57 | finally: | |
59 | fixture.destroy_repo(fork_name) |
|
58 | fixture.destroy_repo(fork_name) | |
60 |
|
59 | |||
61 | def test_api_fork_repo_into_group(self, backend, user_util): |
|
60 | def test_api_fork_repo_into_group(self, backend, user_util): | |
62 | source_name = backend['minimal'].repo_name |
|
61 | source_name = backend['minimal'].repo_name | |
63 | repo_group = user_util.create_repo_group() |
|
62 | repo_group = user_util.create_repo_group() | |
64 | fork_name = '%s/api-repo-fork' % repo_group.group_name |
|
63 | fork_name = '%s/api-repo-fork' % repo_group.group_name | |
65 | id_, params = build_data( |
|
64 | id_, params = build_data( | |
66 | self.apikey, 'fork_repo', |
|
65 | self.apikey, 'fork_repo', | |
67 | repoid=source_name, |
|
66 | repoid=source_name, | |
68 | fork_name=fork_name, |
|
67 | fork_name=fork_name, | |
69 | owner=TEST_USER_ADMIN_LOGIN) |
|
68 | owner=TEST_USER_ADMIN_LOGIN) | |
70 | response = api_call(self.app, params) |
|
69 | response = api_call(self.app, params) | |
71 |
|
70 | |||
72 | ret = { |
|
71 | ret = { | |
73 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
72 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), | |
74 | 'success': True, |
|
73 | 'success': True, | |
75 | 'task': None, |
|
74 | 'task': None, | |
76 | } |
|
75 | } | |
77 | expected = ret |
|
76 | expected = ret | |
78 | try: |
|
77 | try: | |
79 | assert_ok(id_, expected, given=response.body) |
|
78 | assert_ok(id_, expected, given=response.body) | |
80 | finally: |
|
79 | finally: | |
81 | fixture.destroy_repo(fork_name) |
|
80 | fixture.destroy_repo(fork_name) | |
82 |
|
81 | |||
83 | def test_api_fork_repo_non_admin(self, backend): |
|
82 | def test_api_fork_repo_non_admin(self, backend): | |
84 | source_name = backend['minimal'].repo_name |
|
83 | source_name = backend['minimal'].repo_name | |
85 | fork_name = backend.new_repo_name() |
|
84 | fork_name = backend.new_repo_name() | |
86 |
|
85 | |||
87 | id_, params = build_data( |
|
86 | id_, params = build_data( | |
88 | self.apikey_regular, 'fork_repo', |
|
87 | self.apikey_regular, 'fork_repo', | |
89 | repoid=source_name, |
|
88 | repoid=source_name, | |
90 | fork_name=fork_name) |
|
89 | fork_name=fork_name) | |
91 | response = api_call(self.app, params) |
|
90 | response = api_call(self.app, params) | |
92 |
|
91 | |||
93 | expected = { |
|
92 | expected = { | |
94 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
93 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), | |
95 | 'success': True, |
|
94 | 'success': True, | |
96 | 'task': None, |
|
95 | 'task': None, | |
97 | } |
|
96 | } | |
98 | try: |
|
97 | try: | |
99 | assert_ok(id_, expected, given=response.body) |
|
98 | assert_ok(id_, expected, given=response.body) | |
100 | finally: |
|
99 | finally: | |
101 | fixture.destroy_repo(fork_name) |
|
100 | fixture.destroy_repo(fork_name) | |
102 |
|
101 | |||
103 | def test_api_fork_repo_non_admin_into_group_no_permission(self, backend, user_util): |
|
102 | def test_api_fork_repo_non_admin_into_group_no_permission(self, backend, user_util): | |
104 | source_name = backend['minimal'].repo_name |
|
103 | source_name = backend['minimal'].repo_name | |
105 | repo_group = user_util.create_repo_group() |
|
104 | repo_group = user_util.create_repo_group() | |
106 | repo_group_name = repo_group.group_name |
|
105 | repo_group_name = repo_group.group_name | |
107 | fork_name = '%s/api-repo-fork' % repo_group_name |
|
106 | fork_name = '%s/api-repo-fork' % repo_group_name | |
108 |
|
107 | |||
109 | id_, params = build_data( |
|
108 | id_, params = build_data( | |
110 | self.apikey_regular, 'fork_repo', |
|
109 | self.apikey_regular, 'fork_repo', | |
111 | repoid=source_name, |
|
110 | repoid=source_name, | |
112 | fork_name=fork_name) |
|
111 | fork_name=fork_name) | |
113 | response = api_call(self.app, params) |
|
112 | response = api_call(self.app, params) | |
114 |
|
113 | |||
115 | expected = { |
|
114 | expected = { | |
116 | 'repo_group': 'Repository group `{}` does not exist'.format( |
|
115 | 'repo_group': 'Repository group `{}` does not exist'.format( | |
117 | repo_group_name)} |
|
116 | repo_group_name)} | |
118 | try: |
|
117 | try: | |
119 | assert_error(id_, expected, given=response.body) |
|
118 | assert_error(id_, expected, given=response.body) | |
120 | finally: |
|
119 | finally: | |
121 | fixture.destroy_repo(fork_name) |
|
120 | fixture.destroy_repo(fork_name) | |
122 |
|
121 | |||
123 | def test_api_fork_repo_non_admin_into_group(self, backend, user_util): |
|
122 | def test_api_fork_repo_non_admin_into_group(self, backend, user_util): | |
124 | source_name = backend['minimal'].repo_name |
|
123 | source_name = backend['minimal'].repo_name | |
125 | repo_group = user_util.create_repo_group() |
|
124 | repo_group = user_util.create_repo_group() | |
126 | fork_name = '%s/api-repo-fork' % repo_group.group_name |
|
125 | fork_name = '%s/api-repo-fork' % repo_group.group_name | |
127 |
|
126 | |||
128 | RepoGroupModel().grant_user_permission( |
|
127 | RepoGroupModel().grant_user_permission( | |
129 | repo_group, self.TEST_USER_LOGIN, 'group.admin') |
|
128 | repo_group, self.TEST_USER_LOGIN, 'group.admin') | |
130 | Session().commit() |
|
129 | Session().commit() | |
131 |
|
130 | |||
132 | id_, params = build_data( |
|
131 | id_, params = build_data( | |
133 | self.apikey_regular, 'fork_repo', |
|
132 | self.apikey_regular, 'fork_repo', | |
134 | repoid=source_name, |
|
133 | repoid=source_name, | |
135 | fork_name=fork_name) |
|
134 | fork_name=fork_name) | |
136 | response = api_call(self.app, params) |
|
135 | response = api_call(self.app, params) | |
137 |
|
136 | |||
138 | expected = { |
|
137 | expected = { | |
139 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
138 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), | |
140 | 'success': True, |
|
139 | 'success': True, | |
141 | 'task': None, |
|
140 | 'task': None, | |
142 | } |
|
141 | } | |
143 | try: |
|
142 | try: | |
144 | assert_ok(id_, expected, given=response.body) |
|
143 | assert_ok(id_, expected, given=response.body) | |
145 | finally: |
|
144 | finally: | |
146 | fixture.destroy_repo(fork_name) |
|
145 | fixture.destroy_repo(fork_name) | |
147 |
|
146 | |||
148 | def test_api_fork_repo_non_admin_specify_owner(self, backend): |
|
147 | def test_api_fork_repo_non_admin_specify_owner(self, backend): | |
149 | source_name = backend['minimal'].repo_name |
|
148 | source_name = backend['minimal'].repo_name | |
150 | fork_name = backend.new_repo_name() |
|
149 | fork_name = backend.new_repo_name() | |
151 | id_, params = build_data( |
|
150 | id_, params = build_data( | |
152 | self.apikey_regular, 'fork_repo', |
|
151 | self.apikey_regular, 'fork_repo', | |
153 | repoid=source_name, |
|
152 | repoid=source_name, | |
154 | fork_name=fork_name, |
|
153 | fork_name=fork_name, | |
155 | owner=TEST_USER_ADMIN_LOGIN) |
|
154 | owner=TEST_USER_ADMIN_LOGIN) | |
156 | response = api_call(self.app, params) |
|
155 | response = api_call(self.app, params) | |
157 | expected = 'Only RhodeCode super-admin can specify `owner` param' |
|
156 | expected = 'Only RhodeCode super-admin can specify `owner` param' | |
158 | assert_error(id_, expected, given=response.body) |
|
157 | assert_error(id_, expected, given=response.body) | |
159 |
|
158 | |||
160 | def test_api_fork_repo_non_admin_no_permission_of_source_repo( |
|
159 | def test_api_fork_repo_non_admin_no_permission_of_source_repo( | |
161 | self, backend): |
|
160 | self, backend): | |
162 | source_name = backend['minimal'].repo_name |
|
161 | source_name = backend['minimal'].repo_name | |
163 | RepoModel().grant_user_permission(repo=source_name, |
|
162 | RepoModel().grant_user_permission(repo=source_name, | |
164 | user=self.TEST_USER_LOGIN, |
|
163 | user=self.TEST_USER_LOGIN, | |
165 | perm='repository.none') |
|
164 | perm='repository.none') | |
166 | fork_name = backend.new_repo_name() |
|
165 | fork_name = backend.new_repo_name() | |
167 | id_, params = build_data( |
|
166 | id_, params = build_data( | |
168 | self.apikey_regular, 'fork_repo', |
|
167 | self.apikey_regular, 'fork_repo', | |
169 | repoid=backend.repo_name, |
|
168 | repoid=backend.repo_name, | |
170 | fork_name=fork_name) |
|
169 | fork_name=fork_name) | |
171 | response = api_call(self.app, params) |
|
170 | response = api_call(self.app, params) | |
172 | expected = 'repository `%s` does not exist' % (backend.repo_name) |
|
171 | expected = 'repository `%s` does not exist' % (backend.repo_name) | |
173 | assert_error(id_, expected, given=response.body) |
|
172 | assert_error(id_, expected, given=response.body) | |
174 |
|
173 | |||
175 | def test_api_fork_repo_non_admin_no_permission_to_fork_to_root_level( |
|
174 | def test_api_fork_repo_non_admin_no_permission_to_fork_to_root_level( | |
176 | self, backend, user_util): |
|
175 | self, backend, user_util): | |
177 |
|
176 | |||
178 | regular_user = user_util.create_user() |
|
177 | regular_user = user_util.create_user() | |
179 | regular_user_api_key = regular_user.api_key |
|
178 | regular_user_api_key = regular_user.api_key | |
180 | usr = UserModel().get_by_username(regular_user.username) |
|
179 | usr = UserModel().get_by_username(regular_user.username) | |
181 | usr.inherit_default_permissions = False |
|
180 | usr.inherit_default_permissions = False | |
182 | Session().add(usr) |
|
181 | Session().add(usr) | |
183 | UserModel().grant_perm(regular_user.username, 'hg.fork.repository') |
|
182 | UserModel().grant_perm(regular_user.username, 'hg.fork.repository') | |
184 |
|
183 | |||
185 | source_name = backend['minimal'].repo_name |
|
184 | source_name = backend['minimal'].repo_name | |
186 | fork_name = backend.new_repo_name() |
|
185 | fork_name = backend.new_repo_name() | |
187 | id_, params = build_data( |
|
186 | id_, params = build_data( | |
188 | regular_user_api_key, 'fork_repo', |
|
187 | regular_user_api_key, 'fork_repo', | |
189 | repoid=source_name, |
|
188 | repoid=source_name, | |
190 | fork_name=fork_name) |
|
189 | fork_name=fork_name) | |
191 | response = api_call(self.app, params) |
|
190 | response = api_call(self.app, params) | |
192 | expected = { |
|
191 | expected = { | |
193 | "repo_name": "You do not have the permission to " |
|
192 | "repo_name": "You do not have the permission to " | |
194 | "store repositories in the root location."} |
|
193 | "store repositories in the root location."} | |
195 | assert_error(id_, expected, given=response.body) |
|
194 | assert_error(id_, expected, given=response.body) | |
196 |
|
195 | |||
197 | def test_api_fork_repo_non_admin_no_permission_to_fork( |
|
196 | def test_api_fork_repo_non_admin_no_permission_to_fork( | |
198 | self, backend, user_util): |
|
197 | self, backend, user_util): | |
199 |
|
198 | |||
200 | regular_user = user_util.create_user() |
|
199 | regular_user = user_util.create_user() | |
201 | regular_user_api_key = regular_user.api_key |
|
200 | regular_user_api_key = regular_user.api_key | |
202 | usr = UserModel().get_by_username(regular_user.username) |
|
201 | usr = UserModel().get_by_username(regular_user.username) | |
203 | usr.inherit_default_permissions = False |
|
202 | usr.inherit_default_permissions = False | |
204 | Session().add(usr) |
|
203 | Session().add(usr) | |
205 |
|
204 | |||
206 | source_name = backend['minimal'].repo_name |
|
205 | source_name = backend['minimal'].repo_name | |
207 | fork_name = backend.new_repo_name() |
|
206 | fork_name = backend.new_repo_name() | |
208 | id_, params = build_data( |
|
207 | id_, params = build_data( | |
209 | regular_user_api_key, 'fork_repo', |
|
208 | regular_user_api_key, 'fork_repo', | |
210 | repoid=source_name, |
|
209 | repoid=source_name, | |
211 | fork_name=fork_name) |
|
210 | fork_name=fork_name) | |
212 | response = api_call(self.app, params) |
|
211 | response = api_call(self.app, params) | |
213 |
|
212 | |||
214 | expected = "Access was denied to this resource." |
|
213 | expected = "Access was denied to this resource." | |
215 | assert_error(id_, expected, given=response.body) |
|
214 | assert_error(id_, expected, given=response.body) | |
216 |
|
215 | |||
217 | def test_api_fork_repo_unknown_owner(self, backend): |
|
216 | def test_api_fork_repo_unknown_owner(self, backend): | |
218 | source_name = backend['minimal'].repo_name |
|
217 | source_name = backend['minimal'].repo_name | |
219 | fork_name = backend.new_repo_name() |
|
218 | fork_name = backend.new_repo_name() | |
220 | owner = 'i-dont-exist' |
|
219 | owner = 'i-dont-exist' | |
221 | id_, params = build_data( |
|
220 | id_, params = build_data( | |
222 | self.apikey, 'fork_repo', |
|
221 | self.apikey, 'fork_repo', | |
223 | repoid=source_name, |
|
222 | repoid=source_name, | |
224 | fork_name=fork_name, |
|
223 | fork_name=fork_name, | |
225 | owner=owner) |
|
224 | owner=owner) | |
226 | response = api_call(self.app, params) |
|
225 | response = api_call(self.app, params) | |
227 | expected = 'user `%s` does not exist' % (owner,) |
|
226 | expected = 'user `%s` does not exist' % (owner,) | |
228 | assert_error(id_, expected, given=response.body) |
|
227 | assert_error(id_, expected, given=response.body) | |
229 |
|
228 | |||
230 | def test_api_fork_repo_fork_exists(self, backend): |
|
229 | def test_api_fork_repo_fork_exists(self, backend): | |
231 | source_name = backend['minimal'].repo_name |
|
230 | source_name = backend['minimal'].repo_name | |
232 | fork_name = backend.new_repo_name() |
|
231 | fork_name = backend.new_repo_name() | |
233 | fork_repo = fixture.create_fork(source_name, fork_name) |
|
232 | fork_repo = fixture.create_fork(source_name, fork_name) | |
234 |
|
233 | |||
235 | id_, params = build_data( |
|
234 | id_, params = build_data( | |
236 | self.apikey, 'fork_repo', |
|
235 | self.apikey, 'fork_repo', | |
237 | repoid=source_name, |
|
236 | repoid=source_name, | |
238 | fork_name=fork_name, |
|
237 | fork_name=fork_name, | |
239 | owner=TEST_USER_ADMIN_LOGIN) |
|
238 | owner=TEST_USER_ADMIN_LOGIN) | |
240 | response = api_call(self.app, params) |
|
239 | response = api_call(self.app, params) | |
241 |
|
240 | |||
242 | try: |
|
241 | try: | |
243 | expected = { |
|
242 | expected = { | |
244 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( |
|
243 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( | |
245 | fork_name)} |
|
244 | fork_name)} | |
246 | assert_error(id_, expected, given=response.body) |
|
245 | assert_error(id_, expected, given=response.body) | |
247 | finally: |
|
246 | finally: | |
248 | fixture.destroy_repo(fork_repo.repo_name) |
|
247 | fixture.destroy_repo(fork_repo.repo_name) | |
249 |
|
248 | |||
250 | def test_api_fork_repo_repo_exists(self, backend): |
|
249 | def test_api_fork_repo_repo_exists(self, backend): | |
251 | source_name = backend['minimal'].repo_name |
|
250 | source_name = backend['minimal'].repo_name | |
252 | fork_name = source_name |
|
251 | fork_name = source_name | |
253 |
|
252 | |||
254 | id_, params = build_data( |
|
253 | id_, params = build_data( | |
255 | self.apikey, 'fork_repo', |
|
254 | self.apikey, 'fork_repo', | |
256 | repoid=source_name, |
|
255 | repoid=source_name, | |
257 | fork_name=fork_name, |
|
256 | fork_name=fork_name, | |
258 | owner=TEST_USER_ADMIN_LOGIN) |
|
257 | owner=TEST_USER_ADMIN_LOGIN) | |
259 | response = api_call(self.app, params) |
|
258 | response = api_call(self.app, params) | |
260 |
|
259 | |||
261 | expected = { |
|
260 | expected = { | |
262 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( |
|
261 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( | |
263 | fork_name)} |
|
262 | fork_name)} | |
264 | assert_error(id_, expected, given=response.body) |
|
263 | assert_error(id_, expected, given=response.body) | |
265 |
|
264 | |||
266 | @mock.patch.object(RepoModel, 'create_fork', crash) |
|
265 | @mock.patch.object(RepoModel, 'create_fork', crash) | |
267 | def test_api_fork_repo_exception_occurred(self, backend): |
|
266 | def test_api_fork_repo_exception_occurred(self, backend): | |
268 | source_name = backend['minimal'].repo_name |
|
267 | source_name = backend['minimal'].repo_name | |
269 | fork_name = backend.new_repo_name() |
|
268 | fork_name = backend.new_repo_name() | |
270 | id_, params = build_data( |
|
269 | id_, params = build_data( | |
271 | self.apikey, 'fork_repo', |
|
270 | self.apikey, 'fork_repo', | |
272 | repoid=source_name, |
|
271 | repoid=source_name, | |
273 | fork_name=fork_name, |
|
272 | fork_name=fork_name, | |
274 | owner=TEST_USER_ADMIN_LOGIN) |
|
273 | owner=TEST_USER_ADMIN_LOGIN) | |
275 | response = api_call(self.app, params) |
|
274 | response = api_call(self.app, params) | |
276 |
|
275 | |||
277 | expected = 'failed to fork repository `%s` as `%s`' % (source_name, |
|
276 | expected = 'failed to fork repository `%s` as `%s`' % (source_name, | |
278 | fork_name) |
|
277 | fork_name) | |
279 | assert_error(id_, expected, given=response.body) |
|
278 | assert_error(id_, expected, given=response.body) |
@@ -1,115 +1,114 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 | from rhodecode.tests import HG_REPO |
|
21 | from rhodecode.tests import HG_REPO | |
23 | from rhodecode.api.tests.utils import ( |
|
22 | from rhodecode.api.tests.utils import ( | |
24 | build_data, api_call, assert_error, assert_ok) |
|
23 | build_data, api_call, assert_error, assert_ok) | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestApiSearch(object): |
|
27 | class TestApiSearch(object): | |
29 |
|
28 | |||
30 | @pytest.mark.parametrize("sort_dir", [ |
|
29 | @pytest.mark.parametrize("sort_dir", [ | |
31 | "asc", |
|
30 | "asc", | |
32 | "desc", |
|
31 | "desc", | |
33 | ]) |
|
32 | ]) | |
34 | @pytest.mark.parametrize("sort", [ |
|
33 | @pytest.mark.parametrize("sort", [ | |
35 | "xxx", |
|
34 | "xxx", | |
36 | "author_email", |
|
35 | "author_email", | |
37 | "date", |
|
36 | "date", | |
38 | "message", |
|
37 | "message", | |
39 | ]) |
|
38 | ]) | |
40 | @pytest.mark.parametrize("query, expected_hits, expected_paths", [ |
|
39 | @pytest.mark.parametrize("query, expected_hits, expected_paths", [ | |
41 | ('todo', 23, [ |
|
40 | ('todo', 23, [ | |
42 | 'vcs/backends/hg/inmemory.py', |
|
41 | 'vcs/backends/hg/inmemory.py', | |
43 | 'vcs/tests/test_git.py']), |
|
42 | 'vcs/tests/test_git.py']), | |
44 | ('extension:rst installation', 6, [ |
|
43 | ('extension:rst installation', 6, [ | |
45 | 'docs/index.rst', |
|
44 | 'docs/index.rst', | |
46 | 'docs/installation.rst']), |
|
45 | 'docs/installation.rst']), | |
47 | ('def repo', 87, [ |
|
46 | ('def repo', 87, [ | |
48 | 'vcs/tests/test_git.py', |
|
47 | 'vcs/tests/test_git.py', | |
49 | 'vcs/tests/test_changesets.py']), |
|
48 | 'vcs/tests/test_changesets.py']), | |
50 | ('repository:%s def test' % HG_REPO, 18, [ |
|
49 | ('repository:%s def test' % HG_REPO, 18, [ | |
51 | 'vcs/tests/test_git.py', |
|
50 | 'vcs/tests/test_git.py', | |
52 | 'vcs/tests/test_changesets.py']), |
|
51 | 'vcs/tests/test_changesets.py']), | |
53 | ('"def main"', 9, [ |
|
52 | ('"def main"', 9, [ | |
54 | 'vcs/__init__.py', |
|
53 | 'vcs/__init__.py', | |
55 | 'vcs/tests/__init__.py', |
|
54 | 'vcs/tests/__init__.py', | |
56 | 'vcs/utils/progressbar.py']), |
|
55 | 'vcs/utils/progressbar.py']), | |
57 | ('owner:test_admin', 358, [ |
|
56 | ('owner:test_admin', 358, [ | |
58 | 'vcs/tests/base.py', |
|
57 | 'vcs/tests/base.py', | |
59 | 'MANIFEST.in', |
|
58 | 'MANIFEST.in', | |
60 | 'vcs/utils/termcolors.py', |
|
59 | 'vcs/utils/termcolors.py', | |
61 | 'docs/theme/ADC/static/documentation.png']), |
|
60 | 'docs/theme/ADC/static/documentation.png']), | |
62 | ('owner:test_admin def main', 72, [ |
|
61 | ('owner:test_admin def main', 72, [ | |
63 | 'vcs/__init__.py', |
|
62 | 'vcs/__init__.py', | |
64 | 'vcs/tests/test_utils_filesize.py', |
|
63 | 'vcs/tests/test_utils_filesize.py', | |
65 | 'vcs/tests/test_cli.py']), |
|
64 | 'vcs/tests/test_cli.py']), | |
66 | ('owner:michał test', 0, []), |
|
65 | ('owner:michał test', 0, []), | |
67 | ]) |
|
66 | ]) | |
68 | def test_search_content_results(self, sort_dir, sort, query, expected_hits, expected_paths): |
|
67 | def test_search_content_results(self, sort_dir, sort, query, expected_hits, expected_paths): | |
69 | id_, params = build_data( |
|
68 | id_, params = build_data( | |
70 | self.apikey_regular, 'search', |
|
69 | self.apikey_regular, 'search', | |
71 | search_query=query, |
|
70 | search_query=query, | |
72 | search_sort='{}:{}'.format(sort_dir, sort), |
|
71 | search_sort='{}:{}'.format(sort_dir, sort), | |
73 | search_type='content') |
|
72 | search_type='content') | |
74 |
|
73 | |||
75 | response = api_call(self.app, params) |
|
74 | response = api_call(self.app, params) | |
76 | json_response = response.json |
|
75 | json_response = response.json | |
77 |
|
76 | |||
78 | assert json_response['result']['item_count'] == expected_hits |
|
77 | assert json_response['result']['item_count'] == expected_hits | |
79 | paths = [x['f_path'] for x in json_response['result']['results']] |
|
78 | paths = [x['f_path'] for x in json_response['result']['results']] | |
80 |
|
79 | |||
81 | for expected_path in expected_paths: |
|
80 | for expected_path in expected_paths: | |
82 | assert expected_path in paths |
|
81 | assert expected_path in paths | |
83 |
|
82 | |||
84 | @pytest.mark.parametrize("sort_dir", [ |
|
83 | @pytest.mark.parametrize("sort_dir", [ | |
85 | "asc", |
|
84 | "asc", | |
86 | "desc", |
|
85 | "desc", | |
87 | ]) |
|
86 | ]) | |
88 | @pytest.mark.parametrize("sort", [ |
|
87 | @pytest.mark.parametrize("sort", [ | |
89 | "xxx", |
|
88 | "xxx", | |
90 | "date", |
|
89 | "date", | |
91 | "file", |
|
90 | "file", | |
92 | "size", |
|
91 | "size", | |
93 | ]) |
|
92 | ]) | |
94 | @pytest.mark.parametrize("query, expected_hits, expected_paths", [ |
|
93 | @pytest.mark.parametrize("query, expected_hits, expected_paths", [ | |
95 | ('readme.rst', 3, []), |
|
94 | ('readme.rst', 3, []), | |
96 | ('test*', 75, []), |
|
95 | ('test*', 75, []), | |
97 | ('*model*', 1, []), |
|
96 | ('*model*', 1, []), | |
98 | ('extension:rst', 48, []), |
|
97 | ('extension:rst', 48, []), | |
99 | ('extension:rst api', 24, []), |
|
98 | ('extension:rst api', 24, []), | |
100 | ]) |
|
99 | ]) | |
101 | def test_search_file_paths(self, sort_dir, sort, query, expected_hits, expected_paths): |
|
100 | def test_search_file_paths(self, sort_dir, sort, query, expected_hits, expected_paths): | |
102 | id_, params = build_data( |
|
101 | id_, params = build_data( | |
103 | self.apikey_regular, 'search', |
|
102 | self.apikey_regular, 'search', | |
104 | search_query=query, |
|
103 | search_query=query, | |
105 | search_sort='{}:{}'.format(sort_dir, sort), |
|
104 | search_sort='{}:{}'.format(sort_dir, sort), | |
106 | search_type='path') |
|
105 | search_type='path') | |
107 |
|
106 | |||
108 | response = api_call(self.app, params) |
|
107 | response = api_call(self.app, params) | |
109 | json_response = response.json |
|
108 | json_response = response.json | |
110 |
|
109 | |||
111 | assert json_response['result']['item_count'] == expected_hits |
|
110 | assert json_response['result']['item_count'] == expected_hits | |
112 | paths = [x['f_path'] for x in json_response['result']['results']] |
|
111 | paths = [x['f_path'] for x in json_response['result']['results']] | |
113 |
|
112 | |||
114 | for expected_path in expected_paths: |
|
113 | for expected_path in expected_paths: | |
115 | assert expected_path in paths |
|
114 | assert expected_path in paths |
@@ -1,101 +1,101 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
|
23 | from rhodecode.lib.str_utils import safe_bytes | |||
24 | from rhodecode.model.db import Gist |
|
24 | from rhodecode.model.db import Gist | |
25 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok) |
|
26 | build_data, api_call, assert_error, assert_ok) | |
27 |
|
27 | |||
28 |
|
28 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestApiGetGist(object): |
|
30 | class TestApiGetGist(object): | |
31 | def test_api_get_gist(self, gist_util, http_host_only_stub): |
|
31 | def test_api_get_gist(self, gist_util, http_host_only_stub): | |
32 | gist = gist_util.create_gist() |
|
32 | gist = gist_util.create_gist() | |
33 | gist_id = gist.gist_access_id |
|
33 | gist_id = gist.gist_access_id | |
34 | gist_created_on = gist.created_on |
|
34 | gist_created_on = gist.created_on | |
35 | gist_modified_at = gist.modified_at |
|
35 | gist_modified_at = gist.modified_at | |
36 | id_, params = build_data( |
|
36 | id_, params = build_data( | |
37 | self.apikey, 'get_gist', gistid=gist_id, ) |
|
37 | self.apikey, 'get_gist', gistid=gist_id, ) | |
38 | response = api_call(self.app, params) |
|
38 | response = api_call(self.app, params) | |
39 |
|
39 | |||
40 | expected = { |
|
40 | expected = { | |
41 | 'access_id': gist_id, |
|
41 | 'access_id': gist_id, | |
42 | 'created_on': gist_created_on, |
|
42 | 'created_on': gist_created_on, | |
43 | 'modified_at': gist_modified_at, |
|
43 | 'modified_at': gist_modified_at, | |
44 | 'description': 'new-gist', |
|
44 | 'description': 'new-gist', | |
45 | 'expires': -1.0, |
|
45 | 'expires': -1.0, | |
46 | 'gist_id': int(gist_id), |
|
46 | 'gist_id': int(gist_id), | |
47 | 'type': 'public', |
|
47 | 'type': 'public', | |
48 | 'url': 'http://%s/_admin/gists/%s' % (http_host_only_stub, gist_id,), |
|
48 | 'url': 'http://%s/_admin/gists/%s' % (http_host_only_stub, gist_id,), | |
49 | 'acl_level': Gist.ACL_LEVEL_PUBLIC, |
|
49 | 'acl_level': Gist.ACL_LEVEL_PUBLIC, | |
50 | 'content': None, |
|
50 | 'content': None, | |
51 | } |
|
51 | } | |
52 |
|
52 | |||
53 | assert_ok(id_, expected, given=response.body) |
|
53 | assert_ok(id_, expected, given=response.body) | |
54 |
|
54 | |||
55 | def test_api_get_gist_with_content(self, gist_util, http_host_only_stub): |
|
55 | def test_api_get_gist_with_content(self, gist_util, http_host_only_stub): | |
56 | mapping = { |
|
56 | mapping = { | |
57 |
|
|
57 | b'filename1.txt': {'content': b'hello world'}, | |
58 |
|
|
58 | safe_bytes('filename1Ä….txt'): {'content': safe_bytes('hello worldÄ™')} | |
59 | } |
|
59 | } | |
60 | gist = gist_util.create_gist(gist_mapping=mapping) |
|
60 | gist = gist_util.create_gist(gist_mapping=mapping) | |
61 | gist_id = gist.gist_access_id |
|
61 | gist_id = gist.gist_access_id | |
62 | gist_created_on = gist.created_on |
|
62 | gist_created_on = gist.created_on | |
63 | gist_modified_at = gist.modified_at |
|
63 | gist_modified_at = gist.modified_at | |
64 | id_, params = build_data( |
|
64 | id_, params = build_data( | |
65 | self.apikey, 'get_gist', gistid=gist_id, content=True) |
|
65 | self.apikey, 'get_gist', gistid=gist_id, content=True) | |
66 | response = api_call(self.app, params) |
|
66 | response = api_call(self.app, params) | |
67 |
|
67 | |||
68 | expected = { |
|
68 | expected = { | |
69 | 'access_id': gist_id, |
|
69 | 'access_id': gist_id, | |
70 | 'created_on': gist_created_on, |
|
70 | 'created_on': gist_created_on, | |
71 | 'modified_at': gist_modified_at, |
|
71 | 'modified_at': gist_modified_at, | |
72 | 'description': 'new-gist', |
|
72 | 'description': 'new-gist', | |
73 | 'expires': -1.0, |
|
73 | 'expires': -1.0, | |
74 | 'gist_id': int(gist_id), |
|
74 | 'gist_id': int(gist_id), | |
75 | 'type': 'public', |
|
75 | 'type': 'public', | |
76 | 'url': 'http://%s/_admin/gists/%s' % (http_host_only_stub, gist_id,), |
|
76 | 'url': 'http://%s/_admin/gists/%s' % (http_host_only_stub, gist_id,), | |
77 | 'acl_level': Gist.ACL_LEVEL_PUBLIC, |
|
77 | 'acl_level': Gist.ACL_LEVEL_PUBLIC, | |
78 | 'content': { |
|
78 | 'content': { | |
79 | u'filename1.txt': u'hello world', |
|
79 | u'filename1.txt': u'hello world', | |
80 | u'filename1Ä….txt': u'hello worldÄ™' |
|
80 | u'filename1Ä….txt': u'hello worldÄ™' | |
81 | }, |
|
81 | }, | |
82 | } |
|
82 | } | |
83 |
|
83 | |||
84 | assert_ok(id_, expected, given=response.body) |
|
84 | assert_ok(id_, expected, given=response.body) | |
85 |
|
85 | |||
86 | def test_api_get_gist_not_existing(self): |
|
86 | def test_api_get_gist_not_existing(self): | |
87 | id_, params = build_data( |
|
87 | id_, params = build_data( | |
88 | self.apikey_regular, 'get_gist', gistid='12345', ) |
|
88 | self.apikey_regular, 'get_gist', gistid='12345', ) | |
89 | response = api_call(self.app, params) |
|
89 | response = api_call(self.app, params) | |
90 | expected = 'gist `%s` does not exist' % ('12345',) |
|
90 | expected = 'gist `%s` does not exist' % ('12345',) | |
91 | assert_error(id_, expected, given=response.body) |
|
91 | assert_error(id_, expected, given=response.body) | |
92 |
|
92 | |||
93 | def test_api_get_gist_private_gist_without_permission(self, gist_util): |
|
93 | def test_api_get_gist_private_gist_without_permission(self, gist_util): | |
94 | gist = gist_util.create_gist() |
|
94 | gist = gist_util.create_gist() | |
95 | gist_id = gist.gist_access_id |
|
95 | gist_id = gist.gist_access_id | |
96 | id_, params = build_data( |
|
96 | id_, params = build_data( | |
97 | self.apikey_regular, 'get_gist', gistid=gist_id, ) |
|
97 | self.apikey_regular, 'get_gist', gistid=gist_id, ) | |
98 | response = api_call(self.app, params) |
|
98 | response = api_call(self.app, params) | |
99 |
|
99 | |||
100 | expected = 'gist `%s` does not exist' % (gist_id,) |
|
100 | expected = 'gist `%s` does not exist' % (gist_id,) | |
101 | assert_error(id_, expected, given=response.body) |
|
101 | assert_error(id_, expected, given=response.body) |
@@ -1,74 +1,73 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
23 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error) |
|
25 | build_data, api_call, assert_error) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestApiGetGist(object): |
|
29 | class TestApiGetGist(object): | |
31 | def test_api_get_gists(self, gist_util): |
|
30 | def test_api_get_gists(self, gist_util): | |
32 | gist_util.create_gist() |
|
31 | gist_util.create_gist() | |
33 | gist_util.create_gist() |
|
32 | gist_util.create_gist() | |
34 |
|
33 | |||
35 | id_, params = build_data(self.apikey, 'get_gists') |
|
34 | id_, params = build_data(self.apikey, 'get_gists') | |
36 | response = api_call(self.app, params) |
|
35 | response = api_call(self.app, params) | |
37 | assert len(response.json['result']) == 2 |
|
36 | assert len(response.json['result']) == 2 | |
38 |
|
37 | |||
39 | def test_api_get_gists_regular_user(self, gist_util): |
|
38 | def test_api_get_gists_regular_user(self, gist_util): | |
40 | # by admin |
|
39 | # by admin | |
41 | gist_util.create_gist() |
|
40 | gist_util.create_gist() | |
42 | gist_util.create_gist() |
|
41 | gist_util.create_gist() | |
43 |
|
42 | |||
44 | # by reg user |
|
43 | # by reg user | |
45 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
44 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) | |
46 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
45 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) | |
47 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
46 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) | |
48 |
|
47 | |||
49 | id_, params = build_data(self.apikey_regular, 'get_gists') |
|
48 | id_, params = build_data(self.apikey_regular, 'get_gists') | |
50 | response = api_call(self.app, params) |
|
49 | response = api_call(self.app, params) | |
51 | assert len(response.json['result']) == 3 |
|
50 | assert len(response.json['result']) == 3 | |
52 |
|
51 | |||
53 | def test_api_get_gists_only_for_regular_user(self, gist_util): |
|
52 | def test_api_get_gists_only_for_regular_user(self, gist_util): | |
54 | # by admin |
|
53 | # by admin | |
55 | gist_util.create_gist() |
|
54 | gist_util.create_gist() | |
56 | gist_util.create_gist() |
|
55 | gist_util.create_gist() | |
57 |
|
56 | |||
58 | # by reg user |
|
57 | # by reg user | |
59 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
58 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) | |
60 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
59 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) | |
61 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
60 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) | |
62 |
|
61 | |||
63 | id_, params = build_data( |
|
62 | id_, params = build_data( | |
64 | self.apikey, 'get_gists', userid=self.TEST_USER_LOGIN) |
|
63 | self.apikey, 'get_gists', userid=self.TEST_USER_LOGIN) | |
65 | response = api_call(self.app, params) |
|
64 | response = api_call(self.app, params) | |
66 | assert len(response.json['result']) == 3 |
|
65 | assert len(response.json['result']) == 3 | |
67 |
|
66 | |||
68 | def test_api_get_gists_regular_user_with_different_userid(self): |
|
67 | def test_api_get_gists_regular_user_with_different_userid(self): | |
69 | id_, params = build_data( |
|
68 | id_, params = build_data( | |
70 | self.apikey_regular, 'get_gists', |
|
69 | self.apikey_regular, 'get_gists', | |
71 | userid=TEST_USER_ADMIN_LOGIN) |
|
70 | userid=TEST_USER_ADMIN_LOGIN) | |
72 | response = api_call(self.app, params) |
|
71 | response = api_call(self.app, params) | |
73 | expected = 'userid is not the same as your user' |
|
72 | expected = 'userid is not the same as your user' | |
74 | assert_error(id_, expected, given=response.body) |
|
73 | assert_error(id_, expected, given=response.body) |
@@ -1,36 +1,35 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestGetIp(object): |
|
27 | class TestGetIp(object): | |
29 | def test_api_get_ip(self): |
|
28 | def test_api_get_ip(self): | |
30 | id_, params = build_data(self.apikey, 'get_ip') |
|
29 | id_, params = build_data(self.apikey, 'get_ip') | |
31 | response = api_call(self.app, params) |
|
30 | response = api_call(self.app, params) | |
32 | expected = { |
|
31 | expected = { | |
33 | 'server_ip_addr': '0.0.0.0', |
|
32 | 'server_ip_addr': '0.0.0.0', | |
34 | 'user_ips': [] |
|
33 | 'user_ips': [] | |
35 | } |
|
34 | } | |
36 | assert_ok(id_, expected, given=response.body) |
|
35 | assert_ok(id_, expected, given=response.body) |
@@ -1,91 +1,90 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.db import Repository, User |
|
23 | from rhodecode.model.db import Repository, User | |
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN |
|
24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_ok, assert_error) |
|
26 | build_data, api_call, assert_ok, assert_error) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGetLocks(object): |
|
30 | class TestGetLocks(object): | |
32 | def test_api_get_user_locks_regular_user(self): |
|
31 | def test_api_get_user_locks_regular_user(self): | |
33 | id_, params = build_data(self.apikey_regular, 'get_user_locks') |
|
32 | id_, params = build_data(self.apikey_regular, 'get_user_locks') | |
34 | response = api_call(self.app, params) |
|
33 | response = api_call(self.app, params) | |
35 | expected = [] |
|
34 | expected = [] | |
36 | assert_ok(id_, expected, given=response.body) |
|
35 | assert_ok(id_, expected, given=response.body) | |
37 |
|
36 | |||
38 | def test_api_get_user_locks_with_userid_regular_user(self): |
|
37 | def test_api_get_user_locks_with_userid_regular_user(self): | |
39 | id_, params = build_data( |
|
38 | id_, params = build_data( | |
40 | self.apikey_regular, 'get_user_locks', userid=TEST_USER_ADMIN_LOGIN) |
|
39 | self.apikey_regular, 'get_user_locks', userid=TEST_USER_ADMIN_LOGIN) | |
41 | response = api_call(self.app, params) |
|
40 | response = api_call(self.app, params) | |
42 | expected = 'userid is not the same as your user' |
|
41 | expected = 'userid is not the same as your user' | |
43 | assert_error(id_, expected, given=response.body) |
|
42 | assert_error(id_, expected, given=response.body) | |
44 |
|
43 | |||
45 | def test_api_get_user_locks(self): |
|
44 | def test_api_get_user_locks(self): | |
46 | id_, params = build_data(self.apikey, 'get_user_locks') |
|
45 | id_, params = build_data(self.apikey, 'get_user_locks') | |
47 | response = api_call(self.app, params) |
|
46 | response = api_call(self.app, params) | |
48 | expected = [] |
|
47 | expected = [] | |
49 | assert_ok(id_, expected, given=response.body) |
|
48 | assert_ok(id_, expected, given=response.body) | |
50 |
|
49 | |||
51 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ |
|
50 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ | |
52 | ('apikey', True), |
|
51 | ('apikey', True), | |
53 | ('apikey_regular', False), |
|
52 | ('apikey_regular', False), | |
54 | ]) |
|
53 | ]) | |
55 | def test_api_get_user_locks_with_one_locked_repo( |
|
54 | def test_api_get_user_locks_with_one_locked_repo( | |
56 | self, apikey_attr, expect_secrets, backend): |
|
55 | self, apikey_attr, expect_secrets, backend): | |
57 |
|
56 | |||
58 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
57 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) | |
59 | Repository.lock( |
|
58 | Repository.lock( | |
60 | repo, User.get_by_username(self.TEST_USER_LOGIN).user_id) |
|
59 | repo, User.get_by_username(self.TEST_USER_LOGIN).user_id) | |
61 |
|
60 | |||
62 | apikey = getattr(self, apikey_attr) |
|
61 | apikey = getattr(self, apikey_attr) | |
63 |
|
62 | |||
64 | id_, params = build_data(apikey, 'get_user_locks') |
|
63 | id_, params = build_data(apikey, 'get_user_locks') | |
65 | if apikey_attr == 'apikey': |
|
64 | if apikey_attr == 'apikey': | |
66 | # super-admin should call in specific user |
|
65 | # super-admin should call in specific user | |
67 | id_, params = build_data(apikey, 'get_user_locks', |
|
66 | id_, params = build_data(apikey, 'get_user_locks', | |
68 | userid=self.TEST_USER_LOGIN) |
|
67 | userid=self.TEST_USER_LOGIN) | |
69 |
|
68 | |||
70 | response = api_call(self.app, params) |
|
69 | response = api_call(self.app, params) | |
71 | expected = [repo.get_api_data(include_secrets=expect_secrets)] |
|
70 | expected = [repo.get_api_data(include_secrets=expect_secrets)] | |
72 | assert_ok(id_, expected, given=response.body) |
|
71 | assert_ok(id_, expected, given=response.body) | |
73 |
|
72 | |||
74 | def test_api_get_user_locks_with_one_locked_repo_for_specific_user( |
|
73 | def test_api_get_user_locks_with_one_locked_repo_for_specific_user( | |
75 | self, backend): |
|
74 | self, backend): | |
76 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
75 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) | |
77 |
|
76 | |||
78 | Repository.lock(repo, User.get_by_username( |
|
77 | Repository.lock(repo, User.get_by_username( | |
79 | self.TEST_USER_LOGIN).user_id) |
|
78 | self.TEST_USER_LOGIN).user_id) | |
80 | id_, params = build_data( |
|
79 | id_, params = build_data( | |
81 | self.apikey, 'get_user_locks', userid=self.TEST_USER_LOGIN) |
|
80 | self.apikey, 'get_user_locks', userid=self.TEST_USER_LOGIN) | |
82 | response = api_call(self.app, params) |
|
81 | response = api_call(self.app, params) | |
83 | expected = [repo.get_api_data(include_secrets=True)] |
|
82 | expected = [repo.get_api_data(include_secrets=True)] | |
84 | assert_ok(id_, expected, given=response.body) |
|
83 | assert_ok(id_, expected, given=response.body) | |
85 |
|
84 | |||
86 | def test_api_get_user_locks_with_userid(self): |
|
85 | def test_api_get_user_locks_with_userid(self): | |
87 | id_, params = build_data( |
|
86 | id_, params = build_data( | |
88 | self.apikey, 'get_user_locks', userid=TEST_USER_REGULAR_LOGIN) |
|
87 | self.apikey, 'get_user_locks', userid=TEST_USER_REGULAR_LOGIN) | |
89 | response = api_call(self.app, params) |
|
88 | response = api_call(self.app, params) | |
90 | expected = [] |
|
89 | expected = [] | |
91 | assert_ok(id_, expected, given=response.body) |
|
90 | assert_ok(id_, expected, given=response.body) |
@@ -1,63 +1,62 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestGetMethod(object): |
|
27 | class TestGetMethod(object): | |
29 | def test_get_methods_no_matches(self): |
|
28 | def test_get_methods_no_matches(self): | |
30 | id_, params = build_data(self.apikey, 'get_method', pattern='hello') |
|
29 | id_, params = build_data(self.apikey, 'get_method', pattern='hello') | |
31 | response = api_call(self.app, params) |
|
30 | response = api_call(self.app, params) | |
32 |
|
31 | |||
33 | expected = [] |
|
32 | expected = [] | |
34 | assert_ok(id_, expected, given=response.body) |
|
33 | assert_ok(id_, expected, given=response.body) | |
35 |
|
34 | |||
36 | def test_get_methods(self): |
|
35 | def test_get_methods(self): | |
37 | id_, params = build_data(self.apikey, 'get_method', pattern='*comment*') |
|
36 | id_, params = build_data(self.apikey, 'get_method', pattern='*comment*') | |
38 | response = api_call(self.app, params) |
|
37 | response = api_call(self.app, params) | |
39 |
|
38 | |||
40 | expected = [ |
|
39 | expected = [ | |
41 | 'changeset_comment', 'comment_pull_request', 'get_pull_request_comments', |
|
40 | 'changeset_comment', 'comment_pull_request', 'get_pull_request_comments', | |
42 | 'comment_commit', 'edit_comment', 'get_comment', 'get_repo_comments' |
|
41 | 'comment_commit', 'edit_comment', 'get_comment', 'get_repo_comments' | |
43 | ] |
|
42 | ] | |
44 | assert_ok(id_, expected, given=response.body) |
|
43 | assert_ok(id_, expected, given=response.body) | |
45 |
|
44 | |||
46 | def test_get_methods_on_single_match(self): |
|
45 | def test_get_methods_on_single_match(self): | |
47 | id_, params = build_data(self.apikey, 'get_method', |
|
46 | id_, params = build_data(self.apikey, 'get_method', | |
48 | pattern='*comment_commit*') |
|
47 | pattern='*comment_commit*') | |
49 | response = api_call(self.app, params) |
|
48 | response = api_call(self.app, params) | |
50 |
|
49 | |||
51 | expected = ['comment_commit', |
|
50 | expected = ['comment_commit', | |
52 | {'apiuser': '<RequiredType>', |
|
51 | {'apiuser': '<RequiredType>', | |
53 |
'comment_type': "<Optional: |
|
52 | 'comment_type': "<Optional:'note'>", | |
54 | 'commit_id': '<RequiredType>', |
|
53 | 'commit_id': '<RequiredType>', | |
55 | 'extra_recipients': '<Optional:[]>', |
|
54 | 'extra_recipients': '<Optional:[]>', | |
56 | 'message': '<RequiredType>', |
|
55 | 'message': '<RequiredType>', | |
57 | 'repoid': '<RequiredType>', |
|
56 | 'repoid': '<RequiredType>', | |
58 | 'request': '<RequiredType>', |
|
57 | 'request': '<RequiredType>', | |
59 | 'resolves_comment_id': '<Optional:None>', |
|
58 | 'resolves_comment_id': '<Optional:None>', | |
60 | 'status': '<Optional:None>', |
|
59 | 'status': '<Optional:None>', | |
61 | 'userid': '<Optional:<OptionalAttr:apiuser>>', |
|
60 | 'userid': '<Optional:<OptionalAttr:apiuser>>', | |
62 | 'send_email': '<Optional:True>'}] |
|
61 | 'send_email': '<Optional:True>'}] | |
63 | assert_ok(id_, expected, given=response.body) |
|
62 | assert_ok(id_, expected, given=response.body) |
@@ -1,143 +1,143 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 | import urlobject |
|
22 | import urlobject | |
24 |
|
23 | |||
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok) |
|
25 | build_data, api_call, assert_error, assert_ok) | |
27 | from rhodecode.lib import helpers as h |
|
26 | from rhodecode.lib import helpers as h | |
28 |
from rhodecode.lib.utils |
|
27 | from rhodecode.lib.str_utils import safe_str | |
|
28 | ||||
29 |
|
29 | |||
30 | pytestmark = pytest.mark.backends("git", "hg") |
|
30 | pytestmark = pytest.mark.backends("git", "hg") | |
31 |
|
31 | |||
32 |
|
32 | |||
33 | @pytest.mark.usefixtures("testuser_api", "app") |
|
33 | @pytest.mark.usefixtures("testuser_api", "app") | |
34 | class TestGetPullRequest(object): |
|
34 | class TestGetPullRequest(object): | |
35 |
|
35 | |||
36 | def test_api_get_pull_request(self, pr_util, http_host_only_stub): |
|
36 | def test_api_get_pull_request(self, pr_util, http_host_only_stub): | |
37 | from rhodecode.model.pull_request import PullRequestModel |
|
37 | from rhodecode.model.pull_request import PullRequestModel | |
38 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
38 | pull_request = pr_util.create_pull_request(mergeable=True) | |
39 | id_, params = build_data( |
|
39 | id_, params = build_data( | |
40 | self.apikey, 'get_pull_request', |
|
40 | self.apikey, 'get_pull_request', | |
41 | pullrequestid=pull_request.pull_request_id, merge_state=True) |
|
41 | pullrequestid=pull_request.pull_request_id, merge_state=True) | |
42 |
|
42 | |||
43 | response = api_call(self.app, params) |
|
43 | response = api_call(self.app, params) | |
44 |
|
44 | |||
45 | assert response.status == '200 OK' |
|
45 | assert response.status == '200 OK' | |
46 |
|
46 | |||
47 | url_obj = urlobject.URLObject( |
|
47 | url_obj = urlobject.URLObject( | |
48 | h.route_url( |
|
48 | h.route_url( | |
49 | 'pullrequest_show', |
|
49 | 'pullrequest_show', | |
50 | repo_name=pull_request.target_repo.repo_name, |
|
50 | repo_name=pull_request.target_repo.repo_name, | |
51 | pull_request_id=pull_request.pull_request_id)) |
|
51 | pull_request_id=pull_request.pull_request_id)) | |
52 |
|
52 | |||
53 |
pr_url = safe_ |
|
53 | pr_url = safe_str( | |
54 | url_obj.with_netloc(http_host_only_stub)) |
|
54 | url_obj.with_netloc(http_host_only_stub)) | |
55 |
source_url = safe_ |
|
55 | source_url = safe_str( | |
56 | pull_request.source_repo.clone_url().with_netloc(http_host_only_stub)) |
|
56 | pull_request.source_repo.clone_url().with_netloc(http_host_only_stub)) | |
57 |
target_url = safe_ |
|
57 | target_url = safe_str( | |
58 | pull_request.target_repo.clone_url().with_netloc(http_host_only_stub)) |
|
58 | pull_request.target_repo.clone_url().with_netloc(http_host_only_stub)) | |
59 |
shadow_url = safe_ |
|
59 | shadow_url = safe_str( | |
60 | PullRequestModel().get_shadow_clone_url(pull_request)) |
|
60 | PullRequestModel().get_shadow_clone_url(pull_request)) | |
61 |
|
61 | |||
62 | expected = { |
|
62 | expected = { | |
63 | 'pull_request_id': pull_request.pull_request_id, |
|
63 | 'pull_request_id': pull_request.pull_request_id, | |
64 | 'url': pr_url, |
|
64 | 'url': pr_url, | |
65 | 'title': pull_request.title, |
|
65 | 'title': pull_request.title, | |
66 | 'description': pull_request.description, |
|
66 | 'description': pull_request.description, | |
67 | 'status': pull_request.status, |
|
67 | 'status': pull_request.status, | |
68 | 'state': pull_request.pull_request_state, |
|
68 | 'state': pull_request.pull_request_state, | |
69 | 'created_on': pull_request.created_on, |
|
69 | 'created_on': pull_request.created_on, | |
70 | 'updated_on': pull_request.updated_on, |
|
70 | 'updated_on': pull_request.updated_on, | |
71 | 'commit_ids': pull_request.revisions, |
|
71 | 'commit_ids': pull_request.revisions, | |
72 | 'review_status': pull_request.calculated_review_status(), |
|
72 | 'review_status': pull_request.calculated_review_status(), | |
73 | 'mergeable': { |
|
73 | 'mergeable': { | |
74 | 'status': True, |
|
74 | 'status': True, | |
75 | 'message': 'This pull request can be automatically merged.', |
|
75 | 'message': 'This pull request can be automatically merged.', | |
76 | }, |
|
76 | }, | |
77 | 'source': { |
|
77 | 'source': { | |
78 | 'clone_url': source_url, |
|
78 | 'clone_url': source_url, | |
79 | 'repository': pull_request.source_repo.repo_name, |
|
79 | 'repository': pull_request.source_repo.repo_name, | |
80 | 'reference': { |
|
80 | 'reference': { | |
81 | 'name': pull_request.source_ref_parts.name, |
|
81 | 'name': pull_request.source_ref_parts.name, | |
82 | 'type': pull_request.source_ref_parts.type, |
|
82 | 'type': pull_request.source_ref_parts.type, | |
83 | 'commit_id': pull_request.source_ref_parts.commit_id, |
|
83 | 'commit_id': pull_request.source_ref_parts.commit_id, | |
84 | }, |
|
84 | }, | |
85 | }, |
|
85 | }, | |
86 | 'target': { |
|
86 | 'target': { | |
87 | 'clone_url': target_url, |
|
87 | 'clone_url': target_url, | |
88 | 'repository': pull_request.target_repo.repo_name, |
|
88 | 'repository': pull_request.target_repo.repo_name, | |
89 | 'reference': { |
|
89 | 'reference': { | |
90 | 'name': pull_request.target_ref_parts.name, |
|
90 | 'name': pull_request.target_ref_parts.name, | |
91 | 'type': pull_request.target_ref_parts.type, |
|
91 | 'type': pull_request.target_ref_parts.type, | |
92 | 'commit_id': pull_request.target_ref_parts.commit_id, |
|
92 | 'commit_id': pull_request.target_ref_parts.commit_id, | |
93 | }, |
|
93 | }, | |
94 | }, |
|
94 | }, | |
95 | 'merge': { |
|
95 | 'merge': { | |
96 | 'clone_url': shadow_url, |
|
96 | 'clone_url': shadow_url, | |
97 | 'reference': { |
|
97 | 'reference': { | |
98 | 'name': pull_request.shadow_merge_ref.name, |
|
98 | 'name': pull_request.shadow_merge_ref.name, | |
99 | 'type': pull_request.shadow_merge_ref.type, |
|
99 | 'type': pull_request.shadow_merge_ref.type, | |
100 | 'commit_id': pull_request.shadow_merge_ref.commit_id, |
|
100 | 'commit_id': pull_request.shadow_merge_ref.commit_id, | |
101 | }, |
|
101 | }, | |
102 | }, |
|
102 | }, | |
103 | 'author': pull_request.author.get_api_data(include_secrets=False, |
|
103 | 'author': pull_request.author.get_api_data(include_secrets=False, | |
104 | details='basic'), |
|
104 | details='basic'), | |
105 | 'reviewers': [ |
|
105 | 'reviewers': [ | |
106 | { |
|
106 | { | |
107 | 'user': reviewer.get_api_data(include_secrets=False, |
|
107 | 'user': reviewer.get_api_data(include_secrets=False, | |
108 | details='basic'), |
|
108 | details='basic'), | |
109 | 'reasons': reasons, |
|
109 | 'reasons': reasons, | |
110 | 'review_status': st[0][1].status if st else 'not_reviewed', |
|
110 | 'review_status': st[0][1].status if st else 'not_reviewed', | |
111 | } |
|
111 | } | |
112 | for obj, reviewer, reasons, mandatory, st in |
|
112 | for obj, reviewer, reasons, mandatory, st in | |
113 | pull_request.reviewers_statuses() |
|
113 | pull_request.reviewers_statuses() | |
114 | ] |
|
114 | ] | |
115 | } |
|
115 | } | |
116 | assert_ok(id_, expected, response.body) |
|
116 | assert_ok(id_, expected, response.body) | |
117 |
|
117 | |||
118 | def test_api_get_pull_request_repo_error(self, pr_util): |
|
118 | def test_api_get_pull_request_repo_error(self, pr_util): | |
119 | pull_request = pr_util.create_pull_request() |
|
119 | pull_request = pr_util.create_pull_request() | |
120 | id_, params = build_data( |
|
120 | id_, params = build_data( | |
121 | self.apikey, 'get_pull_request', |
|
121 | self.apikey, 'get_pull_request', | |
122 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
122 | repoid=666, pullrequestid=pull_request.pull_request_id) | |
123 | response = api_call(self.app, params) |
|
123 | response = api_call(self.app, params) | |
124 |
|
124 | |||
125 | expected = 'repository `666` does not exist' |
|
125 | expected = 'repository `666` does not exist' | |
126 | assert_error(id_, expected, given=response.body) |
|
126 | assert_error(id_, expected, given=response.body) | |
127 |
|
127 | |||
128 | def test_api_get_pull_request_pull_request_error(self): |
|
128 | def test_api_get_pull_request_pull_request_error(self): | |
129 | id_, params = build_data( |
|
129 | id_, params = build_data( | |
130 | self.apikey, 'get_pull_request', pullrequestid=666) |
|
130 | self.apikey, 'get_pull_request', pullrequestid=666) | |
131 | response = api_call(self.app, params) |
|
131 | response = api_call(self.app, params) | |
132 |
|
132 | |||
133 | expected = 'pull request `666` does not exist' |
|
133 | expected = 'pull request `666` does not exist' | |
134 | assert_error(id_, expected, given=response.body) |
|
134 | assert_error(id_, expected, given=response.body) | |
135 |
|
135 | |||
136 | def test_api_get_pull_request_pull_request_error_just_pr_id(self): |
|
136 | def test_api_get_pull_request_pull_request_error_just_pr_id(self): | |
137 | id_, params = build_data( |
|
137 | id_, params = build_data( | |
138 | self.apikey, 'get_pull_request', |
|
138 | self.apikey, 'get_pull_request', | |
139 | pullrequestid=666) |
|
139 | pullrequestid=666) | |
140 | response = api_call(self.app, params) |
|
140 | response = api_call(self.app, params) | |
141 |
|
141 | |||
142 | expected = 'pull request `666` does not exist' |
|
142 | expected = 'pull request `666` does not exist' | |
143 | assert_error(id_, expected, given=response.body) |
|
143 | assert_error(id_, expected, given=response.body) |
@@ -1,87 +1,83 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 | import urlobject |
|
|||
24 |
|
22 | |||
25 | from rhodecode.api.tests.utils import ( |
|
23 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok) |
|
24 | build_data, api_call, assert_error, assert_ok) | |
27 | from rhodecode.lib import helpers as h |
|
|||
28 | from rhodecode.lib.utils2 import safe_unicode |
|
|||
29 |
|
25 | |||
30 | pytestmark = pytest.mark.backends("git", "hg") |
|
26 | pytestmark = pytest.mark.backends("git", "hg") | |
31 |
|
27 | |||
32 |
|
28 | |||
33 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
34 | class TestGetPullRequestComments(object): |
|
30 | class TestGetPullRequestComments(object): | |
35 |
|
31 | |||
36 | def test_api_get_pull_request_comments(self, pr_util, http_host_only_stub): |
|
32 | def test_api_get_pull_request_comments(self, pr_util, http_host_only_stub): | |
37 | from rhodecode.model.pull_request import PullRequestModel |
|
33 | from rhodecode.model.pull_request import PullRequestModel | |
38 |
|
34 | |||
39 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
35 | pull_request = pr_util.create_pull_request(mergeable=True) | |
40 | id_, params = build_data( |
|
36 | id_, params = build_data( | |
41 | self.apikey, 'get_pull_request_comments', |
|
37 | self.apikey, 'get_pull_request_comments', | |
42 | pullrequestid=pull_request.pull_request_id) |
|
38 | pullrequestid=pull_request.pull_request_id) | |
43 |
|
39 | |||
44 | response = api_call(self.app, params) |
|
40 | response = api_call(self.app, params) | |
45 |
|
41 | |||
46 | assert response.status == '200 OK' |
|
42 | assert response.status == '200 OK' | |
47 | resp_date = response.json['result'][0]['comment_created_on'] |
|
43 | resp_date = response.json['result'][0]['comment_created_on'] | |
48 | resp_comment_id = response.json['result'][0]['comment_id'] |
|
44 | resp_comment_id = response.json['result'][0]['comment_id'] | |
49 |
|
45 | |||
50 | expected = [ |
|
46 | expected = [ | |
51 | {'comment_author': {'active': True, |
|
47 | {'comment_author': {'active': True, | |
52 | 'full_name_or_username': 'RhodeCode Admin', |
|
48 | 'full_name_or_username': 'RhodeCode Admin', | |
53 | 'username': 'test_admin'}, |
|
49 | 'username': 'test_admin'}, | |
54 | 'comment_created_on': resp_date, |
|
50 | 'comment_created_on': resp_date, | |
55 | 'comment_f_path': None, |
|
51 | 'comment_f_path': None, | |
56 | 'comment_id': resp_comment_id, |
|
52 | 'comment_id': resp_comment_id, | |
57 | 'comment_lineno': None, |
|
53 | 'comment_lineno': None, | |
58 | 'comment_status': {'status': 'under_review', |
|
54 | 'comment_status': {'status': 'under_review', | |
59 | 'status_lbl': 'Under Review'}, |
|
55 | 'status_lbl': 'Under Review'}, | |
60 | 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*', |
|
56 | 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*', | |
61 | 'comment_type': 'note', |
|
57 | 'comment_type': 'note', | |
62 | 'comment_resolved_by': None, |
|
58 | 'comment_resolved_by': None, | |
63 | 'pull_request_version': None, |
|
59 | 'pull_request_version': None, | |
64 | 'comment_last_version': 0, |
|
60 | 'comment_last_version': 0, | |
65 | 'comment_commit_id': None, |
|
61 | 'comment_commit_id': None, | |
66 | 'comment_pull_request_id': pull_request.pull_request_id |
|
62 | 'comment_pull_request_id': pull_request.pull_request_id | |
67 | } |
|
63 | } | |
68 | ] |
|
64 | ] | |
69 | assert_ok(id_, expected, response.body) |
|
65 | assert_ok(id_, expected, response.body) | |
70 |
|
66 | |||
71 | def test_api_get_pull_request_comments_repo_error(self, pr_util): |
|
67 | def test_api_get_pull_request_comments_repo_error(self, pr_util): | |
72 | pull_request = pr_util.create_pull_request() |
|
68 | pull_request = pr_util.create_pull_request() | |
73 | id_, params = build_data( |
|
69 | id_, params = build_data( | |
74 | self.apikey, 'get_pull_request_comments', |
|
70 | self.apikey, 'get_pull_request_comments', | |
75 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
71 | repoid=666, pullrequestid=pull_request.pull_request_id) | |
76 | response = api_call(self.app, params) |
|
72 | response = api_call(self.app, params) | |
77 |
|
73 | |||
78 | expected = 'repository `666` does not exist' |
|
74 | expected = 'repository `666` does not exist' | |
79 | assert_error(id_, expected, given=response.body) |
|
75 | assert_error(id_, expected, given=response.body) | |
80 |
|
76 | |||
81 | def test_api_get_pull_request_comments_pull_request_error(self): |
|
77 | def test_api_get_pull_request_comments_pull_request_error(self): | |
82 | id_, params = build_data( |
|
78 | id_, params = build_data( | |
83 | self.apikey, 'get_pull_request_comments', pullrequestid=666) |
|
79 | self.apikey, 'get_pull_request_comments', pullrequestid=666) | |
84 | response = api_call(self.app, params) |
|
80 | response = api_call(self.app, params) | |
85 |
|
81 | |||
86 | expected = 'pull request `666` does not exist' |
|
82 | expected = 'pull request `666` does not exist' | |
87 | assert_error(id_, expected, given=response.body) |
|
83 | assert_error(id_, expected, given=response.body) |
@@ -1,82 +1,81 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.model.pull_request import PullRequestModel |
|
24 | from rhodecode.model.pull_request import PullRequestModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error) |
|
26 | build_data, api_call, assert_error) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGetPullRequest(object): |
|
30 | class TestGetPullRequest(object): | |
32 |
|
31 | |||
33 | @pytest.mark.backends("git", "hg") |
|
32 | @pytest.mark.backends("git", "hg") | |
34 | def test_api_get_pull_requests(self, pr_util): |
|
33 | def test_api_get_pull_requests(self, pr_util): | |
35 | pull_request = pr_util.create_pull_request() |
|
34 | pull_request = pr_util.create_pull_request() | |
36 | pull_request_2 = PullRequestModel().create( |
|
35 | pull_request_2 = PullRequestModel().create( | |
37 | created_by=pull_request.author, |
|
36 | created_by=pull_request.author, | |
38 | source_repo=pull_request.source_repo, |
|
37 | source_repo=pull_request.source_repo, | |
39 | source_ref=pull_request.source_ref, |
|
38 | source_ref=pull_request.source_ref, | |
40 | target_repo=pull_request.target_repo, |
|
39 | target_repo=pull_request.target_repo, | |
41 | target_ref=pull_request.target_ref, |
|
40 | target_ref=pull_request.target_ref, | |
42 | revisions=pull_request.revisions, |
|
41 | revisions=pull_request.revisions, | |
43 | reviewers=(), |
|
42 | reviewers=(), | |
44 | observers=(), |
|
43 | observers=(), | |
45 | title=pull_request.title, |
|
44 | title=pull_request.title, | |
46 | description=pull_request.description, |
|
45 | description=pull_request.description, | |
47 | ) |
|
46 | ) | |
48 | Session().commit() |
|
47 | Session().commit() | |
49 | id_, params = build_data( |
|
48 | id_, params = build_data( | |
50 | self.apikey, 'get_pull_requests', |
|
49 | self.apikey, 'get_pull_requests', | |
51 | repoid=pull_request.target_repo.repo_name) |
|
50 | repoid=pull_request.target_repo.repo_name) | |
52 | response = api_call(self.app, params) |
|
51 | response = api_call(self.app, params) | |
53 | assert response.status == '200 OK' |
|
52 | assert response.status == '200 OK' | |
54 | assert len(response.json['result']) == 2 |
|
53 | assert len(response.json['result']) == 2 | |
55 |
|
54 | |||
56 | PullRequestModel().close_pull_request( |
|
55 | PullRequestModel().close_pull_request( | |
57 | pull_request_2, pull_request_2.author) |
|
56 | pull_request_2, pull_request_2.author) | |
58 | Session().commit() |
|
57 | Session().commit() | |
59 |
|
58 | |||
60 | id_, params = build_data( |
|
59 | id_, params = build_data( | |
61 | self.apikey, 'get_pull_requests', |
|
60 | self.apikey, 'get_pull_requests', | |
62 | repoid=pull_request.target_repo.repo_name, |
|
61 | repoid=pull_request.target_repo.repo_name, | |
63 | status='new') |
|
62 | status='new') | |
64 | response = api_call(self.app, params) |
|
63 | response = api_call(self.app, params) | |
65 | assert response.status == '200 OK' |
|
64 | assert response.status == '200 OK' | |
66 | assert len(response.json['result']) == 1 |
|
65 | assert len(response.json['result']) == 1 | |
67 |
|
66 | |||
68 | id_, params = build_data( |
|
67 | id_, params = build_data( | |
69 | self.apikey, 'get_pull_requests', |
|
68 | self.apikey, 'get_pull_requests', | |
70 | repoid=pull_request.target_repo.repo_name, |
|
69 | repoid=pull_request.target_repo.repo_name, | |
71 | status='closed') |
|
70 | status='closed') | |
72 | response = api_call(self.app, params) |
|
71 | response = api_call(self.app, params) | |
73 | assert response.status == '200 OK' |
|
72 | assert response.status == '200 OK' | |
74 | assert len(response.json['result']) == 1 |
|
73 | assert len(response.json['result']) == 1 | |
75 |
|
74 | |||
76 | @pytest.mark.backends("git", "hg") |
|
75 | @pytest.mark.backends("git", "hg") | |
77 | def test_api_get_pull_requests_repo_error(self): |
|
76 | def test_api_get_pull_requests_repo_error(self): | |
78 | id_, params = build_data(self.apikey, 'get_pull_requests', repoid=666) |
|
77 | id_, params = build_data(self.apikey, 'get_pull_requests', repoid=666) | |
79 | response = api_call(self.app, params) |
|
78 | response = api_call(self.app, params) | |
80 |
|
79 | |||
81 | expected = 'repository `666` does not exist' |
|
80 | expected = 'repository `666` does not exist' | |
82 | assert_error(id_, expected, given=response.body) |
|
81 | assert_error(id_, expected, given=response.body) |
@@ -1,143 +1,142 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.model.repo import RepoModel |
|
24 | from rhodecode.model.repo import RepoModel | |
26 | from rhodecode.model.user import UserModel |
|
25 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
28 | from rhodecode.api.tests.utils import ( |
|
27 | from rhodecode.api.tests.utils import ( | |
29 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
28 | build_data, api_call, assert_ok, assert_error, expected_permissions) | |
30 |
|
29 | |||
31 |
|
30 | |||
32 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | @pytest.mark.usefixtures("testuser_api", "app") | |
33 | class TestGetRepo(object): |
|
32 | class TestGetRepo(object): | |
34 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ |
|
33 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ | |
35 | ('apikey', True), |
|
34 | ('apikey', True), | |
36 | ('apikey_regular', False), |
|
35 | ('apikey_regular', False), | |
37 | ]) |
|
36 | ]) | |
38 | @pytest.mark.parametrize("cache_param", [ |
|
37 | @pytest.mark.parametrize("cache_param", [ | |
39 | True, |
|
38 | True, | |
40 | False, |
|
39 | False, | |
41 | None, |
|
40 | None, | |
42 | ]) |
|
41 | ]) | |
43 | def test_api_get_repo( |
|
42 | def test_api_get_repo( | |
44 | self, apikey_attr, expect_secrets, cache_param, backend, |
|
43 | self, apikey_attr, expect_secrets, cache_param, backend, | |
45 | user_util): |
|
44 | user_util): | |
46 | repo = backend.create_repo() |
|
45 | repo = backend.create_repo() | |
47 | repo_id = repo.repo_id |
|
46 | repo_id = repo.repo_id | |
48 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
47 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
49 | group = user_util.create_user_group(members=[usr]) |
|
48 | group = user_util.create_user_group(members=[usr]) | |
50 | user_util.grant_user_group_permission_to_repo( |
|
49 | user_util.grant_user_group_permission_to_repo( | |
51 | repo=repo, user_group=group, permission_name='repository.read') |
|
50 | repo=repo, user_group=group, permission_name='repository.read') | |
52 | Session().commit() |
|
51 | Session().commit() | |
53 | kwargs = { |
|
52 | kwargs = { | |
54 | 'repoid': repo.repo_name, |
|
53 | 'repoid': repo.repo_name, | |
55 | } |
|
54 | } | |
56 | if cache_param is not None: |
|
55 | if cache_param is not None: | |
57 | kwargs['cache'] = cache_param |
|
56 | kwargs['cache'] = cache_param | |
58 |
|
57 | |||
59 | apikey = getattr(self, apikey_attr) |
|
58 | apikey = getattr(self, apikey_attr) | |
60 | id_, params = build_data(apikey, 'get_repo', **kwargs) |
|
59 | id_, params = build_data(apikey, 'get_repo', **kwargs) | |
61 | response = api_call(self.app, params) |
|
60 | response = api_call(self.app, params) | |
62 |
|
61 | |||
63 | ret = repo.get_api_data() |
|
62 | ret = repo.get_api_data() | |
64 |
|
63 | |||
65 | permissions = expected_permissions(repo) |
|
64 | permissions = expected_permissions(repo) | |
66 |
|
65 | |||
67 | followers = [] |
|
66 | followers = [] | |
68 |
|
67 | |||
69 | repo = RepoModel().get(repo_id) |
|
68 | repo = RepoModel().get(repo_id) | |
70 | for user in repo.followers: |
|
69 | for user in repo.followers: | |
71 | followers.append(user.user.get_api_data( |
|
70 | followers.append(user.user.get_api_data( | |
72 | include_secrets=expect_secrets)) |
|
71 | include_secrets=expect_secrets)) | |
73 |
|
72 | |||
74 | ret['permissions'] = permissions |
|
73 | ret['permissions'] = permissions | |
75 | ret['followers'] = followers |
|
74 | ret['followers'] = followers | |
76 |
|
75 | |||
77 | expected = ret |
|
76 | expected = ret | |
78 |
|
77 | |||
79 | assert_ok(id_, expected, given=response.body) |
|
78 | assert_ok(id_, expected, given=response.body) | |
80 |
|
79 | |||
81 | @pytest.mark.parametrize("grant_perm", [ |
|
80 | @pytest.mark.parametrize("grant_perm", [ | |
82 | 'repository.admin', |
|
81 | 'repository.admin', | |
83 | 'repository.write', |
|
82 | 'repository.write', | |
84 | 'repository.read', |
|
83 | 'repository.read', | |
85 | ]) |
|
84 | ]) | |
86 | def test_api_get_repo_by_non_admin(self, grant_perm, backend): |
|
85 | def test_api_get_repo_by_non_admin(self, grant_perm, backend): | |
87 | # TODO: Depending on which tests are running before this one, we |
|
86 | # TODO: Depending on which tests are running before this one, we | |
88 | # start with a different number of permissions in the database. |
|
87 | # start with a different number of permissions in the database. | |
89 | repo = RepoModel().get_by_repo_name(backend.repo_name) |
|
88 | repo = RepoModel().get_by_repo_name(backend.repo_name) | |
90 | repo_id = repo.repo_id |
|
89 | repo_id = repo.repo_id | |
91 | permission_count = len(repo.repo_to_perm) |
|
90 | permission_count = len(repo.repo_to_perm) | |
92 |
|
91 | |||
93 | RepoModel().grant_user_permission(repo=backend.repo_name, |
|
92 | RepoModel().grant_user_permission(repo=backend.repo_name, | |
94 | user=self.TEST_USER_LOGIN, |
|
93 | user=self.TEST_USER_LOGIN, | |
95 | perm=grant_perm) |
|
94 | perm=grant_perm) | |
96 | Session().commit() |
|
95 | Session().commit() | |
97 | id_, params = build_data( |
|
96 | id_, params = build_data( | |
98 | self.apikey_regular, 'get_repo', repoid=backend.repo_name) |
|
97 | self.apikey_regular, 'get_repo', repoid=backend.repo_name) | |
99 | response = api_call(self.app, params) |
|
98 | response = api_call(self.app, params) | |
100 |
|
99 | |||
101 | repo = RepoModel().get_by_repo_name(backend.repo_name) |
|
100 | repo = RepoModel().get_by_repo_name(backend.repo_name) | |
102 | ret = repo.get_api_data() |
|
101 | ret = repo.get_api_data() | |
103 |
|
102 | |||
104 | assert permission_count + 1, len(repo.repo_to_perm) |
|
103 | assert permission_count + 1, len(repo.repo_to_perm) | |
105 |
|
104 | |||
106 | permissions = expected_permissions(repo) |
|
105 | permissions = expected_permissions(repo) | |
107 |
|
106 | |||
108 | followers = [] |
|
107 | followers = [] | |
109 |
|
108 | |||
110 | repo = RepoModel().get(repo_id) |
|
109 | repo = RepoModel().get(repo_id) | |
111 | for user in repo.followers: |
|
110 | for user in repo.followers: | |
112 | followers.append(user.user.get_api_data()) |
|
111 | followers.append(user.user.get_api_data()) | |
113 |
|
112 | |||
114 | ret['permissions'] = permissions |
|
113 | ret['permissions'] = permissions | |
115 | ret['followers'] = followers |
|
114 | ret['followers'] = followers | |
116 |
|
115 | |||
117 | expected = ret |
|
116 | expected = ret | |
118 | try: |
|
117 | try: | |
119 | assert_ok(id_, expected, given=response.body) |
|
118 | assert_ok(id_, expected, given=response.body) | |
120 | finally: |
|
119 | finally: | |
121 | RepoModel().revoke_user_permission( |
|
120 | RepoModel().revoke_user_permission( | |
122 | backend.repo_name, self.TEST_USER_LOGIN) |
|
121 | backend.repo_name, self.TEST_USER_LOGIN) | |
123 |
|
122 | |||
124 | def test_api_get_repo_by_non_admin_no_permission_to_repo(self, backend): |
|
123 | def test_api_get_repo_by_non_admin_no_permission_to_repo(self, backend): | |
125 | RepoModel().grant_user_permission(repo=backend.repo_name, |
|
124 | RepoModel().grant_user_permission(repo=backend.repo_name, | |
126 | user=self.TEST_USER_LOGIN, |
|
125 | user=self.TEST_USER_LOGIN, | |
127 | perm='repository.none') |
|
126 | perm='repository.none') | |
128 |
|
127 | |||
129 | id_, params = build_data( |
|
128 | id_, params = build_data( | |
130 | self.apikey_regular, 'get_repo', repoid=backend.repo_name) |
|
129 | self.apikey_regular, 'get_repo', repoid=backend.repo_name) | |
131 | response = api_call(self.app, params) |
|
130 | response = api_call(self.app, params) | |
132 |
|
131 | |||
133 | expected = 'repository `%s` does not exist' % (backend.repo_name) |
|
132 | expected = 'repository `%s` does not exist' % (backend.repo_name) | |
134 | assert_error(id_, expected, given=response.body) |
|
133 | assert_error(id_, expected, given=response.body) | |
135 |
|
134 | |||
136 | def test_api_get_repo_not_existing(self): |
|
135 | def test_api_get_repo_not_existing(self): | |
137 | id_, params = build_data( |
|
136 | id_, params = build_data( | |
138 | self.apikey, 'get_repo', repoid='no-such-repo') |
|
137 | self.apikey, 'get_repo', repoid='no-such-repo') | |
139 | response = api_call(self.app, params) |
|
138 | response = api_call(self.app, params) | |
140 |
|
139 | |||
141 | ret = 'repository `%s` does not exist' % 'no-such-repo' |
|
140 | ret = 'repository `%s` does not exist' % 'no-such-repo' | |
142 | expected = ret |
|
141 | expected = ret | |
143 | assert_error(id_, expected, given=response.body) |
|
142 | assert_error(id_, expected, given=response.body) |
@@ -1,141 +1,140 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_error |
|
23 | from rhodecode.api.tests.utils import build_data, api_call, assert_error | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestGetRepoChangeset(object): |
|
27 | class TestGetRepoChangeset(object): | |
29 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
28 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) | |
30 | def test_get_repo_changeset(self, details, backend): |
|
29 | def test_get_repo_changeset(self, details, backend): | |
31 | commit = backend.repo.get_commit(commit_idx=0) |
|
30 | commit = backend.repo.get_commit(commit_idx=0) | |
32 | __, params = build_data( |
|
31 | __, params = build_data( | |
33 | self.apikey, 'get_repo_changeset', |
|
32 | self.apikey, 'get_repo_changeset', | |
34 | repoid=backend.repo_name, revision=commit.raw_id, |
|
33 | repoid=backend.repo_name, revision=commit.raw_id, | |
35 | details=details, |
|
34 | details=details, | |
36 | ) |
|
35 | ) | |
37 | response = api_call(self.app, params) |
|
36 | response = api_call(self.app, params) | |
38 | result = response.json['result'] |
|
37 | result = response.json['result'] | |
39 | assert result['revision'] == 0 |
|
38 | assert result['revision'] == 0 | |
40 | assert result['raw_id'] == commit.raw_id |
|
39 | assert result['raw_id'] == commit.raw_id | |
41 |
|
40 | |||
42 | if details == 'full': |
|
41 | if details == 'full': | |
43 | assert result['refs']['bookmarks'] == getattr( |
|
42 | assert result['refs']['bookmarks'] == getattr( | |
44 | commit, 'bookmarks', []) |
|
43 | commit, 'bookmarks', []) | |
45 | branches = [commit.branch] if commit.branch else [] |
|
44 | branches = [commit.branch] if commit.branch else [] | |
46 | assert result['refs']['branches'] == branches |
|
45 | assert result['refs']['branches'] == branches | |
47 | assert result['refs']['tags'] == commit.tags |
|
46 | assert result['refs']['tags'] == commit.tags | |
48 |
|
47 | |||
49 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
48 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) | |
50 | def test_get_repo_changeset_bad_type(self, details, backend): |
|
49 | def test_get_repo_changeset_bad_type(self, details, backend): | |
51 | id_, params = build_data( |
|
50 | id_, params = build_data( | |
52 | self.apikey, 'get_repo_changeset', |
|
51 | self.apikey, 'get_repo_changeset', | |
53 | repoid=backend.repo_name, revision=0, |
|
52 | repoid=backend.repo_name, revision=0, | |
54 | details=details, |
|
53 | details=details, | |
55 | ) |
|
54 | ) | |
56 | response = api_call(self.app, params) |
|
55 | response = api_call(self.app, params) | |
57 |
expected = "commit_id must be a string value got < |
|
56 | expected = "commit_id must be a string value got <class 'int'> instead" | |
58 | assert_error(id_, expected, given=response.body) |
|
57 | assert_error(id_, expected, given=response.body) | |
59 |
|
58 | |||
60 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
59 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) | |
61 | def test_get_repo_changesets(self, details, backend): |
|
60 | def test_get_repo_changesets(self, details, backend): | |
62 | limit = 2 |
|
61 | limit = 2 | |
63 | commit = backend.repo.get_commit(commit_idx=0) |
|
62 | commit = backend.repo.get_commit(commit_idx=0) | |
64 | __, params = build_data( |
|
63 | __, params = build_data( | |
65 | self.apikey, 'get_repo_changesets', |
|
64 | self.apikey, 'get_repo_changesets', | |
66 | repoid=backend.repo_name, start_rev=commit.raw_id, limit=limit, |
|
65 | repoid=backend.repo_name, start_rev=commit.raw_id, limit=limit, | |
67 | details=details, |
|
66 | details=details, | |
68 | ) |
|
67 | ) | |
69 | response = api_call(self.app, params) |
|
68 | response = api_call(self.app, params) | |
70 | result = response.json['result'] |
|
69 | result = response.json['result'] | |
71 | assert result |
|
70 | assert result | |
72 | assert len(result) == limit |
|
71 | assert len(result) == limit | |
73 | for x in range(limit): |
|
72 | for x in range(limit): | |
74 | assert result[x]['revision'] == x |
|
73 | assert result[x]['revision'] == x | |
75 |
|
74 | |||
76 | if details == 'full': |
|
75 | if details == 'full': | |
77 | for x in range(limit): |
|
76 | for x in range(limit): | |
78 | assert 'bookmarks' in result[x]['refs'] |
|
77 | assert 'bookmarks' in result[x]['refs'] | |
79 | assert 'branches' in result[x]['refs'] |
|
78 | assert 'branches' in result[x]['refs'] | |
80 | assert 'tags' in result[x]['refs'] |
|
79 | assert 'tags' in result[x]['refs'] | |
81 |
|
80 | |||
82 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
81 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) | |
83 | @pytest.mark.parametrize("start_rev, expected_revision", [ |
|
82 | @pytest.mark.parametrize("start_rev, expected_revision", [ | |
84 | ("0", 0), |
|
83 | ("0", 0), | |
85 | ("10", 10), |
|
84 | ("10", 10), | |
86 | ("20", 20), |
|
85 | ("20", 20), | |
87 | ]) |
|
86 | ]) | |
88 | @pytest.mark.backends("hg", "git") |
|
87 | @pytest.mark.backends("hg", "git") | |
89 | def test_get_repo_changesets_commit_range( |
|
88 | def test_get_repo_changesets_commit_range( | |
90 | self, details, backend, start_rev, expected_revision): |
|
89 | self, details, backend, start_rev, expected_revision): | |
91 | limit = 10 |
|
90 | limit = 10 | |
92 | __, params = build_data( |
|
91 | __, params = build_data( | |
93 | self.apikey, 'get_repo_changesets', |
|
92 | self.apikey, 'get_repo_changesets', | |
94 | repoid=backend.repo_name, start_rev=start_rev, limit=limit, |
|
93 | repoid=backend.repo_name, start_rev=start_rev, limit=limit, | |
95 | details=details, |
|
94 | details=details, | |
96 | ) |
|
95 | ) | |
97 | response = api_call(self.app, params) |
|
96 | response = api_call(self.app, params) | |
98 | result = response.json['result'] |
|
97 | result = response.json['result'] | |
99 | assert result |
|
98 | assert result | |
100 | assert len(result) == limit |
|
99 | assert len(result) == limit | |
101 | for i in range(limit): |
|
100 | for i in range(limit): | |
102 | assert result[i]['revision'] == int(expected_revision) + i |
|
101 | assert result[i]['revision'] == int(expected_revision) + i | |
103 |
|
102 | |||
104 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
103 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) | |
105 | @pytest.mark.parametrize("start_rev, expected_revision", [ |
|
104 | @pytest.mark.parametrize("start_rev, expected_revision", [ | |
106 | ("0", 0), |
|
105 | ("0", 0), | |
107 | ("10", 9), |
|
106 | ("10", 9), | |
108 | ("20", 19), |
|
107 | ("20", 19), | |
109 | ]) |
|
108 | ]) | |
110 | def test_get_repo_changesets_commit_range_svn( |
|
109 | def test_get_repo_changesets_commit_range_svn( | |
111 | self, details, backend_svn, start_rev, expected_revision): |
|
110 | self, details, backend_svn, start_rev, expected_revision): | |
112 |
|
111 | |||
113 | # TODO: johbo: SVN showed a problem here: The parameter "start_rev" |
|
112 | # TODO: johbo: SVN showed a problem here: The parameter "start_rev" | |
114 | # in our API allows to pass in a "Commit ID" as well as a |
|
113 | # in our API allows to pass in a "Commit ID" as well as a | |
115 | # "Commit Index". In the case of Subversion it is not possible to |
|
114 | # "Commit Index". In the case of Subversion it is not possible to | |
116 | # distinguish these cases. As a workaround we implemented this |
|
115 | # distinguish these cases. As a workaround we implemented this | |
117 | # behavior which gives a preference to see it as a "Commit ID". |
|
116 | # behavior which gives a preference to see it as a "Commit ID". | |
118 |
|
117 | |||
119 | limit = 10 |
|
118 | limit = 10 | |
120 | __, params = build_data( |
|
119 | __, params = build_data( | |
121 | self.apikey, 'get_repo_changesets', |
|
120 | self.apikey, 'get_repo_changesets', | |
122 | repoid=backend_svn.repo_name, start_rev=start_rev, limit=limit, |
|
121 | repoid=backend_svn.repo_name, start_rev=start_rev, limit=limit, | |
123 | details=details, |
|
122 | details=details, | |
124 | ) |
|
123 | ) | |
125 | response = api_call(self.app, params) |
|
124 | response = api_call(self.app, params) | |
126 | result = response.json['result'] |
|
125 | result = response.json['result'] | |
127 | assert result |
|
126 | assert result | |
128 | assert len(result) == limit |
|
127 | assert len(result) == limit | |
129 | for i in range(limit): |
|
128 | for i in range(limit): | |
130 | assert result[i]['revision'] == int(expected_revision) + i |
|
129 | assert result[i]['revision'] == int(expected_revision) + i | |
131 |
|
130 | |||
132 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
131 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) | |
133 | def test_get_repo_changesets_bad_type(self, details, backend): |
|
132 | def test_get_repo_changesets_bad_type(self, details, backend): | |
134 | id_, params = build_data( |
|
133 | id_, params = build_data( | |
135 | self.apikey, 'get_repo_changesets', |
|
134 | self.apikey, 'get_repo_changesets', | |
136 | repoid=backend.repo_name, start_rev=0, limit=2, |
|
135 | repoid=backend.repo_name, start_rev=0, limit=2, | |
137 | details=details, |
|
136 | details=details, | |
138 | ) |
|
137 | ) | |
139 | response = api_call(self.app, params) |
|
138 | response = api_call(self.app, params) | |
140 |
expected = "commit_id must be a string value got < |
|
139 | expected = "commit_id must be a string value got <class 'int'> instead" | |
141 | assert_error(id_, expected, given=response.body) |
|
140 | assert_error(id_, expected, given=response.body) |
@@ -1,142 +1,141 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.db import User, ChangesetComment |
|
23 | from rhodecode.model.db import User, ChangesetComment | |
25 | from rhodecode.model.meta import Session |
|
24 | from rhodecode.model.meta import Session | |
26 | from rhodecode.model.comment import CommentsModel |
|
25 | from rhodecode.model.comment import CommentsModel | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_call_ok) |
|
27 | build_data, api_call, assert_error, assert_call_ok) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.fixture() |
|
30 | @pytest.fixture() | |
32 | def make_repo_comments_factory(request): |
|
31 | def make_repo_comments_factory(request): | |
33 |
|
32 | |||
34 | class Make(object): |
|
33 | class Make(object): | |
35 |
|
34 | |||
36 | def make_comments(self, repo): |
|
35 | def make_comments(self, repo): | |
37 | user = User.get_first_super_admin() |
|
36 | user = User.get_first_super_admin() | |
38 | commit = repo.scm_instance()[0] |
|
37 | commit = repo.scm_instance()[0] | |
39 |
|
38 | |||
40 | commit_id = commit.raw_id |
|
39 | commit_id = commit.raw_id | |
41 | file_0 = commit.affected_files[0] |
|
40 | file_0 = commit.affected_files[0] | |
42 | comments = [] |
|
41 | comments = [] | |
43 |
|
42 | |||
44 | # general |
|
43 | # general | |
45 | comment = CommentsModel().create( |
|
44 | comment = CommentsModel().create( | |
46 | text='General Comment', repo=repo, user=user, commit_id=commit_id, |
|
45 | text='General Comment', repo=repo, user=user, commit_id=commit_id, | |
47 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) |
|
46 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) | |
48 | comments.append(comment) |
|
47 | comments.append(comment) | |
49 |
|
48 | |||
50 | # inline |
|
49 | # inline | |
51 | comment = CommentsModel().create( |
|
50 | comment = CommentsModel().create( | |
52 | text='Inline Comment', repo=repo, user=user, commit_id=commit_id, |
|
51 | text='Inline Comment', repo=repo, user=user, commit_id=commit_id, | |
53 | f_path=file_0, line_no='n1', |
|
52 | f_path=file_0, line_no='n1', | |
54 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) |
|
53 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) | |
55 | comments.append(comment) |
|
54 | comments.append(comment) | |
56 |
|
55 | |||
57 | # todo |
|
56 | # todo | |
58 | comment = CommentsModel().create( |
|
57 | comment = CommentsModel().create( | |
59 | text='INLINE TODO Comment', repo=repo, user=user, commit_id=commit_id, |
|
58 | text='INLINE TODO Comment', repo=repo, user=user, commit_id=commit_id, | |
60 | f_path=file_0, line_no='n1', |
|
59 | f_path=file_0, line_no='n1', | |
61 | comment_type=ChangesetComment.COMMENT_TYPE_TODO, send_email=False) |
|
60 | comment_type=ChangesetComment.COMMENT_TYPE_TODO, send_email=False) | |
62 | comments.append(comment) |
|
61 | comments.append(comment) | |
63 |
|
62 | |||
64 | return comments |
|
63 | return comments | |
65 |
|
64 | |||
66 | return Make() |
|
65 | return Make() | |
67 |
|
66 | |||
68 |
|
67 | |||
69 | @pytest.mark.usefixtures("testuser_api", "app") |
|
68 | @pytest.mark.usefixtures("testuser_api", "app") | |
70 | class TestGetRepo(object): |
|
69 | class TestGetRepo(object): | |
71 |
|
70 | |||
72 | @pytest.mark.parametrize('filters, expected_count', [ |
|
71 | @pytest.mark.parametrize('filters, expected_count', [ | |
73 | ({}, 3), |
|
72 | ({}, 3), | |
74 | ({'comment_type': ChangesetComment.COMMENT_TYPE_NOTE}, 2), |
|
73 | ({'comment_type': ChangesetComment.COMMENT_TYPE_NOTE}, 2), | |
75 | ({'comment_type': ChangesetComment.COMMENT_TYPE_TODO}, 1), |
|
74 | ({'comment_type': ChangesetComment.COMMENT_TYPE_TODO}, 1), | |
76 | ({'commit_id': 'FILLED DYNAMIC'}, 3), |
|
75 | ({'commit_id': 'FILLED DYNAMIC'}, 3), | |
77 | ]) |
|
76 | ]) | |
78 | def test_api_get_repo_comments(self, backend, user_util, |
|
77 | def test_api_get_repo_comments(self, backend, user_util, | |
79 | make_repo_comments_factory, filters, expected_count): |
|
78 | make_repo_comments_factory, filters, expected_count): | |
80 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
79 | commits = [{'message': 'A'}, {'message': 'B'}] | |
81 | repo = backend.create_repo(commits=commits) |
|
80 | repo = backend.create_repo(commits=commits) | |
82 | make_repo_comments_factory.make_comments(repo) |
|
81 | make_repo_comments_factory.make_comments(repo) | |
83 |
|
82 | |||
84 | api_call_params = {'repoid': repo.repo_name,} |
|
83 | api_call_params = {'repoid': repo.repo_name,} | |
85 | api_call_params.update(filters) |
|
84 | api_call_params.update(filters) | |
86 |
|
85 | |||
87 | if 'commit_id' in api_call_params: |
|
86 | if 'commit_id' in api_call_params: | |
88 | commit = repo.scm_instance()[0] |
|
87 | commit = repo.scm_instance()[0] | |
89 | commit_id = commit.raw_id |
|
88 | commit_id = commit.raw_id | |
90 | api_call_params['commit_id'] = commit_id |
|
89 | api_call_params['commit_id'] = commit_id | |
91 |
|
90 | |||
92 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) |
|
91 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) | |
93 | response = api_call(self.app, params) |
|
92 | response = api_call(self.app, params) | |
94 | result = assert_call_ok(id_, given=response.body) |
|
93 | result = assert_call_ok(id_, given=response.body) | |
95 |
|
94 | |||
96 | assert len(result) == expected_count |
|
95 | assert len(result) == expected_count | |
97 |
|
96 | |||
98 | def test_api_get_repo_comments_wrong_comment_type( |
|
97 | def test_api_get_repo_comments_wrong_comment_type( | |
99 | self, make_repo_comments_factory, backend_hg): |
|
98 | self, make_repo_comments_factory, backend_hg): | |
100 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
99 | commits = [{'message': 'A'}, {'message': 'B'}] | |
101 | repo = backend_hg.create_repo(commits=commits) |
|
100 | repo = backend_hg.create_repo(commits=commits) | |
102 | make_repo_comments_factory.make_comments(repo) |
|
101 | make_repo_comments_factory.make_comments(repo) | |
103 |
|
102 | |||
104 | api_call_params = {'repoid': repo.repo_name} |
|
103 | api_call_params = {'repoid': repo.repo_name} | |
105 | api_call_params.update({'comment_type': 'bogus'}) |
|
104 | api_call_params.update({'comment_type': 'bogus'}) | |
106 |
|
105 | |||
107 | expected = 'comment_type must be one of `{}` got {}'.format( |
|
106 | expected = 'comment_type must be one of `{}` got {}'.format( | |
108 | ChangesetComment.COMMENT_TYPES, 'bogus') |
|
107 | ChangesetComment.COMMENT_TYPES, 'bogus') | |
109 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) |
|
108 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) | |
110 | response = api_call(self.app, params) |
|
109 | response = api_call(self.app, params) | |
111 | assert_error(id_, expected, given=response.body) |
|
110 | assert_error(id_, expected, given=response.body) | |
112 |
|
111 | |||
113 | def test_api_get_comment(self, make_repo_comments_factory, backend_hg): |
|
112 | def test_api_get_comment(self, make_repo_comments_factory, backend_hg): | |
114 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
113 | commits = [{'message': 'A'}, {'message': 'B'}] | |
115 | repo = backend_hg.create_repo(commits=commits) |
|
114 | repo = backend_hg.create_repo(commits=commits) | |
116 |
|
115 | |||
117 | comments = make_repo_comments_factory.make_comments(repo) |
|
116 | comments = make_repo_comments_factory.make_comments(repo) | |
118 | comment_ids = [x.comment_id for x in comments] |
|
117 | comment_ids = [x.comment_id for x in comments] | |
119 | Session().commit() |
|
118 | Session().commit() | |
120 |
|
119 | |||
121 | for comment_id in comment_ids: |
|
120 | for comment_id in comment_ids: | |
122 | id_, params = build_data(self.apikey, 'get_comment', |
|
121 | id_, params = build_data(self.apikey, 'get_comment', | |
123 | **{'comment_id': comment_id}) |
|
122 | **{'comment_id': comment_id}) | |
124 | response = api_call(self.app, params) |
|
123 | response = api_call(self.app, params) | |
125 | result = assert_call_ok(id_, given=response.body) |
|
124 | result = assert_call_ok(id_, given=response.body) | |
126 | assert result['comment_id'] == comment_id |
|
125 | assert result['comment_id'] == comment_id | |
127 |
|
126 | |||
128 | def test_api_get_comment_no_access(self, make_repo_comments_factory, backend_hg, user_util): |
|
127 | def test_api_get_comment_no_access(self, make_repo_comments_factory, backend_hg, user_util): | |
129 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
128 | commits = [{'message': 'A'}, {'message': 'B'}] | |
130 | repo = backend_hg.create_repo(commits=commits) |
|
129 | repo = backend_hg.create_repo(commits=commits) | |
131 | comments = make_repo_comments_factory.make_comments(repo) |
|
130 | comments = make_repo_comments_factory.make_comments(repo) | |
132 | comment_id = comments[0].comment_id |
|
131 | comment_id = comments[0].comment_id | |
133 |
|
132 | |||
134 | test_user = user_util.create_user() |
|
133 | test_user = user_util.create_user() | |
135 | user_util.grant_user_permission_to_repo(repo, test_user, 'repository.none') |
|
134 | user_util.grant_user_permission_to_repo(repo, test_user, 'repository.none') | |
136 |
|
135 | |||
137 | id_, params = build_data(test_user.api_key, 'get_comment', |
|
136 | id_, params = build_data(test_user.api_key, 'get_comment', | |
138 | **{'comment_id': comment_id}) |
|
137 | **{'comment_id': comment_id}) | |
139 | response = api_call(self.app, params) |
|
138 | response = api_call(self.app, params) | |
140 | assert_error(id_, |
|
139 | assert_error(id_, | |
141 | expected='comment `{}` does not exist'.format(comment_id), |
|
140 | expected='comment `{}` does not exist'.format(comment_id), | |
142 | given=response.body) |
|
141 | given=response.body) |
@@ -1,55 +1,54 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo_group import RepoGroupModel |
|
23 | from rhodecode.model.repo_group import RepoGroupModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
25 | build_data, api_call, assert_ok, assert_error, expected_permissions) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestApiGetRepoGroup(object): |
|
29 | class TestApiGetRepoGroup(object): | |
31 | def test_api_get_repo_group(self, user_util): |
|
30 | def test_api_get_repo_group(self, user_util): | |
32 | repo_group = user_util.create_repo_group() |
|
31 | repo_group = user_util.create_repo_group() | |
33 | repo_group_name = repo_group.group_name |
|
32 | repo_group_name = repo_group.group_name | |
34 |
|
33 | |||
35 | id_, params = build_data( |
|
34 | id_, params = build_data( | |
36 | self.apikey, 'get_repo_group', repogroupid=repo_group_name) |
|
35 | self.apikey, 'get_repo_group', repogroupid=repo_group_name) | |
37 | response = api_call(self.app, params) |
|
36 | response = api_call(self.app, params) | |
38 |
|
37 | |||
39 | repo_group = RepoGroupModel()._get_repo_group(repo_group_name) |
|
38 | repo_group = RepoGroupModel()._get_repo_group(repo_group_name) | |
40 | ret = repo_group.get_api_data() |
|
39 | ret = repo_group.get_api_data() | |
41 |
|
40 | |||
42 | permissions = expected_permissions(repo_group) |
|
41 | permissions = expected_permissions(repo_group) | |
43 |
|
42 | |||
44 | ret['permissions'] = permissions |
|
43 | ret['permissions'] = permissions | |
45 | expected = ret |
|
44 | expected = ret | |
46 | assert_ok(id_, expected, given=response.body) |
|
45 | assert_ok(id_, expected, given=response.body) | |
47 |
|
46 | |||
48 | def test_api_get_repo_group_not_existing(self): |
|
47 | def test_api_get_repo_group_not_existing(self): | |
49 | id_, params = build_data( |
|
48 | id_, params = build_data( | |
50 | self.apikey, 'get_repo_group', repogroupid='no-such-repo-group') |
|
49 | self.apikey, 'get_repo_group', repogroupid='no-such-repo-group') | |
51 | response = api_call(self.app, params) |
|
50 | response = api_call(self.app, params) | |
52 |
|
51 | |||
53 | ret = 'repository group `%s` does not exist' % 'no-such-repo-group' |
|
52 | ret = 'repository group `%s` does not exist' % 'no-such-repo-group' | |
54 | expected = ret |
|
53 | expected = ret | |
55 | assert_error(id_, expected, given=response.body) |
|
54 | assert_error(id_, expected, given=response.body) |
@@ -1,40 +1,39 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo_group import RepoGroupModel |
|
23 | from rhodecode.model.repo_group import RepoGroupModel | |
25 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok, jsonify |
|
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok, jsonify | |
26 |
|
25 | |||
27 |
|
26 | |||
28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
27 | @pytest.mark.usefixtures("testuser_api", "app") | |
29 | class TestApiGetRepoGroups(object): |
|
28 | class TestApiGetRepoGroups(object): | |
30 | def test_api_get_repo_groups(self): |
|
29 | def test_api_get_repo_groups(self): | |
31 | id_, params = build_data(self.apikey, 'get_repo_groups') |
|
30 | id_, params = build_data(self.apikey, 'get_repo_groups') | |
32 | response = api_call(self.app, params) |
|
31 | response = api_call(self.app, params) | |
33 |
|
32 | |||
34 | result = [] |
|
33 | result = [] | |
35 | for repo in RepoGroupModel().get_all(): |
|
34 | for repo in RepoGroupModel().get_all(): | |
36 | result.append(repo.get_api_data()) |
|
35 | result.append(repo.get_api_data()) | |
37 | ret = jsonify(result) |
|
36 | ret = jsonify(result) | |
38 |
|
37 | |||
39 | expected = ret |
|
38 | expected = ret | |
40 | assert_ok(id_, expected, given=response.body) |
|
39 | assert_ok(id_, expected, given=response.body) |
@@ -1,142 +1,141 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.model.repo import RepoModel |
|
24 | from rhodecode.model.repo import RepoModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok) |
|
26 | build_data, api_call, assert_error, assert_ok) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGetRepoNodes(object): |
|
30 | class TestGetRepoNodes(object): | |
32 | @pytest.mark.parametrize("name, ret_type", [ |
|
31 | @pytest.mark.parametrize("name, ret_type", [ | |
33 | ('all', 'all'), |
|
32 | ('all', 'all'), | |
34 | ('dirs', 'dirs'), |
|
33 | ('dirs', 'dirs'), | |
35 | ('files', 'files'), |
|
34 | ('files', 'files'), | |
36 | ]) |
|
35 | ]) | |
37 | def test_api_get_repo_nodes(self, name, ret_type, backend): |
|
36 | def test_api_get_repo_nodes(self, name, ret_type, backend): | |
38 | commit_id = 'tip' |
|
37 | commit_id = 'tip' | |
39 | path = '/' |
|
38 | path = '/' | |
40 | id_, params = build_data( |
|
39 | id_, params = build_data( | |
41 | self.apikey, 'get_repo_nodes', |
|
40 | self.apikey, 'get_repo_nodes', | |
42 | repoid=backend.repo_name, revision=commit_id, |
|
41 | repoid=backend.repo_name, revision=commit_id, | |
43 | root_path=path, |
|
42 | root_path=path, | |
44 | ret_type=ret_type) |
|
43 | ret_type=ret_type) | |
45 | response = api_call(self.app, params) |
|
44 | response = api_call(self.app, params) | |
46 |
|
45 | |||
47 | # we don't the actual return types here since it's tested somewhere |
|
46 | # we don't the actual return types here since it's tested somewhere | |
48 | # else |
|
47 | # else | |
49 | expected = response.json['result'] |
|
48 | expected = response.json['result'] | |
50 | assert_ok(id_, expected, given=response.body) |
|
49 | assert_ok(id_, expected, given=response.body) | |
51 |
|
50 | |||
52 | def test_api_get_repo_nodes_bad_commits(self, backend): |
|
51 | def test_api_get_repo_nodes_bad_commits(self, backend): | |
53 | commit_id = 'i-dont-exist' |
|
52 | commit_id = 'i-dont-exist' | |
54 | path = '/' |
|
53 | path = '/' | |
55 | id_, params = build_data( |
|
54 | id_, params = build_data( | |
56 | self.apikey, 'get_repo_nodes', |
|
55 | self.apikey, 'get_repo_nodes', | |
57 | repoid=backend.repo_name, revision=commit_id, |
|
56 | repoid=backend.repo_name, revision=commit_id, | |
58 | root_path=path, ) |
|
57 | root_path=path, ) | |
59 | response = api_call(self.app, params) |
|
58 | response = api_call(self.app, params) | |
60 |
|
59 | |||
61 | expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,) |
|
60 | expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,) | |
62 | assert_error(id_, expected, given=response.body) |
|
61 | assert_error(id_, expected, given=response.body) | |
63 |
|
62 | |||
64 | def test_api_get_repo_nodes_bad_path(self, backend): |
|
63 | def test_api_get_repo_nodes_bad_path(self, backend): | |
65 | commit_id = 'tip' |
|
64 | commit_id = 'tip' | |
66 | path = '/idontexits' |
|
65 | path = '/idontexits' | |
67 | id_, params = build_data( |
|
66 | id_, params = build_data( | |
68 | self.apikey, 'get_repo_nodes', |
|
67 | self.apikey, 'get_repo_nodes', | |
69 | repoid=backend.repo_name, revision=commit_id, |
|
68 | repoid=backend.repo_name, revision=commit_id, | |
70 | root_path=path, ) |
|
69 | root_path=path, ) | |
71 | response = api_call(self.app, params) |
|
70 | response = api_call(self.app, params) | |
72 |
|
71 | |||
73 | expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,) |
|
72 | expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,) | |
74 | assert_error(id_, expected, given=response.body) |
|
73 | assert_error(id_, expected, given=response.body) | |
75 |
|
74 | |||
76 | def test_api_get_repo_nodes_max_file_bytes(self, backend): |
|
75 | def test_api_get_repo_nodes_max_file_bytes(self, backend): | |
77 | commit_id = 'tip' |
|
76 | commit_id = 'tip' | |
78 | path = '/' |
|
77 | path = '/' | |
79 | max_file_bytes = 500 |
|
78 | max_file_bytes = 500 | |
80 |
|
79 | |||
81 | id_, params = build_data( |
|
80 | id_, params = build_data( | |
82 | self.apikey, 'get_repo_nodes', |
|
81 | self.apikey, 'get_repo_nodes', | |
83 | repoid=backend.repo_name, revision=commit_id, details='full', |
|
82 | repoid=backend.repo_name, revision=commit_id, details='full', | |
84 | root_path=path) |
|
83 | root_path=path) | |
85 | response = api_call(self.app, params) |
|
84 | response = api_call(self.app, params) | |
86 | assert any(file['content'] and len(file['content']) > max_file_bytes |
|
85 | assert any(file['content'] and len(file['content']) > max_file_bytes | |
87 | for file in response.json['result']) |
|
86 | for file in response.json['result']) | |
88 |
|
87 | |||
89 | id_, params = build_data( |
|
88 | id_, params = build_data( | |
90 | self.apikey, 'get_repo_nodes', |
|
89 | self.apikey, 'get_repo_nodes', | |
91 | repoid=backend.repo_name, revision=commit_id, |
|
90 | repoid=backend.repo_name, revision=commit_id, | |
92 | root_path=path, details='full', |
|
91 | root_path=path, details='full', | |
93 | max_file_bytes=max_file_bytes) |
|
92 | max_file_bytes=max_file_bytes) | |
94 | response = api_call(self.app, params) |
|
93 | response = api_call(self.app, params) | |
95 | assert all( |
|
94 | assert all( | |
96 | file['content'] is None if file['size'] > max_file_bytes else True |
|
95 | file['content'] is None if file['size'] > max_file_bytes else True | |
97 | for file in response.json['result']) |
|
96 | for file in response.json['result']) | |
98 |
|
97 | |||
99 | def test_api_get_repo_nodes_bad_ret_type(self, backend): |
|
98 | def test_api_get_repo_nodes_bad_ret_type(self, backend): | |
100 | commit_id = 'tip' |
|
99 | commit_id = 'tip' | |
101 | path = '/' |
|
100 | path = '/' | |
102 | ret_type = 'error' |
|
101 | ret_type = 'error' | |
103 | id_, params = build_data( |
|
102 | id_, params = build_data( | |
104 | self.apikey, 'get_repo_nodes', |
|
103 | self.apikey, 'get_repo_nodes', | |
105 | repoid=backend.repo_name, revision=commit_id, |
|
104 | repoid=backend.repo_name, revision=commit_id, | |
106 | root_path=path, |
|
105 | root_path=path, | |
107 | ret_type=ret_type) |
|
106 | ret_type=ret_type) | |
108 | response = api_call(self.app, params) |
|
107 | response = api_call(self.app, params) | |
109 |
|
108 | |||
110 | expected = ('ret_type must be one of %s' |
|
109 | expected = ('ret_type must be one of %s' | |
111 | % (','.join(['all', 'dirs', 'files']))) |
|
110 | % (','.join(['all', 'dirs', 'files']))) | |
112 | assert_error(id_, expected, given=response.body) |
|
111 | assert_error(id_, expected, given=response.body) | |
113 |
|
112 | |||
114 | @pytest.mark.parametrize("name, ret_type, grant_perm", [ |
|
113 | @pytest.mark.parametrize("name, ret_type, grant_perm", [ | |
115 | ('all', 'all', 'repository.write'), |
|
114 | ('all', 'all', 'repository.write'), | |
116 | ('dirs', 'dirs', 'repository.admin'), |
|
115 | ('dirs', 'dirs', 'repository.admin'), | |
117 | ('files', 'files', 'repository.read'), |
|
116 | ('files', 'files', 'repository.read'), | |
118 | ]) |
|
117 | ]) | |
119 | def test_api_get_repo_nodes_by_regular_user( |
|
118 | def test_api_get_repo_nodes_by_regular_user( | |
120 | self, name, ret_type, grant_perm, backend): |
|
119 | self, name, ret_type, grant_perm, backend): | |
121 | RepoModel().grant_user_permission(repo=backend.repo_name, |
|
120 | RepoModel().grant_user_permission(repo=backend.repo_name, | |
122 | user=self.TEST_USER_LOGIN, |
|
121 | user=self.TEST_USER_LOGIN, | |
123 | perm=grant_perm) |
|
122 | perm=grant_perm) | |
124 | Session().commit() |
|
123 | Session().commit() | |
125 |
|
124 | |||
126 | commit_id = 'tip' |
|
125 | commit_id = 'tip' | |
127 | path = '/' |
|
126 | path = '/' | |
128 | id_, params = build_data( |
|
127 | id_, params = build_data( | |
129 | self.apikey_regular, 'get_repo_nodes', |
|
128 | self.apikey_regular, 'get_repo_nodes', | |
130 | repoid=backend.repo_name, revision=commit_id, |
|
129 | repoid=backend.repo_name, revision=commit_id, | |
131 | root_path=path, |
|
130 | root_path=path, | |
132 | ret_type=ret_type) |
|
131 | ret_type=ret_type) | |
133 | response = api_call(self.app, params) |
|
132 | response = api_call(self.app, params) | |
134 |
|
133 | |||
135 | # we don't the actual return types here since it's tested somewhere |
|
134 | # we don't the actual return types here since it's tested somewhere | |
136 | # else |
|
135 | # else | |
137 | expected = response.json['result'] |
|
136 | expected = response.json['result'] | |
138 | try: |
|
137 | try: | |
139 | assert_ok(id_, expected, given=response.body) |
|
138 | assert_ok(id_, expected, given=response.body) | |
140 | finally: |
|
139 | finally: | |
141 | RepoModel().revoke_user_permission( |
|
140 | RepoModel().revoke_user_permission( | |
142 | backend.repo_name, self.TEST_USER_LOGIN) |
|
141 | backend.repo_name, self.TEST_USER_LOGIN) |
@@ -1,40 +1,39 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.model.repo import RepoModel |
|
24 | from rhodecode.model.repo import RepoModel | |
26 | from rhodecode.model.user import UserModel |
|
25 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
28 | from rhodecode.api.tests.utils import ( |
|
27 | from rhodecode.api.tests.utils import ( | |
29 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
28 | build_data, api_call, assert_ok, assert_error, expected_permissions) | |
30 |
|
29 | |||
31 |
|
30 | |||
32 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | @pytest.mark.usefixtures("testuser_api", "app") | |
33 | class TestGetRepo(object): |
|
32 | class TestGetRepo(object): | |
34 | def test_api_get_repo_refs(self, backend, user_util): |
|
33 | def test_api_get_repo_refs(self, backend, user_util): | |
35 | repo = backend.create_repo() |
|
34 | repo = backend.create_repo() | |
36 | id_, params = build_data(self.apikey, 'get_repo_refs', |
|
35 | id_, params = build_data(self.apikey, 'get_repo_refs', | |
37 | **{'repoid': repo.repo_name,}) |
|
36 | **{'repoid': repo.repo_name,}) | |
38 | response = api_call(self.app, params) |
|
37 | response = api_call(self.app, params) | |
39 | expected = repo.scm_instance().refs() |
|
38 | expected = repo.scm_instance().refs() | |
40 | assert_ok(id_, expected, given=response.body) |
|
39 | assert_ok(id_, expected, given=response.body) |
@@ -1,129 +1,128 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_ok, assert_error, jsonify) |
|
25 | build_data, api_call, assert_ok, assert_error, jsonify) | |
27 | from rhodecode.model.db import User |
|
26 | from rhodecode.model.db import User | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGetRepos(object): |
|
30 | class TestGetRepos(object): | |
32 | def test_api_get_repos(self): |
|
31 | def test_api_get_repos(self): | |
33 | id_, params = build_data(self.apikey, 'get_repos') |
|
32 | id_, params = build_data(self.apikey, 'get_repos') | |
34 | response = api_call(self.app, params) |
|
33 | response = api_call(self.app, params) | |
35 |
|
34 | |||
36 | result = [] |
|
35 | result = [] | |
37 | for repo in RepoModel().get_all(): |
|
36 | for repo in RepoModel().get_all(): | |
38 | result.append(repo.get_api_data(include_secrets=True)) |
|
37 | result.append(repo.get_api_data(include_secrets=True)) | |
39 | ret = jsonify(result) |
|
38 | ret = jsonify(result) | |
40 |
|
39 | |||
41 | expected = ret |
|
40 | expected = ret | |
42 | assert_ok(id_, expected, given=response.body) |
|
41 | assert_ok(id_, expected, given=response.body) | |
43 |
|
42 | |||
44 | def test_api_get_repos_only_toplevel(self, user_util): |
|
43 | def test_api_get_repos_only_toplevel(self, user_util): | |
45 | repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
44 | repo_group = user_util.create_repo_group(auto_cleanup=True) | |
46 | user_util.create_repo(parent=repo_group) |
|
45 | user_util.create_repo(parent=repo_group) | |
47 |
|
46 | |||
48 | id_, params = build_data(self.apikey, 'get_repos', traverse=0) |
|
47 | id_, params = build_data(self.apikey, 'get_repos', traverse=0) | |
49 | response = api_call(self.app, params) |
|
48 | response = api_call(self.app, params) | |
50 |
|
49 | |||
51 | result = [] |
|
50 | result = [] | |
52 | for repo in RepoModel().get_repos_for_root(root=None): |
|
51 | for repo in RepoModel().get_repos_for_root(root=None): | |
53 | result.append(repo.get_api_data(include_secrets=True)) |
|
52 | result.append(repo.get_api_data(include_secrets=True)) | |
54 | expected = jsonify(result) |
|
53 | expected = jsonify(result) | |
55 |
|
54 | |||
56 | assert_ok(id_, expected, given=response.body) |
|
55 | assert_ok(id_, expected, given=response.body) | |
57 |
|
56 | |||
58 | def test_api_get_repos_with_wrong_root(self): |
|
57 | def test_api_get_repos_with_wrong_root(self): | |
59 | id_, params = build_data(self.apikey, 'get_repos', root='abracadabra') |
|
58 | id_, params = build_data(self.apikey, 'get_repos', root='abracadabra') | |
60 | response = api_call(self.app, params) |
|
59 | response = api_call(self.app, params) | |
61 |
|
60 | |||
62 | expected = 'Root repository group `abracadabra` does not exist' |
|
61 | expected = 'Root repository group `abracadabra` does not exist' | |
63 | assert_error(id_, expected, given=response.body) |
|
62 | assert_error(id_, expected, given=response.body) | |
64 |
|
63 | |||
65 | def test_api_get_repos_with_root(self, user_util): |
|
64 | def test_api_get_repos_with_root(self, user_util): | |
66 | repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
65 | repo_group = user_util.create_repo_group(auto_cleanup=True) | |
67 | repo_group_name = repo_group.group_name |
|
66 | repo_group_name = repo_group.group_name | |
68 |
|
67 | |||
69 | user_util.create_repo(parent=repo_group) |
|
68 | user_util.create_repo(parent=repo_group) | |
70 | user_util.create_repo(parent=repo_group) |
|
69 | user_util.create_repo(parent=repo_group) | |
71 |
|
70 | |||
72 | # nested, should not show up |
|
71 | # nested, should not show up | |
73 | user_util._test_name = '{}/'.format(repo_group_name) |
|
72 | user_util._test_name = '{}/'.format(repo_group_name) | |
74 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
73 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) | |
75 | user_util.create_repo(parent=sub_repo_group) |
|
74 | user_util.create_repo(parent=sub_repo_group) | |
76 |
|
75 | |||
77 | id_, params = build_data(self.apikey, 'get_repos', |
|
76 | id_, params = build_data(self.apikey, 'get_repos', | |
78 | root=repo_group_name, traverse=0) |
|
77 | root=repo_group_name, traverse=0) | |
79 | response = api_call(self.app, params) |
|
78 | response = api_call(self.app, params) | |
80 |
|
79 | |||
81 | result = [] |
|
80 | result = [] | |
82 | for repo in RepoModel().get_repos_for_root(repo_group): |
|
81 | for repo in RepoModel().get_repos_for_root(repo_group): | |
83 | result.append(repo.get_api_data(include_secrets=True)) |
|
82 | result.append(repo.get_api_data(include_secrets=True)) | |
84 |
|
83 | |||
85 | assert len(result) == 2 |
|
84 | assert len(result) == 2 | |
86 | expected = jsonify(result) |
|
85 | expected = jsonify(result) | |
87 | assert_ok(id_, expected, given=response.body) |
|
86 | assert_ok(id_, expected, given=response.body) | |
88 |
|
87 | |||
89 | def test_api_get_repos_with_root_and_traverse(self, user_util): |
|
88 | def test_api_get_repos_with_root_and_traverse(self, user_util): | |
90 | repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
89 | repo_group = user_util.create_repo_group(auto_cleanup=True) | |
91 | repo_group_name = repo_group.group_name |
|
90 | repo_group_name = repo_group.group_name | |
92 |
|
91 | |||
93 | user_util.create_repo(parent=repo_group) |
|
92 | user_util.create_repo(parent=repo_group) | |
94 | user_util.create_repo(parent=repo_group) |
|
93 | user_util.create_repo(parent=repo_group) | |
95 |
|
94 | |||
96 | # nested, should not show up |
|
95 | # nested, should not show up | |
97 | user_util._test_name = '{}/'.format(repo_group_name) |
|
96 | user_util._test_name = '{}/'.format(repo_group_name) | |
98 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
97 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) | |
99 | user_util.create_repo(parent=sub_repo_group) |
|
98 | user_util.create_repo(parent=sub_repo_group) | |
100 |
|
99 | |||
101 | id_, params = build_data(self.apikey, 'get_repos', |
|
100 | id_, params = build_data(self.apikey, 'get_repos', | |
102 | root=repo_group_name, traverse=1) |
|
101 | root=repo_group_name, traverse=1) | |
103 | response = api_call(self.app, params) |
|
102 | response = api_call(self.app, params) | |
104 |
|
103 | |||
105 | result = [] |
|
104 | result = [] | |
106 | for repo in RepoModel().get_repos_for_root( |
|
105 | for repo in RepoModel().get_repos_for_root( | |
107 | repo_group_name, traverse=True): |
|
106 | repo_group_name, traverse=True): | |
108 | result.append(repo.get_api_data(include_secrets=True)) |
|
107 | result.append(repo.get_api_data(include_secrets=True)) | |
109 |
|
108 | |||
110 | assert len(result) == 3 |
|
109 | assert len(result) == 3 | |
111 | expected = jsonify(result) |
|
110 | expected = jsonify(result) | |
112 | assert_ok(id_, expected, given=response.body) |
|
111 | assert_ok(id_, expected, given=response.body) | |
113 |
|
112 | |||
114 | def test_api_get_repos_non_admin(self): |
|
113 | def test_api_get_repos_non_admin(self): | |
115 | id_, params = build_data(self.apikey_regular, 'get_repos') |
|
114 | id_, params = build_data(self.apikey_regular, 'get_repos') | |
116 | response = api_call(self.app, params) |
|
115 | response = api_call(self.app, params) | |
117 |
|
116 | |||
118 | user = User.get_by_username(self.TEST_USER_LOGIN) |
|
117 | user = User.get_by_username(self.TEST_USER_LOGIN) | |
119 | allowed_repos = user.AuthUser().permissions['repositories'] |
|
118 | allowed_repos = user.AuthUser().permissions['repositories'] | |
120 |
|
119 | |||
121 | result = [] |
|
120 | result = [] | |
122 | for repo in RepoModel().get_all(): |
|
121 | for repo in RepoModel().get_all(): | |
123 | perm = allowed_repos[repo.repo_name] |
|
122 | perm = allowed_repos[repo.repo_name] | |
124 | if perm in ['repository.read', 'repository.write', 'repository.admin']: |
|
123 | if perm in ['repository.read', 'repository.write', 'repository.admin']: | |
125 | result.append(repo.get_api_data()) |
|
124 | result.append(repo.get_api_data()) | |
126 | ret = jsonify(result) |
|
125 | ret = jsonify(result) | |
127 |
|
126 | |||
128 | expected = ret |
|
127 | expected = ret | |
129 | assert_ok(id_, expected, given=response.body) |
|
128 | assert_ok(id_, expected, given=response.body) |
@@ -1,84 +1,83 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.scm import ScmModel |
|
23 | from rhodecode.model.scm import ScmModel | |
25 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok | |
26 |
|
25 | |||
27 |
|
26 | |||
28 | @pytest.fixture() |
|
27 | @pytest.fixture() | |
29 | def http_host_stub(): |
|
28 | def http_host_stub(): | |
30 | """ |
|
29 | """ | |
31 | To ensure that we can get an IP address, this test shall run with a |
|
30 | To ensure that we can get an IP address, this test shall run with a | |
32 | hostname set to "localhost". |
|
31 | hostname set to "localhost". | |
33 | """ |
|
32 | """ | |
34 | return 'localhost:80' |
|
33 | return 'localhost:80' | |
35 |
|
34 | |||
36 |
|
35 | |||
37 | @pytest.mark.usefixtures("testuser_api", "app") |
|
36 | @pytest.mark.usefixtures("testuser_api", "app") | |
38 | class TestGetServerInfo(object): |
|
37 | class TestGetServerInfo(object): | |
39 | def test_api_get_server_info(self): |
|
38 | def test_api_get_server_info(self): | |
40 | id_, params = build_data(self.apikey, 'get_server_info') |
|
39 | id_, params = build_data(self.apikey, 'get_server_info') | |
41 | response = api_call(self.app, params) |
|
40 | response = api_call(self.app, params) | |
42 | resp = response.json |
|
41 | resp = response.json | |
43 | expected = ScmModel().get_server_info() |
|
42 | expected = ScmModel().get_server_info() | |
44 | expected['memory'] = resp['result']['memory'] |
|
43 | expected['memory'] = resp['result']['memory'] | |
45 | expected['uptime'] = resp['result']['uptime'] |
|
44 | expected['uptime'] = resp['result']['uptime'] | |
46 | expected['load'] = resp['result']['load'] |
|
45 | expected['load'] = resp['result']['load'] | |
47 | expected['cpu'] = resp['result']['cpu'] |
|
46 | expected['cpu'] = resp['result']['cpu'] | |
48 | expected['storage'] = resp['result']['storage'] |
|
47 | expected['storage'] = resp['result']['storage'] | |
49 | expected['storage_temp'] = resp['result']['storage_temp'] |
|
48 | expected['storage_temp'] = resp['result']['storage_temp'] | |
50 | expected['storage_inodes'] = resp['result']['storage_inodes'] |
|
49 | expected['storage_inodes'] = resp['result']['storage_inodes'] | |
51 | expected['server'] = resp['result']['server'] |
|
50 | expected['server'] = resp['result']['server'] | |
52 |
|
51 | |||
53 | expected['index_storage'] = resp['result']['index_storage'] |
|
52 | expected['index_storage'] = resp['result']['index_storage'] | |
54 | expected['storage'] = resp['result']['storage'] |
|
53 | expected['storage'] = resp['result']['storage'] | |
55 |
|
54 | |||
56 | assert_ok(id_, expected, given=response.body) |
|
55 | assert_ok(id_, expected, given=response.body) | |
57 |
|
56 | |||
58 | def test_api_get_server_info_ip(self): |
|
57 | def test_api_get_server_info_ip(self): | |
59 | id_, params = build_data(self.apikey, 'get_server_info') |
|
58 | id_, params = build_data(self.apikey, 'get_server_info') | |
60 | response = api_call(self.app, params) |
|
59 | response = api_call(self.app, params) | |
61 | resp = response.json |
|
60 | resp = response.json | |
62 | expected = ScmModel().get_server_info({'SERVER_NAME': 'unknown'}) |
|
61 | expected = ScmModel().get_server_info({'SERVER_NAME': 'unknown'}) | |
63 | expected['memory'] = resp['result']['memory'] |
|
62 | expected['memory'] = resp['result']['memory'] | |
64 | expected['uptime'] = resp['result']['uptime'] |
|
63 | expected['uptime'] = resp['result']['uptime'] | |
65 | expected['load'] = resp['result']['load'] |
|
64 | expected['load'] = resp['result']['load'] | |
66 | expected['cpu'] = resp['result']['cpu'] |
|
65 | expected['cpu'] = resp['result']['cpu'] | |
67 | expected['storage'] = resp['result']['storage'] |
|
66 | expected['storage'] = resp['result']['storage'] | |
68 | expected['storage_temp'] = resp['result']['storage_temp'] |
|
67 | expected['storage_temp'] = resp['result']['storage_temp'] | |
69 | expected['storage_inodes'] = resp['result']['storage_inodes'] |
|
68 | expected['storage_inodes'] = resp['result']['storage_inodes'] | |
70 | expected['server'] = resp['result']['server'] |
|
69 | expected['server'] = resp['result']['server'] | |
71 |
|
70 | |||
72 | expected['index_storage'] = resp['result']['index_storage'] |
|
71 | expected['index_storage'] = resp['result']['index_storage'] | |
73 | expected['storage'] = resp['result']['storage'] |
|
72 | expected['storage'] = resp['result']['storage'] | |
74 |
|
73 | |||
75 | assert_ok(id_, expected, given=response.body) |
|
74 | assert_ok(id_, expected, given=response.body) | |
76 |
|
75 | |||
77 | def test_api_get_server_info_data_for_search_index_build(self): |
|
76 | def test_api_get_server_info_data_for_search_index_build(self): | |
78 | id_, params = build_data(self.apikey, 'get_server_info') |
|
77 | id_, params = build_data(self.apikey, 'get_server_info') | |
79 | response = api_call(self.app, params) |
|
78 | response = api_call(self.app, params) | |
80 | resp = response.json |
|
79 | resp = response.json | |
81 |
|
80 | |||
82 | # required by indexer |
|
81 | # required by indexer | |
83 | assert resp['result']['index_storage'] |
|
82 | assert resp['result']['index_storage'] | |
84 | assert resp['result']['storage'] |
|
83 | assert resp['result']['storage'] |
@@ -1,86 +1,85 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.lib.auth import AuthUser |
|
22 | from rhodecode.lib.auth import AuthUser | |
24 | from rhodecode.model.user import UserModel |
|
23 | from rhodecode.model.user import UserModel | |
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_ok, assert_error) |
|
26 | build_data, api_call, assert_ok, assert_error) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGetUser(object): |
|
30 | class TestGetUser(object): | |
32 | def test_api_get_user(self): |
|
31 | def test_api_get_user(self): | |
33 | id_, params = build_data( |
|
32 | id_, params = build_data( | |
34 | self.apikey, 'get_user', userid=TEST_USER_ADMIN_LOGIN) |
|
33 | self.apikey, 'get_user', userid=TEST_USER_ADMIN_LOGIN) | |
35 | response = api_call(self.app, params) |
|
34 | response = api_call(self.app, params) | |
36 |
|
35 | |||
37 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
36 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
38 | ret = usr.get_api_data(include_secrets=True) |
|
37 | ret = usr.get_api_data(include_secrets=True) | |
39 | permissions = AuthUser(usr.user_id).permissions |
|
38 | permissions = AuthUser(usr.user_id).permissions | |
40 | ret['permissions'] = permissions |
|
39 | ret['permissions'] = permissions | |
41 | ret['permissions_summary'] = permissions |
|
40 | ret['permissions_summary'] = permissions | |
42 |
|
41 | |||
43 | expected = ret |
|
42 | expected = ret | |
44 | assert_ok(id_, expected, given=response.body) |
|
43 | assert_ok(id_, expected, given=response.body) | |
45 |
|
44 | |||
46 | def test_api_get_user_not_existing(self): |
|
45 | def test_api_get_user_not_existing(self): | |
47 | id_, params = build_data(self.apikey, 'get_user', userid='trololo') |
|
46 | id_, params = build_data(self.apikey, 'get_user', userid='trololo') | |
48 | response = api_call(self.app, params) |
|
47 | response = api_call(self.app, params) | |
49 |
|
48 | |||
50 | expected = "user `%s` does not exist" % 'trololo' |
|
49 | expected = "user `%s` does not exist" % 'trololo' | |
51 | assert_error(id_, expected, given=response.body) |
|
50 | assert_error(id_, expected, given=response.body) | |
52 |
|
51 | |||
53 | def test_api_get_user_without_giving_userid(self): |
|
52 | def test_api_get_user_without_giving_userid(self): | |
54 | id_, params = build_data(self.apikey, 'get_user') |
|
53 | id_, params = build_data(self.apikey, 'get_user') | |
55 | response = api_call(self.app, params) |
|
54 | response = api_call(self.app, params) | |
56 |
|
55 | |||
57 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
56 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
58 | ret = usr.get_api_data(include_secrets=True) |
|
57 | ret = usr.get_api_data(include_secrets=True) | |
59 | permissions = AuthUser(usr.user_id).permissions |
|
58 | permissions = AuthUser(usr.user_id).permissions | |
60 | ret['permissions'] = permissions |
|
59 | ret['permissions'] = permissions | |
61 | ret['permissions_summary'] = permissions |
|
60 | ret['permissions_summary'] = permissions | |
62 |
|
61 | |||
63 | expected = ret |
|
62 | expected = ret | |
64 | assert_ok(id_, expected, given=response.body) |
|
63 | assert_ok(id_, expected, given=response.body) | |
65 |
|
64 | |||
66 | def test_api_get_user_without_giving_userid_non_admin(self): |
|
65 | def test_api_get_user_without_giving_userid_non_admin(self): | |
67 | id_, params = build_data(self.apikey_regular, 'get_user') |
|
66 | id_, params = build_data(self.apikey_regular, 'get_user') | |
68 | response = api_call(self.app, params) |
|
67 | response = api_call(self.app, params) | |
69 |
|
68 | |||
70 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
69 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
71 | ret = usr.get_api_data(include_secrets=True) |
|
70 | ret = usr.get_api_data(include_secrets=True) | |
72 | permissions = AuthUser(usr.user_id).permissions |
|
71 | permissions = AuthUser(usr.user_id).permissions | |
73 | ret['permissions'] = permissions |
|
72 | ret['permissions'] = permissions | |
74 | ret['permissions_summary'] = permissions |
|
73 | ret['permissions_summary'] = permissions | |
75 |
|
74 | |||
76 | expected = ret |
|
75 | expected = ret | |
77 | assert_ok(id_, expected, given=response.body) |
|
76 | assert_ok(id_, expected, given=response.body) | |
78 |
|
77 | |||
79 | def test_api_get_user_with_giving_userid_non_admin(self): |
|
78 | def test_api_get_user_with_giving_userid_non_admin(self): | |
80 | id_, params = build_data( |
|
79 | id_, params = build_data( | |
81 | self.apikey_regular, 'get_user', |
|
80 | self.apikey_regular, 'get_user', | |
82 | userid=self.TEST_USER_LOGIN) |
|
81 | userid=self.TEST_USER_LOGIN) | |
83 | response = api_call(self.app, params) |
|
82 | response = api_call(self.app, params) | |
84 |
|
83 | |||
85 | expected = 'userid is not the same as your user' |
|
84 | expected = 'userid is not the same as your user' | |
86 | assert_error(id_, expected, given=response.body) |
|
85 | assert_error(id_, expected, given=response.body) |
@@ -1,76 +1,75 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.user import UserModel |
|
22 | from rhodecode.model.user import UserModel | |
24 | from rhodecode.api.tests.utils import ( |
|
23 | from rhodecode.api.tests.utils import ( | |
25 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
24 | build_data, api_call, assert_ok, assert_error, expected_permissions) | |
26 |
|
25 | |||
27 |
|
26 | |||
28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
27 | @pytest.mark.usefixtures("testuser_api", "app") | |
29 | class TestGetUserGroups(object): |
|
28 | class TestGetUserGroups(object): | |
30 | def test_api_get_user_group(self, user_util): |
|
29 | def test_api_get_user_group(self, user_util): | |
31 | user, group = user_util.create_user_with_group() |
|
30 | user, group = user_util.create_user_with_group() | |
32 | id_, params = build_data( |
|
31 | id_, params = build_data( | |
33 | self.apikey, 'get_user_group', usergroupid=group.users_group_name) |
|
32 | self.apikey, 'get_user_group', usergroupid=group.users_group_name) | |
34 | response = api_call(self.app, params) |
|
33 | response = api_call(self.app, params) | |
35 |
|
34 | |||
36 | ret = group.get_api_data() |
|
35 | ret = group.get_api_data() | |
37 | ret['users'] = [user.get_api_data()] |
|
36 | ret['users'] = [user.get_api_data()] | |
38 |
|
37 | |||
39 | permissions = expected_permissions(group) |
|
38 | permissions = expected_permissions(group) | |
40 |
|
39 | |||
41 | ret['permissions'] = permissions |
|
40 | ret['permissions'] = permissions | |
42 | ret['permissions_summary'] = response.json['result']['permissions_summary'] |
|
41 | ret['permissions_summary'] = response.json['result']['permissions_summary'] | |
43 | expected = ret |
|
42 | expected = ret | |
44 | assert_ok(id_, expected, given=response.body) |
|
43 | assert_ok(id_, expected, given=response.body) | |
45 |
|
44 | |||
46 | def test_api_get_user_group_regular_user(self, user_util): |
|
45 | def test_api_get_user_group_regular_user(self, user_util): | |
47 | user, group = user_util.create_user_with_group() |
|
46 | user, group = user_util.create_user_with_group() | |
48 | id_, params = build_data( |
|
47 | id_, params = build_data( | |
49 | self.apikey_regular, 'get_user_group', |
|
48 | self.apikey_regular, 'get_user_group', | |
50 | usergroupid=group.users_group_name) |
|
49 | usergroupid=group.users_group_name) | |
51 | response = api_call(self.app, params) |
|
50 | response = api_call(self.app, params) | |
52 |
|
51 | |||
53 | ret = group.get_api_data() |
|
52 | ret = group.get_api_data() | |
54 | ret['users'] = [user.get_api_data()] |
|
53 | ret['users'] = [user.get_api_data()] | |
55 |
|
54 | |||
56 | permissions = expected_permissions(group) |
|
55 | permissions = expected_permissions(group) | |
57 |
|
56 | |||
58 | ret['permissions'] = permissions |
|
57 | ret['permissions'] = permissions | |
59 | ret['permissions_summary'] = response.json['result']['permissions_summary'] |
|
58 | ret['permissions_summary'] = response.json['result']['permissions_summary'] | |
60 | expected = ret |
|
59 | expected = ret | |
61 | assert_ok(id_, expected, given=response.body) |
|
60 | assert_ok(id_, expected, given=response.body) | |
62 |
|
61 | |||
63 | def test_api_get_user_group_regular_user_permission_denied( |
|
62 | def test_api_get_user_group_regular_user_permission_denied( | |
64 | self, user_util): |
|
63 | self, user_util): | |
65 | group = user_util.create_user_group() |
|
64 | group = user_util.create_user_group() | |
66 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
65 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
67 | group_name = group.users_group_name |
|
66 | group_name = group.users_group_name | |
68 | user_util.grant_user_permission_to_user_group( |
|
67 | user_util.grant_user_permission_to_user_group( | |
69 | group, user, 'usergroup.none') |
|
68 | group, user, 'usergroup.none') | |
70 |
|
69 | |||
71 | id_, params = build_data( |
|
70 | id_, params = build_data( | |
72 | self.apikey_regular, 'get_user_group', usergroupid=group_name) |
|
71 | self.apikey_regular, 'get_user_group', usergroupid=group_name) | |
73 | response = api_call(self.app, params) |
|
72 | response = api_call(self.app, params) | |
74 |
|
73 | |||
75 | expected = 'user group `%s` does not exist' % (group_name,) |
|
74 | expected = 'user group `%s` does not exist' % (group_name,) | |
76 | assert_error(id_, expected, given=response.body) |
|
75 | assert_error(id_, expected, given=response.body) |
@@ -1,71 +1,69 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import json |
|
|||
23 |
|
||||
24 | import pytest |
|
21 | import pytest | |
25 |
|
22 | |||
26 | from rhodecode.model.user import UserModel |
|
23 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.api.tests.utils import build_data, api_call |
|
24 | from rhodecode.api.tests.utils import build_data, api_call | |
|
25 | from rhodecode.lib.ext_json import json | |||
28 |
|
26 | |||
29 |
|
27 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGetUserGroups(object): |
|
29 | class TestGetUserGroups(object): | |
32 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ |
|
30 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ | |
33 | ('apikey', True), |
|
31 | ('apikey', True), | |
34 | ('apikey_regular', False), |
|
32 | ('apikey_regular', False), | |
35 | ]) |
|
33 | ]) | |
36 | def test_api_get_user_groups(self, apikey_attr, expect_secrets, user_util): |
|
34 | def test_api_get_user_groups(self, apikey_attr, expect_secrets, user_util): | |
37 | first_group = user_util.create_user_group() |
|
35 | first_group = user_util.create_user_group() | |
38 | second_group = user_util.create_user_group() |
|
36 | second_group = user_util.create_user_group() | |
39 | expected = [ |
|
37 | expected = [ | |
40 | g.get_api_data(include_secrets=expect_secrets) |
|
38 | g.get_api_data(include_secrets=expect_secrets) | |
41 | for g in (first_group, second_group)] |
|
39 | for g in (first_group, second_group)] | |
42 |
|
40 | |||
43 | apikey = getattr(self, apikey_attr) |
|
41 | apikey = getattr(self, apikey_attr) | |
44 | id_, params = build_data(apikey, 'get_user_groups', ) |
|
42 | id_, params = build_data(apikey, 'get_user_groups', ) | |
45 | response = api_call(self.app, params) |
|
43 | response = api_call(self.app, params) | |
46 | self._assert_ok(id_, expected, response) |
|
44 | self._assert_ok(id_, expected, response) | |
47 |
|
45 | |||
48 | def test_api_get_user_groups_regular_user(self, user_util): |
|
46 | def test_api_get_user_groups_regular_user(self, user_util): | |
49 | first_group = user_util.create_user_group() |
|
47 | first_group = user_util.create_user_group() | |
50 | second_group = user_util.create_user_group() |
|
48 | second_group = user_util.create_user_group() | |
51 | expected = [g.get_api_data() for g in (first_group, second_group)] |
|
49 | expected = [g.get_api_data() for g in (first_group, second_group)] | |
52 |
|
50 | |||
53 | id_, params = build_data(self.apikey_regular, 'get_user_groups', ) |
|
51 | id_, params = build_data(self.apikey_regular, 'get_user_groups', ) | |
54 | response = api_call(self.app, params) |
|
52 | response = api_call(self.app, params) | |
55 | self._assert_ok(id_, expected, response) |
|
53 | self._assert_ok(id_, expected, response) | |
56 |
|
54 | |||
57 | def test_api_get_user_groups_regular_user_no_permission(self, user_util): |
|
55 | def test_api_get_user_groups_regular_user_no_permission(self, user_util): | |
58 | group = user_util.create_user_group() |
|
56 | group = user_util.create_user_group() | |
59 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
57 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
60 | user_util.grant_user_permission_to_user_group( |
|
58 | user_util.grant_user_permission_to_user_group( | |
61 | group, user, 'usergroup.none') |
|
59 | group, user, 'usergroup.none') | |
62 | id_, params = build_data(self.apikey_regular, 'get_user_groups', ) |
|
60 | id_, params = build_data(self.apikey_regular, 'get_user_groups', ) | |
63 | response = api_call(self.app, params) |
|
61 | response = api_call(self.app, params) | |
64 | expected = [] |
|
62 | expected = [] | |
65 | self._assert_ok(id_, expected, response) |
|
63 | self._assert_ok(id_, expected, response) | |
66 |
|
64 | |||
67 | def _assert_ok(self, id_, expected_list, response): |
|
65 | def _assert_ok(self, id_, expected_list, response): | |
68 | result = json.loads(response.body) |
|
66 | result = json.loads(response.body) | |
69 | assert result['id'] == id_ |
|
67 | assert result['id'] == id_ | |
70 | assert result['error'] is None |
|
68 | assert result['error'] is None | |
71 |
assert |
|
69 | assert result['result'] == expected_list |
@@ -1,40 +1,39 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.db import User |
|
22 | from rhodecode.model.db import User | |
24 | from rhodecode.api.tests.utils import ( |
|
23 | from rhodecode.api.tests.utils import ( | |
25 | build_data, api_call, assert_ok, jsonify) |
|
24 | build_data, api_call, assert_ok, jsonify) | |
26 |
|
25 | |||
27 |
|
26 | |||
28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
27 | @pytest.mark.usefixtures("testuser_api", "app") | |
29 | class TestGetUsers(object): |
|
28 | class TestGetUsers(object): | |
30 | def test_api_get_users(self): |
|
29 | def test_api_get_users(self): | |
31 | id_, params = build_data(self.apikey, 'get_users', ) |
|
30 | id_, params = build_data(self.apikey, 'get_users', ) | |
32 | response = api_call(self.app, params) |
|
31 | response = api_call(self.app, params) | |
33 | ret_all = [] |
|
32 | ret_all = [] | |
34 | _users = User.query().filter(User.username != User.DEFAULT_USER) \ |
|
33 | _users = User.query().filter(User.username != User.DEFAULT_USER) \ | |
35 | .order_by(User.username).all() |
|
34 | .order_by(User.username).all() | |
36 | for usr in _users: |
|
35 | for usr in _users: | |
37 | ret = usr.get_api_data(include_secrets=True) |
|
36 | ret = usr.get_api_data(include_secrets=True) | |
38 | ret_all.append(jsonify(ret)) |
|
37 | ret_all.append(jsonify(ret)) | |
39 | expected = ret_all |
|
38 | expected = ret_all | |
40 | assert_ok(id_, expected, given=response.body) |
|
39 | assert_ok(id_, expected, given=response.body) |
@@ -1,90 +1,89 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestGrantUserGroupPermission(object): |
|
29 | class TestGrantUserGroupPermission(object): | |
31 | @pytest.mark.parametrize("name, perm", [ |
|
30 | @pytest.mark.parametrize("name, perm", [ | |
32 | ('none', 'repository.none'), |
|
31 | ('none', 'repository.none'), | |
33 | ('read', 'repository.read'), |
|
32 | ('read', 'repository.read'), | |
34 | ('write', 'repository.write'), |
|
33 | ('write', 'repository.write'), | |
35 | ('admin', 'repository.admin') |
|
34 | ('admin', 'repository.admin') | |
36 | ]) |
|
35 | ]) | |
37 | def test_api_grant_user_group_permission( |
|
36 | def test_api_grant_user_group_permission( | |
38 | self, name, perm, backend, user_util): |
|
37 | self, name, perm, backend, user_util): | |
39 | user_group = user_util.create_user_group() |
|
38 | user_group = user_util.create_user_group() | |
40 | id_, params = build_data( |
|
39 | id_, params = build_data( | |
41 | self.apikey, |
|
40 | self.apikey, | |
42 | 'grant_user_group_permission', |
|
41 | 'grant_user_group_permission', | |
43 | repoid=backend.repo_name, |
|
42 | repoid=backend.repo_name, | |
44 | usergroupid=user_group.users_group_name, |
|
43 | usergroupid=user_group.users_group_name, | |
45 | perm=perm) |
|
44 | perm=perm) | |
46 | response = api_call(self.app, params) |
|
45 | response = api_call(self.app, params) | |
47 |
|
46 | |||
48 | ret = { |
|
47 | ret = { | |
49 | 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % ( |
|
48 | 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % ( | |
50 | perm, user_group.users_group_name, backend.repo_name |
|
49 | perm, user_group.users_group_name, backend.repo_name | |
51 | ), |
|
50 | ), | |
52 | 'success': True |
|
51 | 'success': True | |
53 | } |
|
52 | } | |
54 | expected = ret |
|
53 | expected = ret | |
55 | assert_ok(id_, expected, given=response.body) |
|
54 | assert_ok(id_, expected, given=response.body) | |
56 |
|
55 | |||
57 | def test_api_grant_user_group_permission_wrong_permission( |
|
56 | def test_api_grant_user_group_permission_wrong_permission( | |
58 | self, backend, user_util): |
|
57 | self, backend, user_util): | |
59 | perm = 'haha.no.permission' |
|
58 | perm = 'haha.no.permission' | |
60 | user_group = user_util.create_user_group() |
|
59 | user_group = user_util.create_user_group() | |
61 | id_, params = build_data( |
|
60 | id_, params = build_data( | |
62 | self.apikey, |
|
61 | self.apikey, | |
63 | 'grant_user_group_permission', |
|
62 | 'grant_user_group_permission', | |
64 | repoid=backend.repo_name, |
|
63 | repoid=backend.repo_name, | |
65 | usergroupid=user_group.users_group_name, |
|
64 | usergroupid=user_group.users_group_name, | |
66 | perm=perm) |
|
65 | perm=perm) | |
67 | response = api_call(self.app, params) |
|
66 | response = api_call(self.app, params) | |
68 |
|
67 | |||
69 | expected = 'permission `%s` does not exist.' % (perm,) |
|
68 | expected = 'permission `%s` does not exist.' % (perm,) | |
70 | assert_error(id_, expected, given=response.body) |
|
69 | assert_error(id_, expected, given=response.body) | |
71 |
|
70 | |||
72 | @mock.patch.object(RepoModel, 'grant_user_group_permission', crash) |
|
71 | @mock.patch.object(RepoModel, 'grant_user_group_permission', crash) | |
73 | def test_api_grant_user_group_permission_exception_when_adding( |
|
72 | def test_api_grant_user_group_permission_exception_when_adding( | |
74 | self, backend, user_util): |
|
73 | self, backend, user_util): | |
75 | perm = 'repository.read' |
|
74 | perm = 'repository.read' | |
76 | user_group = user_util.create_user_group() |
|
75 | user_group = user_util.create_user_group() | |
77 | id_, params = build_data( |
|
76 | id_, params = build_data( | |
78 | self.apikey, |
|
77 | self.apikey, | |
79 | 'grant_user_group_permission', |
|
78 | 'grant_user_group_permission', | |
80 | repoid=backend.repo_name, |
|
79 | repoid=backend.repo_name, | |
81 | usergroupid=user_group.users_group_name, |
|
80 | usergroupid=user_group.users_group_name, | |
82 | perm=perm) |
|
81 | perm=perm) | |
83 | response = api_call(self.app, params) |
|
82 | response = api_call(self.app, params) | |
84 |
|
83 | |||
85 | expected = ( |
|
84 | expected = ( | |
86 | 'failed to edit permission for user group: `%s` in repo: `%s`' % ( |
|
85 | 'failed to edit permission for user group: `%s` in repo: `%s`' % ( | |
87 | user_group.users_group_name, backend.repo_name |
|
86 | user_group.users_group_name, backend.repo_name | |
88 | ) |
|
87 | ) | |
89 | ) |
|
88 | ) | |
90 | assert_error(id_, expected, given=response.body) |
|
89 | assert_error(id_, expected, given=response.body) |
@@ -1,173 +1,172 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.user import UserModel |
|
23 | from rhodecode.model.user import UserModel | |
25 | from rhodecode.model.repo_group import RepoGroupModel |
|
24 | from rhodecode.model.repo_group import RepoGroupModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok, crash) |
|
26 | build_data, api_call, assert_error, assert_ok, crash) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGrantUserGroupPermissionFromRepoGroup(object): |
|
30 | class TestGrantUserGroupPermissionFromRepoGroup(object): | |
32 | @pytest.mark.parametrize("name, perm, apply_to_children", [ |
|
31 | @pytest.mark.parametrize("name, perm, apply_to_children", [ | |
33 | ('none', 'group.none', 'none'), |
|
32 | ('none', 'group.none', 'none'), | |
34 | ('read', 'group.read', 'none'), |
|
33 | ('read', 'group.read', 'none'), | |
35 | ('write', 'group.write', 'none'), |
|
34 | ('write', 'group.write', 'none'), | |
36 | ('admin', 'group.admin', 'none'), |
|
35 | ('admin', 'group.admin', 'none'), | |
37 |
|
36 | |||
38 | ('none', 'group.none', 'all'), |
|
37 | ('none', 'group.none', 'all'), | |
39 | ('read', 'group.read', 'all'), |
|
38 | ('read', 'group.read', 'all'), | |
40 | ('write', 'group.write', 'all'), |
|
39 | ('write', 'group.write', 'all'), | |
41 | ('admin', 'group.admin', 'all'), |
|
40 | ('admin', 'group.admin', 'all'), | |
42 |
|
41 | |||
43 | ('none', 'group.none', 'repos'), |
|
42 | ('none', 'group.none', 'repos'), | |
44 | ('read', 'group.read', 'repos'), |
|
43 | ('read', 'group.read', 'repos'), | |
45 | ('write', 'group.write', 'repos'), |
|
44 | ('write', 'group.write', 'repos'), | |
46 | ('admin', 'group.admin', 'repos'), |
|
45 | ('admin', 'group.admin', 'repos'), | |
47 |
|
46 | |||
48 | ('none', 'group.none', 'groups'), |
|
47 | ('none', 'group.none', 'groups'), | |
49 | ('read', 'group.read', 'groups'), |
|
48 | ('read', 'group.read', 'groups'), | |
50 | ('write', 'group.write', 'groups'), |
|
49 | ('write', 'group.write', 'groups'), | |
51 | ('admin', 'group.admin', 'groups'), |
|
50 | ('admin', 'group.admin', 'groups'), | |
52 | ]) |
|
51 | ]) | |
53 | def test_api_grant_user_group_permission_to_repo_group( |
|
52 | def test_api_grant_user_group_permission_to_repo_group( | |
54 | self, name, perm, apply_to_children, user_util): |
|
53 | self, name, perm, apply_to_children, user_util): | |
55 | user_group = user_util.create_user_group() |
|
54 | user_group = user_util.create_user_group() | |
56 | repo_group = user_util.create_repo_group() |
|
55 | repo_group = user_util.create_repo_group() | |
57 | user_util.create_repo(parent=repo_group) |
|
56 | user_util.create_repo(parent=repo_group) | |
58 |
|
57 | |||
59 | id_, params = build_data( |
|
58 | id_, params = build_data( | |
60 | self.apikey, |
|
59 | self.apikey, | |
61 | 'grant_user_group_permission_to_repo_group', |
|
60 | 'grant_user_group_permission_to_repo_group', | |
62 | repogroupid=repo_group.name, |
|
61 | repogroupid=repo_group.name, | |
63 | usergroupid=user_group.users_group_name, |
|
62 | usergroupid=user_group.users_group_name, | |
64 | perm=perm, |
|
63 | perm=perm, | |
65 | apply_to_children=apply_to_children,) |
|
64 | apply_to_children=apply_to_children,) | |
66 | response = api_call(self.app, params) |
|
65 | response = api_call(self.app, params) | |
67 |
|
66 | |||
68 | ret = { |
|
67 | ret = { | |
69 | 'msg': ( |
|
68 | 'msg': ( | |
70 | 'Granted perm: `%s` (recursive:%s) for user group: `%s`' |
|
69 | 'Granted perm: `%s` (recursive:%s) for user group: `%s`' | |
71 | ' in repo group: `%s`' % ( |
|
70 | ' in repo group: `%s`' % ( | |
72 | perm, apply_to_children, user_group.users_group_name, |
|
71 | perm, apply_to_children, user_group.users_group_name, | |
73 | repo_group.name |
|
72 | repo_group.name | |
74 | ) |
|
73 | ) | |
75 | ), |
|
74 | ), | |
76 | 'success': True |
|
75 | 'success': True | |
77 | } |
|
76 | } | |
78 | expected = ret |
|
77 | expected = ret | |
79 | try: |
|
78 | try: | |
80 | assert_ok(id_, expected, given=response.body) |
|
79 | assert_ok(id_, expected, given=response.body) | |
81 | finally: |
|
80 | finally: | |
82 | RepoGroupModel().revoke_user_group_permission( |
|
81 | RepoGroupModel().revoke_user_group_permission( | |
83 | repo_group.group_id, user_group.users_group_id) |
|
82 | repo_group.group_id, user_group.users_group_id) | |
84 |
|
83 | |||
85 | @pytest.mark.parametrize( |
|
84 | @pytest.mark.parametrize( | |
86 | "name, perm, apply_to_children, grant_admin, access_ok", [ |
|
85 | "name, perm, apply_to_children, grant_admin, access_ok", [ | |
87 | ('none_fails', 'group.none', 'none', False, False), |
|
86 | ('none_fails', 'group.none', 'none', False, False), | |
88 | ('read_fails', 'group.read', 'none', False, False), |
|
87 | ('read_fails', 'group.read', 'none', False, False), | |
89 | ('write_fails', 'group.write', 'none', False, False), |
|
88 | ('write_fails', 'group.write', 'none', False, False), | |
90 | ('admin_fails', 'group.admin', 'none', False, False), |
|
89 | ('admin_fails', 'group.admin', 'none', False, False), | |
91 |
|
90 | |||
92 | # with granted perms |
|
91 | # with granted perms | |
93 | ('none_ok', 'group.none', 'none', True, True), |
|
92 | ('none_ok', 'group.none', 'none', True, True), | |
94 | ('read_ok', 'group.read', 'none', True, True), |
|
93 | ('read_ok', 'group.read', 'none', True, True), | |
95 | ('write_ok', 'group.write', 'none', True, True), |
|
94 | ('write_ok', 'group.write', 'none', True, True), | |
96 | ('admin_ok', 'group.admin', 'none', True, True), |
|
95 | ('admin_ok', 'group.admin', 'none', True, True), | |
97 | ] |
|
96 | ] | |
98 | ) |
|
97 | ) | |
99 | def test_api_grant_user_group_permission_to_repo_group_by_regular_user( |
|
98 | def test_api_grant_user_group_permission_to_repo_group_by_regular_user( | |
100 | self, name, perm, apply_to_children, grant_admin, access_ok, |
|
99 | self, name, perm, apply_to_children, grant_admin, access_ok, | |
101 | user_util): |
|
100 | user_util): | |
102 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
101 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
103 | user_group = user_util.create_user_group() |
|
102 | user_group = user_util.create_user_group() | |
104 | repo_group = user_util.create_repo_group() |
|
103 | repo_group = user_util.create_repo_group() | |
105 | if grant_admin: |
|
104 | if grant_admin: | |
106 | user_util.grant_user_permission_to_repo_group( |
|
105 | user_util.grant_user_permission_to_repo_group( | |
107 | repo_group, user, 'group.admin') |
|
106 | repo_group, user, 'group.admin') | |
108 |
|
107 | |||
109 | id_, params = build_data( |
|
108 | id_, params = build_data( | |
110 | self.apikey_regular, |
|
109 | self.apikey_regular, | |
111 | 'grant_user_group_permission_to_repo_group', |
|
110 | 'grant_user_group_permission_to_repo_group', | |
112 | repogroupid=repo_group.name, |
|
111 | repogroupid=repo_group.name, | |
113 | usergroupid=user_group.users_group_name, |
|
112 | usergroupid=user_group.users_group_name, | |
114 | perm=perm, |
|
113 | perm=perm, | |
115 | apply_to_children=apply_to_children,) |
|
114 | apply_to_children=apply_to_children,) | |
116 | response = api_call(self.app, params) |
|
115 | response = api_call(self.app, params) | |
117 | if access_ok: |
|
116 | if access_ok: | |
118 | ret = { |
|
117 | ret = { | |
119 | 'msg': ( |
|
118 | 'msg': ( | |
120 | 'Granted perm: `%s` (recursive:%s) for user group: `%s`' |
|
119 | 'Granted perm: `%s` (recursive:%s) for user group: `%s`' | |
121 | ' in repo group: `%s`' % ( |
|
120 | ' in repo group: `%s`' % ( | |
122 | perm, apply_to_children, user_group.users_group_name, |
|
121 | perm, apply_to_children, user_group.users_group_name, | |
123 | repo_group.name |
|
122 | repo_group.name | |
124 | ) |
|
123 | ) | |
125 | ), |
|
124 | ), | |
126 | 'success': True |
|
125 | 'success': True | |
127 | } |
|
126 | } | |
128 | expected = ret |
|
127 | expected = ret | |
129 | try: |
|
128 | try: | |
130 | assert_ok(id_, expected, given=response.body) |
|
129 | assert_ok(id_, expected, given=response.body) | |
131 | finally: |
|
130 | finally: | |
132 | RepoGroupModel().revoke_user_group_permission( |
|
131 | RepoGroupModel().revoke_user_group_permission( | |
133 | repo_group.group_id, user_group.users_group_id) |
|
132 | repo_group.group_id, user_group.users_group_id) | |
134 | else: |
|
133 | else: | |
135 | expected = 'repository group `%s` does not exist' % (repo_group.name,) |
|
134 | expected = 'repository group `%s` does not exist' % (repo_group.name,) | |
136 | assert_error(id_, expected, given=response.body) |
|
135 | assert_error(id_, expected, given=response.body) | |
137 |
|
136 | |||
138 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission( |
|
137 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission( | |
139 | self, user_util): |
|
138 | self, user_util): | |
140 | user_group = user_util.create_user_group() |
|
139 | user_group = user_util.create_user_group() | |
141 | repo_group = user_util.create_repo_group() |
|
140 | repo_group = user_util.create_repo_group() | |
142 | perm = 'haha.no.permission' |
|
141 | perm = 'haha.no.permission' | |
143 | id_, params = build_data( |
|
142 | id_, params = build_data( | |
144 | self.apikey, |
|
143 | self.apikey, | |
145 | 'grant_user_group_permission_to_repo_group', |
|
144 | 'grant_user_group_permission_to_repo_group', | |
146 | repogroupid=repo_group.name, |
|
145 | repogroupid=repo_group.name, | |
147 | usergroupid=user_group.users_group_name, |
|
146 | usergroupid=user_group.users_group_name, | |
148 | perm=perm) |
|
147 | perm=perm) | |
149 | response = api_call(self.app, params) |
|
148 | response = api_call(self.app, params) | |
150 |
|
149 | |||
151 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) |
|
150 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) | |
152 | assert_error(id_, expected, given=response.body) |
|
151 | assert_error(id_, expected, given=response.body) | |
153 |
|
152 | |||
154 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash) |
|
153 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash) | |
155 | def test_api_grant_user_group_permission_exception_when_adding_2( |
|
154 | def test_api_grant_user_group_permission_exception_when_adding_2( | |
156 | self, user_util): |
|
155 | self, user_util): | |
157 | user_group = user_util.create_user_group() |
|
156 | user_group = user_util.create_user_group() | |
158 | repo_group = user_util.create_repo_group() |
|
157 | repo_group = user_util.create_repo_group() | |
159 | perm = 'group.read' |
|
158 | perm = 'group.read' | |
160 | id_, params = build_data( |
|
159 | id_, params = build_data( | |
161 | self.apikey, |
|
160 | self.apikey, | |
162 | 'grant_user_group_permission_to_repo_group', |
|
161 | 'grant_user_group_permission_to_repo_group', | |
163 | repogroupid=repo_group.name, |
|
162 | repogroupid=repo_group.name, | |
164 | usergroupid=user_group.users_group_name, |
|
163 | usergroupid=user_group.users_group_name, | |
165 | perm=perm) |
|
164 | perm=perm) | |
166 | response = api_call(self.app, params) |
|
165 | response = api_call(self.app, params) | |
167 |
|
166 | |||
168 | expected = ( |
|
167 | expected = ( | |
169 | 'failed to edit permission for user group: `%s`' |
|
168 | 'failed to edit permission for user group: `%s`' | |
170 | ' in repo group: `%s`' % ( |
|
169 | ' in repo group: `%s`' % ( | |
171 | user_group.users_group_name, repo_group.name) |
|
170 | user_group.users_group_name, repo_group.name) | |
172 | ) |
|
171 | ) | |
173 | assert_error(id_, expected, given=response.body) |
|
172 | assert_error(id_, expected, given=response.body) |
@@ -1,97 +1,96 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.user_group import UserGroupModel |
|
22 | from rhodecode.model.user_group import UserGroupModel | |
24 | from rhodecode.api.tests.utils import ( |
|
23 | from rhodecode.api.tests.utils import ( | |
25 | build_data, api_call, assert_ok, assert_error) |
|
24 | build_data, api_call, assert_ok, assert_error) | |
26 |
|
25 | |||
27 |
|
26 | |||
28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
27 | @pytest.mark.usefixtures("testuser_api", "app") | |
29 | class TestGrantUserGroupPermissionFromUserGroup(object): |
|
28 | class TestGrantUserGroupPermissionFromUserGroup(object): | |
30 | @pytest.mark.parametrize("name, perm", [ |
|
29 | @pytest.mark.parametrize("name, perm", [ | |
31 | ('none', 'usergroup.none'), |
|
30 | ('none', 'usergroup.none'), | |
32 | ('read', 'usergroup.read'), |
|
31 | ('read', 'usergroup.read'), | |
33 | ('write', 'usergroup.write'), |
|
32 | ('write', 'usergroup.write'), | |
34 | ('admin', 'usergroup.admin'), |
|
33 | ('admin', 'usergroup.admin'), | |
35 |
|
34 | |||
36 | ('none', 'usergroup.none'), |
|
35 | ('none', 'usergroup.none'), | |
37 | ('read', 'usergroup.read'), |
|
36 | ('read', 'usergroup.read'), | |
38 | ('write', 'usergroup.write'), |
|
37 | ('write', 'usergroup.write'), | |
39 | ('admin', 'usergroup.admin'), |
|
38 | ('admin', 'usergroup.admin'), | |
40 |
|
39 | |||
41 | ('none', 'usergroup.none'), |
|
40 | ('none', 'usergroup.none'), | |
42 | ('read', 'usergroup.read'), |
|
41 | ('read', 'usergroup.read'), | |
43 | ('write', 'usergroup.write'), |
|
42 | ('write', 'usergroup.write'), | |
44 | ('admin', 'usergroup.admin'), |
|
43 | ('admin', 'usergroup.admin'), | |
45 |
|
44 | |||
46 | ('none', 'usergroup.none'), |
|
45 | ('none', 'usergroup.none'), | |
47 | ('read', 'usergroup.read'), |
|
46 | ('read', 'usergroup.read'), | |
48 | ('write', 'usergroup.write'), |
|
47 | ('write', 'usergroup.write'), | |
49 | ('admin', 'usergroup.admin'), |
|
48 | ('admin', 'usergroup.admin'), | |
50 | ]) |
|
49 | ]) | |
51 | def test_api_grant_user_group_permission_to_user_group( |
|
50 | def test_api_grant_user_group_permission_to_user_group( | |
52 | self, name, perm, user_util): |
|
51 | self, name, perm, user_util): | |
53 | group = user_util.create_user_group() |
|
52 | group = user_util.create_user_group() | |
54 | target_group = user_util.create_user_group() |
|
53 | target_group = user_util.create_user_group() | |
55 |
|
54 | |||
56 | id_, params = build_data( |
|
55 | id_, params = build_data( | |
57 | self.apikey, |
|
56 | self.apikey, | |
58 | 'grant_user_group_permission_to_user_group', |
|
57 | 'grant_user_group_permission_to_user_group', | |
59 | usergroupid=target_group.users_group_name, |
|
58 | usergroupid=target_group.users_group_name, | |
60 | sourceusergroupid=group.users_group_name, |
|
59 | sourceusergroupid=group.users_group_name, | |
61 | perm=perm) |
|
60 | perm=perm) | |
62 | response = api_call(self.app, params) |
|
61 | response = api_call(self.app, params) | |
63 |
|
62 | |||
64 | expected = { |
|
63 | expected = { | |
65 | 'msg': ( |
|
64 | 'msg': ( | |
66 | 'Granted perm: `%s` for user group: `%s`' |
|
65 | 'Granted perm: `%s` for user group: `%s`' | |
67 | ' in user group: `%s`' % ( |
|
66 | ' in user group: `%s`' % ( | |
68 | perm, group.users_group_name, |
|
67 | perm, group.users_group_name, | |
69 | target_group.users_group_name |
|
68 | target_group.users_group_name | |
70 | ) |
|
69 | ) | |
71 | ), |
|
70 | ), | |
72 | 'success': True |
|
71 | 'success': True | |
73 | } |
|
72 | } | |
74 | try: |
|
73 | try: | |
75 | assert_ok(id_, expected, given=response.body) |
|
74 | assert_ok(id_, expected, given=response.body) | |
76 | finally: |
|
75 | finally: | |
77 | UserGroupModel().revoke_user_group_permission( |
|
76 | UserGroupModel().revoke_user_group_permission( | |
78 | target_group.users_group_id, group.users_group_id) |
|
77 | target_group.users_group_id, group.users_group_id) | |
79 |
|
78 | |||
80 | def test_api_grant_user_group_permission_to_user_group_same_failure( |
|
79 | def test_api_grant_user_group_permission_to_user_group_same_failure( | |
81 | self, user_util): |
|
80 | self, user_util): | |
82 | group = user_util.create_user_group() |
|
81 | group = user_util.create_user_group() | |
83 |
|
82 | |||
84 | id_, params = build_data( |
|
83 | id_, params = build_data( | |
85 | self.apikey, |
|
84 | self.apikey, | |
86 | 'grant_user_group_permission_to_user_group', |
|
85 | 'grant_user_group_permission_to_user_group', | |
87 | usergroupid=group.users_group_name, |
|
86 | usergroupid=group.users_group_name, | |
88 | sourceusergroupid=group.users_group_name, |
|
87 | sourceusergroupid=group.users_group_name, | |
89 | perm='usergroup.none') |
|
88 | perm='usergroup.none') | |
90 | response = api_call(self.app, params) |
|
89 | response = api_call(self.app, params) | |
91 |
|
90 | |||
92 | expected = ( |
|
91 | expected = ( | |
93 | 'failed to edit permission for user group: `%s`' |
|
92 | 'failed to edit permission for user group: `%s`' | |
94 | ' in user group: `%s`' % ( |
|
93 | ' in user group: `%s`' % ( | |
95 | group.users_group_name, group.users_group_name) |
|
94 | group.users_group_name, group.users_group_name) | |
96 | ) |
|
95 | ) | |
97 | assert_error(id_, expected, given=response.body) |
|
96 | assert_error(id_, expected, given=response.body) |
@@ -1,87 +1,86 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestGrantUserPermission(object): |
|
29 | class TestGrantUserPermission(object): | |
31 | @pytest.mark.parametrize("name, perm", [ |
|
30 | @pytest.mark.parametrize("name, perm", [ | |
32 | ('none', 'repository.none'), |
|
31 | ('none', 'repository.none'), | |
33 | ('read', 'repository.read'), |
|
32 | ('read', 'repository.read'), | |
34 | ('write', 'repository.write'), |
|
33 | ('write', 'repository.write'), | |
35 | ('admin', 'repository.admin') |
|
34 | ('admin', 'repository.admin') | |
36 | ]) |
|
35 | ]) | |
37 | def test_api_grant_user_permission(self, name, perm, backend, user_util): |
|
36 | def test_api_grant_user_permission(self, name, perm, backend, user_util): | |
38 | user = user_util.create_user() |
|
37 | user = user_util.create_user() | |
39 | id_, params = build_data( |
|
38 | id_, params = build_data( | |
40 | self.apikey, |
|
39 | self.apikey, | |
41 | 'grant_user_permission', |
|
40 | 'grant_user_permission', | |
42 | repoid=backend.repo_name, |
|
41 | repoid=backend.repo_name, | |
43 | userid=user.username, |
|
42 | userid=user.username, | |
44 | perm=perm) |
|
43 | perm=perm) | |
45 | response = api_call(self.app, params) |
|
44 | response = api_call(self.app, params) | |
46 |
|
45 | |||
47 | ret = { |
|
46 | ret = { | |
48 | 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % ( |
|
47 | 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % ( | |
49 | perm, user.username, backend.repo_name |
|
48 | perm, user.username, backend.repo_name | |
50 | ), |
|
49 | ), | |
51 | 'success': True |
|
50 | 'success': True | |
52 | } |
|
51 | } | |
53 | expected = ret |
|
52 | expected = ret | |
54 | assert_ok(id_, expected, given=response.body) |
|
53 | assert_ok(id_, expected, given=response.body) | |
55 |
|
54 | |||
56 | def test_api_grant_user_permission_wrong_permission( |
|
55 | def test_api_grant_user_permission_wrong_permission( | |
57 | self, backend, user_util): |
|
56 | self, backend, user_util): | |
58 | user = user_util.create_user() |
|
57 | user = user_util.create_user() | |
59 | perm = 'haha.no.permission' |
|
58 | perm = 'haha.no.permission' | |
60 | id_, params = build_data( |
|
59 | id_, params = build_data( | |
61 | self.apikey, |
|
60 | self.apikey, | |
62 | 'grant_user_permission', |
|
61 | 'grant_user_permission', | |
63 | repoid=backend.repo_name, |
|
62 | repoid=backend.repo_name, | |
64 | userid=user.username, |
|
63 | userid=user.username, | |
65 | perm=perm) |
|
64 | perm=perm) | |
66 | response = api_call(self.app, params) |
|
65 | response = api_call(self.app, params) | |
67 |
|
66 | |||
68 | expected = 'permission `%s` does not exist.' % (perm,) |
|
67 | expected = 'permission `%s` does not exist.' % (perm,) | |
69 | assert_error(id_, expected, given=response.body) |
|
68 | assert_error(id_, expected, given=response.body) | |
70 |
|
69 | |||
71 | @mock.patch.object(RepoModel, 'grant_user_permission', crash) |
|
70 | @mock.patch.object(RepoModel, 'grant_user_permission', crash) | |
72 | def test_api_grant_user_permission_exception_when_adding( |
|
71 | def test_api_grant_user_permission_exception_when_adding( | |
73 | self, backend, user_util): |
|
72 | self, backend, user_util): | |
74 | user = user_util.create_user() |
|
73 | user = user_util.create_user() | |
75 | perm = 'repository.read' |
|
74 | perm = 'repository.read' | |
76 | id_, params = build_data( |
|
75 | id_, params = build_data( | |
77 | self.apikey, |
|
76 | self.apikey, | |
78 | 'grant_user_permission', |
|
77 | 'grant_user_permission', | |
79 | repoid=backend.repo_name, |
|
78 | repoid=backend.repo_name, | |
80 | userid=user.username, |
|
79 | userid=user.username, | |
81 | perm=perm) |
|
80 | perm=perm) | |
82 | response = api_call(self.app, params) |
|
81 | response = api_call(self.app, params) | |
83 |
|
82 | |||
84 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
|
83 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( | |
85 | user.username, backend.repo_name |
|
84 | user.username, backend.repo_name | |
86 | ) |
|
85 | ) | |
87 | assert_error(id_, expected, given=response.body) |
|
86 | assert_error(id_, expected, given=response.body) |
@@ -1,157 +1,156 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.user import UserModel |
|
23 | from rhodecode.model.user import UserModel | |
25 | from rhodecode.model.repo_group import RepoGroupModel |
|
24 | from rhodecode.model.repo_group import RepoGroupModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok, crash) |
|
26 | build_data, api_call, assert_error, assert_ok, crash) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGrantUserPermissionFromRepoGroup(object): |
|
30 | class TestGrantUserPermissionFromRepoGroup(object): | |
32 | @pytest.mark.parametrize("name, perm, apply_to_children", [ |
|
31 | @pytest.mark.parametrize("name, perm, apply_to_children", [ | |
33 | ('none', 'group.none', 'none'), |
|
32 | ('none', 'group.none', 'none'), | |
34 | ('read', 'group.read', 'none'), |
|
33 | ('read', 'group.read', 'none'), | |
35 | ('write', 'group.write', 'none'), |
|
34 | ('write', 'group.write', 'none'), | |
36 | ('admin', 'group.admin', 'none'), |
|
35 | ('admin', 'group.admin', 'none'), | |
37 |
|
36 | |||
38 | ('none', 'group.none', 'all'), |
|
37 | ('none', 'group.none', 'all'), | |
39 | ('read', 'group.read', 'all'), |
|
38 | ('read', 'group.read', 'all'), | |
40 | ('write', 'group.write', 'all'), |
|
39 | ('write', 'group.write', 'all'), | |
41 | ('admin', 'group.admin', 'all'), |
|
40 | ('admin', 'group.admin', 'all'), | |
42 |
|
41 | |||
43 | ('none', 'group.none', 'repos'), |
|
42 | ('none', 'group.none', 'repos'), | |
44 | ('read', 'group.read', 'repos'), |
|
43 | ('read', 'group.read', 'repos'), | |
45 | ('write', 'group.write', 'repos'), |
|
44 | ('write', 'group.write', 'repos'), | |
46 | ('admin', 'group.admin', 'repos'), |
|
45 | ('admin', 'group.admin', 'repos'), | |
47 |
|
46 | |||
48 | ('none', 'group.none', 'groups'), |
|
47 | ('none', 'group.none', 'groups'), | |
49 | ('read', 'group.read', 'groups'), |
|
48 | ('read', 'group.read', 'groups'), | |
50 | ('write', 'group.write', 'groups'), |
|
49 | ('write', 'group.write', 'groups'), | |
51 | ('admin', 'group.admin', 'groups'), |
|
50 | ('admin', 'group.admin', 'groups'), | |
52 | ]) |
|
51 | ]) | |
53 | def test_api_grant_user_permission_to_repo_group( |
|
52 | def test_api_grant_user_permission_to_repo_group( | |
54 | self, name, perm, apply_to_children, user_util): |
|
53 | self, name, perm, apply_to_children, user_util): | |
55 | user = user_util.create_user() |
|
54 | user = user_util.create_user() | |
56 | repo_group = user_util.create_repo_group() |
|
55 | repo_group = user_util.create_repo_group() | |
57 | id_, params = build_data( |
|
56 | id_, params = build_data( | |
58 | self.apikey, 'grant_user_permission_to_repo_group', |
|
57 | self.apikey, 'grant_user_permission_to_repo_group', | |
59 | repogroupid=repo_group.name, userid=user.username, |
|
58 | repogroupid=repo_group.name, userid=user.username, | |
60 | perm=perm, apply_to_children=apply_to_children) |
|
59 | perm=perm, apply_to_children=apply_to_children) | |
61 | response = api_call(self.app, params) |
|
60 | response = api_call(self.app, params) | |
62 |
|
61 | |||
63 | ret = { |
|
62 | ret = { | |
64 | 'msg': ( |
|
63 | 'msg': ( | |
65 | 'Granted perm: `%s` (recursive:%s) for user: `%s`' |
|
64 | 'Granted perm: `%s` (recursive:%s) for user: `%s`' | |
66 | ' in repo group: `%s`' % ( |
|
65 | ' in repo group: `%s`' % ( | |
67 | perm, apply_to_children, user.username, repo_group.name |
|
66 | perm, apply_to_children, user.username, repo_group.name | |
68 | ) |
|
67 | ) | |
69 | ), |
|
68 | ), | |
70 | 'success': True |
|
69 | 'success': True | |
71 | } |
|
70 | } | |
72 | expected = ret |
|
71 | expected = ret | |
73 | assert_ok(id_, expected, given=response.body) |
|
72 | assert_ok(id_, expected, given=response.body) | |
74 |
|
73 | |||
75 | @pytest.mark.parametrize( |
|
74 | @pytest.mark.parametrize( | |
76 | "name, perm, apply_to_children, grant_admin, access_ok", [ |
|
75 | "name, perm, apply_to_children, grant_admin, access_ok", [ | |
77 | ('none_fails', 'group.none', 'none', False, False), |
|
76 | ('none_fails', 'group.none', 'none', False, False), | |
78 | ('read_fails', 'group.read', 'none', False, False), |
|
77 | ('read_fails', 'group.read', 'none', False, False), | |
79 | ('write_fails', 'group.write', 'none', False, False), |
|
78 | ('write_fails', 'group.write', 'none', False, False), | |
80 | ('admin_fails', 'group.admin', 'none', False, False), |
|
79 | ('admin_fails', 'group.admin', 'none', False, False), | |
81 |
|
80 | |||
82 | # with granted perms |
|
81 | # with granted perms | |
83 | ('none_ok', 'group.none', 'none', True, True), |
|
82 | ('none_ok', 'group.none', 'none', True, True), | |
84 | ('read_ok', 'group.read', 'none', True, True), |
|
83 | ('read_ok', 'group.read', 'none', True, True), | |
85 | ('write_ok', 'group.write', 'none', True, True), |
|
84 | ('write_ok', 'group.write', 'none', True, True), | |
86 | ('admin_ok', 'group.admin', 'none', True, True), |
|
85 | ('admin_ok', 'group.admin', 'none', True, True), | |
87 | ] |
|
86 | ] | |
88 | ) |
|
87 | ) | |
89 | def test_api_grant_user_permission_to_repo_group_by_regular_user( |
|
88 | def test_api_grant_user_permission_to_repo_group_by_regular_user( | |
90 | self, name, perm, apply_to_children, grant_admin, access_ok, |
|
89 | self, name, perm, apply_to_children, grant_admin, access_ok, | |
91 | user_util): |
|
90 | user_util): | |
92 | user = user_util.create_user() |
|
91 | user = user_util.create_user() | |
93 | repo_group = user_util.create_repo_group() |
|
92 | repo_group = user_util.create_repo_group() | |
94 |
|
93 | |||
95 | if grant_admin: |
|
94 | if grant_admin: | |
96 | test_user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
95 | test_user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
97 | user_util.grant_user_permission_to_repo_group( |
|
96 | user_util.grant_user_permission_to_repo_group( | |
98 | repo_group, test_user, 'group.admin') |
|
97 | repo_group, test_user, 'group.admin') | |
99 |
|
98 | |||
100 | id_, params = build_data( |
|
99 | id_, params = build_data( | |
101 | self.apikey_regular, 'grant_user_permission_to_repo_group', |
|
100 | self.apikey_regular, 'grant_user_permission_to_repo_group', | |
102 | repogroupid=repo_group.name, userid=user.username, |
|
101 | repogroupid=repo_group.name, userid=user.username, | |
103 | perm=perm, apply_to_children=apply_to_children) |
|
102 | perm=perm, apply_to_children=apply_to_children) | |
104 | response = api_call(self.app, params) |
|
103 | response = api_call(self.app, params) | |
105 | if access_ok: |
|
104 | if access_ok: | |
106 | ret = { |
|
105 | ret = { | |
107 | 'msg': ( |
|
106 | 'msg': ( | |
108 | 'Granted perm: `%s` (recursive:%s) for user: `%s`' |
|
107 | 'Granted perm: `%s` (recursive:%s) for user: `%s`' | |
109 | ' in repo group: `%s`' % ( |
|
108 | ' in repo group: `%s`' % ( | |
110 | perm, apply_to_children, user.username, repo_group.name |
|
109 | perm, apply_to_children, user.username, repo_group.name | |
111 | ) |
|
110 | ) | |
112 | ), |
|
111 | ), | |
113 | 'success': True |
|
112 | 'success': True | |
114 | } |
|
113 | } | |
115 | expected = ret |
|
114 | expected = ret | |
116 | assert_ok(id_, expected, given=response.body) |
|
115 | assert_ok(id_, expected, given=response.body) | |
117 | else: |
|
116 | else: | |
118 | expected = 'repository group `%s` does not exist' % ( |
|
117 | expected = 'repository group `%s` does not exist' % ( | |
119 | repo_group.name, ) |
|
118 | repo_group.name, ) | |
120 | assert_error(id_, expected, given=response.body) |
|
119 | assert_error(id_, expected, given=response.body) | |
121 |
|
120 | |||
122 | def test_api_grant_user_permission_to_repo_group_wrong_permission( |
|
121 | def test_api_grant_user_permission_to_repo_group_wrong_permission( | |
123 | self, user_util): |
|
122 | self, user_util): | |
124 | user = user_util.create_user() |
|
123 | user = user_util.create_user() | |
125 | repo_group = user_util.create_repo_group() |
|
124 | repo_group = user_util.create_repo_group() | |
126 | perm = 'haha.no.permission' |
|
125 | perm = 'haha.no.permission' | |
127 | id_, params = build_data( |
|
126 | id_, params = build_data( | |
128 | self.apikey, |
|
127 | self.apikey, | |
129 | 'grant_user_permission_to_repo_group', |
|
128 | 'grant_user_permission_to_repo_group', | |
130 | repogroupid=repo_group.name, |
|
129 | repogroupid=repo_group.name, | |
131 | userid=user.username, |
|
130 | userid=user.username, | |
132 | perm=perm) |
|
131 | perm=perm) | |
133 | response = api_call(self.app, params) |
|
132 | response = api_call(self.app, params) | |
134 |
|
133 | |||
135 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) |
|
134 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) | |
136 | assert_error(id_, expected, given=response.body) |
|
135 | assert_error(id_, expected, given=response.body) | |
137 |
|
136 | |||
138 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash) |
|
137 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash) | |
139 | def test_api_grant_user_permission_to_repo_group_exception_when_adding( |
|
138 | def test_api_grant_user_permission_to_repo_group_exception_when_adding( | |
140 | self, user_util): |
|
139 | self, user_util): | |
141 | user = user_util.create_user() |
|
140 | user = user_util.create_user() | |
142 | repo_group = user_util.create_repo_group() |
|
141 | repo_group = user_util.create_repo_group() | |
143 | perm = 'group.read' |
|
142 | perm = 'group.read' | |
144 | id_, params = build_data( |
|
143 | id_, params = build_data( | |
145 | self.apikey, |
|
144 | self.apikey, | |
146 | 'grant_user_permission_to_repo_group', |
|
145 | 'grant_user_permission_to_repo_group', | |
147 | repogroupid=repo_group.name, |
|
146 | repogroupid=repo_group.name, | |
148 | userid=user.username, |
|
147 | userid=user.username, | |
149 | perm=perm) |
|
148 | perm=perm) | |
150 | response = api_call(self.app, params) |
|
149 | response = api_call(self.app, params) | |
151 |
|
150 | |||
152 | expected = ( |
|
151 | expected = ( | |
153 | 'failed to edit permission for user: `%s` in repo group: `%s`' % ( |
|
152 | 'failed to edit permission for user: `%s` in repo group: `%s`' % ( | |
154 | user.username, repo_group.name |
|
153 | user.username, repo_group.name | |
155 | ) |
|
154 | ) | |
156 | ) |
|
155 | ) | |
157 | assert_error(id_, expected, given=response.body) |
|
156 | assert_error(id_, expected, given=response.body) |
@@ -1,156 +1,155 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.user import UserModel |
|
23 | from rhodecode.model.user import UserModel | |
25 | from rhodecode.model.user_group import UserGroupModel |
|
24 | from rhodecode.model.user_group import UserGroupModel | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok, crash) |
|
26 | build_data, api_call, assert_error, assert_ok, crash) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestGrantUserPermissionFromUserGroup(object): |
|
30 | class TestGrantUserPermissionFromUserGroup(object): | |
32 | @pytest.mark.parametrize("name, perm", [ |
|
31 | @pytest.mark.parametrize("name, perm", [ | |
33 | ('none', 'usergroup.none'), |
|
32 | ('none', 'usergroup.none'), | |
34 | ('read', 'usergroup.read'), |
|
33 | ('read', 'usergroup.read'), | |
35 | ('write', 'usergroup.write'), |
|
34 | ('write', 'usergroup.write'), | |
36 | ('admin', 'usergroup.admin'), |
|
35 | ('admin', 'usergroup.admin'), | |
37 |
|
36 | |||
38 | ('none', 'usergroup.none'), |
|
37 | ('none', 'usergroup.none'), | |
39 | ('read', 'usergroup.read'), |
|
38 | ('read', 'usergroup.read'), | |
40 | ('write', 'usergroup.write'), |
|
39 | ('write', 'usergroup.write'), | |
41 | ('admin', 'usergroup.admin'), |
|
40 | ('admin', 'usergroup.admin'), | |
42 |
|
41 | |||
43 | ('none', 'usergroup.none'), |
|
42 | ('none', 'usergroup.none'), | |
44 | ('read', 'usergroup.read'), |
|
43 | ('read', 'usergroup.read'), | |
45 | ('write', 'usergroup.write'), |
|
44 | ('write', 'usergroup.write'), | |
46 | ('admin', 'usergroup.admin'), |
|
45 | ('admin', 'usergroup.admin'), | |
47 |
|
46 | |||
48 | ('none', 'usergroup.none'), |
|
47 | ('none', 'usergroup.none'), | |
49 | ('read', 'usergroup.read'), |
|
48 | ('read', 'usergroup.read'), | |
50 | ('write', 'usergroup.write'), |
|
49 | ('write', 'usergroup.write'), | |
51 | ('admin', 'usergroup.admin'), |
|
50 | ('admin', 'usergroup.admin'), | |
52 | ]) |
|
51 | ]) | |
53 | def test_api_grant_user_permission_to_user_group( |
|
52 | def test_api_grant_user_permission_to_user_group( | |
54 | self, name, perm, user_util): |
|
53 | self, name, perm, user_util): | |
55 | user = user_util.create_user() |
|
54 | user = user_util.create_user() | |
56 | group = user_util.create_user_group() |
|
55 | group = user_util.create_user_group() | |
57 | id_, params = build_data( |
|
56 | id_, params = build_data( | |
58 | self.apikey, |
|
57 | self.apikey, | |
59 | 'grant_user_permission_to_user_group', |
|
58 | 'grant_user_permission_to_user_group', | |
60 | usergroupid=group.users_group_name, |
|
59 | usergroupid=group.users_group_name, | |
61 | userid=user.username, |
|
60 | userid=user.username, | |
62 | perm=perm) |
|
61 | perm=perm) | |
63 | response = api_call(self.app, params) |
|
62 | response = api_call(self.app, params) | |
64 |
|
63 | |||
65 | ret = { |
|
64 | ret = { | |
66 | 'msg': 'Granted perm: `%s` for user: `%s` in user group: `%s`' % ( |
|
65 | 'msg': 'Granted perm: `%s` for user: `%s` in user group: `%s`' % ( | |
67 | perm, user.username, group.users_group_name |
|
66 | perm, user.username, group.users_group_name | |
68 | ), |
|
67 | ), | |
69 | 'success': True |
|
68 | 'success': True | |
70 | } |
|
69 | } | |
71 | expected = ret |
|
70 | expected = ret | |
72 | assert_ok(id_, expected, given=response.body) |
|
71 | assert_ok(id_, expected, given=response.body) | |
73 |
|
72 | |||
74 | @pytest.mark.parametrize("name, perm, grant_admin, access_ok", [ |
|
73 | @pytest.mark.parametrize("name, perm, grant_admin, access_ok", [ | |
75 | ('none_fails', 'usergroup.none', False, False), |
|
74 | ('none_fails', 'usergroup.none', False, False), | |
76 | ('read_fails', 'usergroup.read', False, False), |
|
75 | ('read_fails', 'usergroup.read', False, False), | |
77 | ('write_fails', 'usergroup.write', False, False), |
|
76 | ('write_fails', 'usergroup.write', False, False), | |
78 | ('admin_fails', 'usergroup.admin', False, False), |
|
77 | ('admin_fails', 'usergroup.admin', False, False), | |
79 |
|
78 | |||
80 | # with granted perms |
|
79 | # with granted perms | |
81 | ('none_ok', 'usergroup.none', True, True), |
|
80 | ('none_ok', 'usergroup.none', True, True), | |
82 | ('read_ok', 'usergroup.read', True, True), |
|
81 | ('read_ok', 'usergroup.read', True, True), | |
83 | ('write_ok', 'usergroup.write', True, True), |
|
82 | ('write_ok', 'usergroup.write', True, True), | |
84 | ('admin_ok', 'usergroup.admin', True, True), |
|
83 | ('admin_ok', 'usergroup.admin', True, True), | |
85 | ]) |
|
84 | ]) | |
86 | def test_api_grant_user_permission_to_user_group_by_regular_user( |
|
85 | def test_api_grant_user_permission_to_user_group_by_regular_user( | |
87 | self, name, perm, grant_admin, access_ok, user_util): |
|
86 | self, name, perm, grant_admin, access_ok, user_util): | |
88 | api_user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
87 | api_user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
89 | user = user_util.create_user() |
|
88 | user = user_util.create_user() | |
90 | group = user_util.create_user_group() |
|
89 | group = user_util.create_user_group() | |
91 | # grant the user ability to at least read the group |
|
90 | # grant the user ability to at least read the group | |
92 | permission = 'usergroup.admin' if grant_admin else 'usergroup.read' |
|
91 | permission = 'usergroup.admin' if grant_admin else 'usergroup.read' | |
93 | user_util.grant_user_permission_to_user_group( |
|
92 | user_util.grant_user_permission_to_user_group( | |
94 | group, api_user, permission) |
|
93 | group, api_user, permission) | |
95 |
|
94 | |||
96 | id_, params = build_data( |
|
95 | id_, params = build_data( | |
97 | self.apikey_regular, |
|
96 | self.apikey_regular, | |
98 | 'grant_user_permission_to_user_group', |
|
97 | 'grant_user_permission_to_user_group', | |
99 | usergroupid=group.users_group_name, |
|
98 | usergroupid=group.users_group_name, | |
100 | userid=user.username, |
|
99 | userid=user.username, | |
101 | perm=perm) |
|
100 | perm=perm) | |
102 | response = api_call(self.app, params) |
|
101 | response = api_call(self.app, params) | |
103 |
|
102 | |||
104 | if access_ok: |
|
103 | if access_ok: | |
105 | ret = { |
|
104 | ret = { | |
106 | 'msg': ( |
|
105 | 'msg': ( | |
107 | 'Granted perm: `%s` for user: `%s` in user group: `%s`' % ( |
|
106 | 'Granted perm: `%s` for user: `%s` in user group: `%s`' % ( | |
108 | perm, user.username, group.users_group_name |
|
107 | perm, user.username, group.users_group_name | |
109 | ) |
|
108 | ) | |
110 | ), |
|
109 | ), | |
111 | 'success': True |
|
110 | 'success': True | |
112 | } |
|
111 | } | |
113 | expected = ret |
|
112 | expected = ret | |
114 | assert_ok(id_, expected, given=response.body) |
|
113 | assert_ok(id_, expected, given=response.body) | |
115 | else: |
|
114 | else: | |
116 | expected = 'user group `%s` does not exist' % ( |
|
115 | expected = 'user group `%s` does not exist' % ( | |
117 | group.users_group_name) |
|
116 | group.users_group_name) | |
118 | assert_error(id_, expected, given=response.body) |
|
117 | assert_error(id_, expected, given=response.body) | |
119 |
|
118 | |||
120 | def test_api_grant_user_permission_to_user_group_wrong_permission( |
|
119 | def test_api_grant_user_permission_to_user_group_wrong_permission( | |
121 | self, user_util): |
|
120 | self, user_util): | |
122 | user = user_util.create_user() |
|
121 | user = user_util.create_user() | |
123 | group = user_util.create_user_group() |
|
122 | group = user_util.create_user_group() | |
124 | perm = 'haha.no.permission' |
|
123 | perm = 'haha.no.permission' | |
125 | id_, params = build_data( |
|
124 | id_, params = build_data( | |
126 | self.apikey, |
|
125 | self.apikey, | |
127 | 'grant_user_permission_to_user_group', |
|
126 | 'grant_user_permission_to_user_group', | |
128 | usergroupid=group.users_group_name, |
|
127 | usergroupid=group.users_group_name, | |
129 | userid=user.username, |
|
128 | userid=user.username, | |
130 | perm=perm) |
|
129 | perm=perm) | |
131 | response = api_call(self.app, params) |
|
130 | response = api_call(self.app, params) | |
132 |
|
131 | |||
133 | expected = 'permission `%s` does not exist. Permission should start with prefix: `usergroup.`' % perm |
|
132 | expected = 'permission `%s` does not exist. Permission should start with prefix: `usergroup.`' % perm | |
134 | assert_error(id_, expected, given=response.body) |
|
133 | assert_error(id_, expected, given=response.body) | |
135 |
|
134 | |||
136 | def test_api_grant_user_permission_to_user_group_exception_when_adding( |
|
135 | def test_api_grant_user_permission_to_user_group_exception_when_adding( | |
137 | self, user_util): |
|
136 | self, user_util): | |
138 | user = user_util.create_user() |
|
137 | user = user_util.create_user() | |
139 | group = user_util.create_user_group() |
|
138 | group = user_util.create_user_group() | |
140 |
|
139 | |||
141 | perm = 'usergroup.read' |
|
140 | perm = 'usergroup.read' | |
142 | id_, params = build_data( |
|
141 | id_, params = build_data( | |
143 | self.apikey, |
|
142 | self.apikey, | |
144 | 'grant_user_permission_to_user_group', |
|
143 | 'grant_user_permission_to_user_group', | |
145 | usergroupid=group.users_group_name, |
|
144 | usergroupid=group.users_group_name, | |
146 | userid=user.username, |
|
145 | userid=user.username, | |
147 | perm=perm) |
|
146 | perm=perm) | |
148 | with mock.patch.object(UserGroupModel, 'grant_user_permission', crash): |
|
147 | with mock.patch.object(UserGroupModel, 'grant_user_permission', crash): | |
149 | response = api_call(self.app, params) |
|
148 | response = api_call(self.app, params) | |
150 |
|
149 | |||
151 | expected = ( |
|
150 | expected = ( | |
152 | 'failed to edit permission for user: `%s` in user group: `%s`' % ( |
|
151 | 'failed to edit permission for user: `%s` in user group: `%s`' % ( | |
153 | user.username, group.users_group_name |
|
152 | user.username, group.users_group_name | |
154 | ) |
|
153 | ) | |
155 | ) |
|
154 | ) | |
156 | assert_error(id_, expected, given=response.body) |
|
155 | assert_error(id_, expected, given=response.body) |
@@ -1,68 +1,67 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.scm import ScmModel |
|
23 | from rhodecode.model.scm import ScmModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_ok, assert_error, crash) |
|
25 | build_data, api_call, assert_ok, assert_error, crash) | |
27 | from rhodecode.model.repo import RepoModel |
|
26 | from rhodecode.model.repo import RepoModel | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestInvalidateCache(object): |
|
30 | class TestInvalidateCache(object): | |
32 |
|
31 | |||
33 | def _set_cache(self, repo_name): |
|
32 | def _set_cache(self, repo_name): | |
34 | repo = RepoModel().get_by_repo_name(repo_name) |
|
33 | repo = RepoModel().get_by_repo_name(repo_name) | |
35 | repo.scm_instance(cache=True) |
|
34 | repo.scm_instance(cache=True) | |
36 |
|
35 | |||
37 | def test_api_invalidate_cache(self, backend): |
|
36 | def test_api_invalidate_cache(self, backend): | |
38 | self._set_cache(backend.repo_name) |
|
37 | self._set_cache(backend.repo_name) | |
39 |
|
38 | |||
40 | id_, params = build_data( |
|
39 | id_, params = build_data( | |
41 | self.apikey, 'invalidate_cache', repoid=backend.repo_name) |
|
40 | self.apikey, 'invalidate_cache', repoid=backend.repo_name) | |
42 | response = api_call(self.app, params) |
|
41 | response = api_call(self.app, params) | |
43 |
|
42 | |||
44 | expected = { |
|
43 | expected = { | |
45 | 'msg': "Cache for repository `%s` was invalidated" % ( |
|
44 | 'msg': "Cache for repository `%s` was invalidated" % ( | |
46 | backend.repo_name,), |
|
45 | backend.repo_name,), | |
47 | 'repository': backend.repo_name, |
|
46 | 'repository': backend.repo_name, | |
48 | } |
|
47 | } | |
49 | assert_ok(id_, expected, given=response.body) |
|
48 | assert_ok(id_, expected, given=response.body) | |
50 |
|
49 | |||
51 | @mock.patch.object(ScmModel, 'mark_for_invalidation', crash) |
|
50 | @mock.patch.object(ScmModel, 'mark_for_invalidation', crash) | |
52 | def test_api_invalidate_cache_error(self, backend): |
|
51 | def test_api_invalidate_cache_error(self, backend): | |
53 | id_, params = build_data( |
|
52 | id_, params = build_data( | |
54 | self.apikey, 'invalidate_cache', repoid=backend.repo_name) |
|
53 | self.apikey, 'invalidate_cache', repoid=backend.repo_name) | |
55 | response = api_call(self.app, params) |
|
54 | response = api_call(self.app, params) | |
56 |
|
55 | |||
57 | expected = 'Error occurred during cache invalidation action' |
|
56 | expected = 'Error occurred during cache invalidation action' | |
58 | assert_error(id_, expected, given=response.body) |
|
57 | assert_error(id_, expected, given=response.body) | |
59 |
|
58 | |||
60 | def test_api_invalidate_cache_regular_user_no_permission(self, backend): |
|
59 | def test_api_invalidate_cache_regular_user_no_permission(self, backend): | |
61 | self._set_cache(backend.repo_name) |
|
60 | self._set_cache(backend.repo_name) | |
62 |
|
61 | |||
63 | id_, params = build_data( |
|
62 | id_, params = build_data( | |
64 | self.apikey_regular, 'invalidate_cache', repoid=backend.repo_name) |
|
63 | self.apikey_regular, 'invalidate_cache', repoid=backend.repo_name) | |
65 | response = api_call(self.app, params) |
|
64 | response = api_call(self.app, params) | |
66 |
|
65 | |||
67 | expected = "repository `%s` does not exist" % (backend.repo_name,) |
|
66 | expected = "repository `%s` does not exist" % (backend.repo_name,) | |
68 | assert_error(id_, expected, given=response.body) |
|
67 | assert_error(id_, expected, given=response.body) |
@@ -1,259 +1,258 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.db import UserLog, PullRequest |
|
22 | from rhodecode.model.db import UserLog, PullRequest | |
24 | from rhodecode.model.meta import Session |
|
23 | from rhodecode.model.meta import Session | |
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok) |
|
26 | build_data, api_call, assert_error, assert_ok) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestMergePullRequest(object): |
|
30 | class TestMergePullRequest(object): | |
32 |
|
31 | |||
33 | @pytest.mark.backends("git", "hg") |
|
32 | @pytest.mark.backends("git", "hg") | |
34 | def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications): |
|
33 | def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications): | |
35 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
34 | pull_request = pr_util.create_pull_request(mergeable=True) | |
36 | pull_request_id = pull_request.pull_request_id |
|
35 | pull_request_id = pull_request.pull_request_id | |
37 | pull_request_repo = pull_request.target_repo.repo_name |
|
36 | pull_request_repo = pull_request.target_repo.repo_name | |
38 |
|
37 | |||
39 | id_, params = build_data( |
|
38 | id_, params = build_data( | |
40 | self.apikey, 'merge_pull_request', |
|
39 | self.apikey, 'merge_pull_request', | |
41 | repoid=pull_request_repo, |
|
40 | repoid=pull_request_repo, | |
42 | pullrequestid=pull_request_id) |
|
41 | pullrequestid=pull_request_id) | |
43 |
|
42 | |||
44 | response = api_call(self.app, params) |
|
43 | response = api_call(self.app, params) | |
45 |
|
44 | |||
46 | # The above api call detaches the pull request DB object from the |
|
45 | # The above api call detaches the pull request DB object from the | |
47 | # session because of an unconditional transaction rollback in our |
|
46 | # session because of an unconditional transaction rollback in our | |
48 | # middleware. Therefore we need to add it back here if we want to use it. |
|
47 | # middleware. Therefore we need to add it back here if we want to use it. | |
49 | Session().add(pull_request) |
|
48 | Session().add(pull_request) | |
50 |
|
49 | |||
51 | expected = 'merge not possible for following reasons: ' \ |
|
50 | expected = 'merge not possible for following reasons: ' \ | |
52 | 'Pull request reviewer approval is pending.' |
|
51 | 'Pull request reviewer approval is pending.' | |
53 | assert_error(id_, expected, given=response.body) |
|
52 | assert_error(id_, expected, given=response.body) | |
54 |
|
53 | |||
55 | @pytest.mark.backends("git", "hg") |
|
54 | @pytest.mark.backends("git", "hg") | |
56 | def test_api_merge_pull_request_merge_failed_disallowed_state( |
|
55 | def test_api_merge_pull_request_merge_failed_disallowed_state( | |
57 | self, pr_util, no_notifications): |
|
56 | self, pr_util, no_notifications): | |
58 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
57 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) | |
59 | pull_request_id = pull_request.pull_request_id |
|
58 | pull_request_id = pull_request.pull_request_id | |
60 | pull_request_repo = pull_request.target_repo.repo_name |
|
59 | pull_request_repo = pull_request.target_repo.repo_name | |
61 |
|
60 | |||
62 | pr = PullRequest.get(pull_request_id) |
|
61 | pr = PullRequest.get(pull_request_id) | |
63 | pr.pull_request_state = pull_request.STATE_UPDATING |
|
62 | pr.pull_request_state = pull_request.STATE_UPDATING | |
64 | Session().add(pr) |
|
63 | Session().add(pr) | |
65 | Session().commit() |
|
64 | Session().commit() | |
66 |
|
65 | |||
67 | id_, params = build_data( |
|
66 | id_, params = build_data( | |
68 | self.apikey, 'merge_pull_request', |
|
67 | self.apikey, 'merge_pull_request', | |
69 | repoid=pull_request_repo, |
|
68 | repoid=pull_request_repo, | |
70 | pullrequestid=pull_request_id) |
|
69 | pullrequestid=pull_request_id) | |
71 |
|
70 | |||
72 | response = api_call(self.app, params) |
|
71 | response = api_call(self.app, params) | |
73 | expected = 'Operation forbidden because pull request is in state {}, '\ |
|
72 | expected = 'Operation forbidden because pull request is in state {}, '\ | |
74 | 'only state {} is allowed.'.format(PullRequest.STATE_UPDATING, |
|
73 | 'only state {} is allowed.'.format(PullRequest.STATE_UPDATING, | |
75 | PullRequest.STATE_CREATED) |
|
74 | PullRequest.STATE_CREATED) | |
76 | assert_error(id_, expected, given=response.body) |
|
75 | assert_error(id_, expected, given=response.body) | |
77 |
|
76 | |||
78 | @pytest.mark.backends("git", "hg") |
|
77 | @pytest.mark.backends("git", "hg") | |
79 | def test_api_merge_pull_request(self, pr_util, no_notifications): |
|
78 | def test_api_merge_pull_request(self, pr_util, no_notifications): | |
80 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
79 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) | |
81 | author = pull_request.user_id |
|
80 | author = pull_request.user_id | |
82 | repo = pull_request.target_repo.repo_id |
|
81 | repo = pull_request.target_repo.repo_id | |
83 | pull_request_id = pull_request.pull_request_id |
|
82 | pull_request_id = pull_request.pull_request_id | |
84 | pull_request_repo = pull_request.target_repo.repo_name |
|
83 | pull_request_repo = pull_request.target_repo.repo_name | |
85 |
|
84 | |||
86 | id_, params = build_data( |
|
85 | id_, params = build_data( | |
87 | self.apikey, 'comment_pull_request', |
|
86 | self.apikey, 'comment_pull_request', | |
88 | repoid=pull_request_repo, |
|
87 | repoid=pull_request_repo, | |
89 | pullrequestid=pull_request_id, |
|
88 | pullrequestid=pull_request_id, | |
90 | status='approved') |
|
89 | status='approved') | |
91 |
|
90 | |||
92 | response = api_call(self.app, params) |
|
91 | response = api_call(self.app, params) | |
93 | expected = { |
|
92 | expected = { | |
94 | 'comment_id': response.json.get('result', {}).get('comment_id'), |
|
93 | 'comment_id': response.json.get('result', {}).get('comment_id'), | |
95 | 'pull_request_id': pull_request_id, |
|
94 | 'pull_request_id': pull_request_id, | |
96 | 'status': {'given': 'approved', 'was_changed': True} |
|
95 | 'status': {'given': 'approved', 'was_changed': True} | |
97 | } |
|
96 | } | |
98 | assert_ok(id_, expected, given=response.body) |
|
97 | assert_ok(id_, expected, given=response.body) | |
99 |
|
98 | |||
100 | id_, params = build_data( |
|
99 | id_, params = build_data( | |
101 | self.apikey, 'merge_pull_request', |
|
100 | self.apikey, 'merge_pull_request', | |
102 | repoid=pull_request_repo, |
|
101 | repoid=pull_request_repo, | |
103 | pullrequestid=pull_request_id) |
|
102 | pullrequestid=pull_request_id) | |
104 |
|
103 | |||
105 | response = api_call(self.app, params) |
|
104 | response = api_call(self.app, params) | |
106 |
|
105 | |||
107 | pull_request = PullRequest.get(pull_request_id) |
|
106 | pull_request = PullRequest.get(pull_request_id) | |
108 |
|
107 | |||
109 | expected = { |
|
108 | expected = { | |
110 | 'executed': True, |
|
109 | 'executed': True, | |
111 | 'failure_reason': 0, |
|
110 | 'failure_reason': 0, | |
112 | 'merge_status_message': 'This pull request can be automatically merged.', |
|
111 | 'merge_status_message': 'This pull request can be automatically merged.', | |
113 | 'possible': True, |
|
112 | 'possible': True, | |
114 | 'merge_commit_id': pull_request.shadow_merge_ref.commit_id, |
|
113 | 'merge_commit_id': pull_request.shadow_merge_ref.commit_id, | |
115 |
'merge_ref': pull_request.shadow_merge_ref. |
|
114 | 'merge_ref': pull_request.shadow_merge_ref.asdict() | |
116 | } |
|
115 | } | |
117 |
|
116 | |||
118 | assert_ok(id_, expected, response.body) |
|
117 | assert_ok(id_, expected, response.body) | |
119 |
|
118 | |||
120 | journal = UserLog.query()\ |
|
119 | journal = UserLog.query()\ | |
121 | .filter(UserLog.user_id == author)\ |
|
120 | .filter(UserLog.user_id == author)\ | |
122 | .filter(UserLog.repository_id == repo) \ |
|
121 | .filter(UserLog.repository_id == repo) \ | |
123 | .order_by(UserLog.user_log_id.asc()) \ |
|
122 | .order_by(UserLog.user_log_id.asc()) \ | |
124 | .all() |
|
123 | .all() | |
125 | assert journal[-2].action == 'repo.pull_request.merge' |
|
124 | assert journal[-2].action == 'repo.pull_request.merge' | |
126 | assert journal[-1].action == 'repo.pull_request.close' |
|
125 | assert journal[-1].action == 'repo.pull_request.close' | |
127 |
|
126 | |||
128 | id_, params = build_data( |
|
127 | id_, params = build_data( | |
129 | self.apikey, 'merge_pull_request', |
|
128 | self.apikey, 'merge_pull_request', | |
130 | repoid=pull_request_repo, pullrequestid=pull_request_id) |
|
129 | repoid=pull_request_repo, pullrequestid=pull_request_id) | |
131 | response = api_call(self.app, params) |
|
130 | response = api_call(self.app, params) | |
132 |
|
131 | |||
133 | expected = 'merge not possible for following reasons: This pull request is closed.' |
|
132 | expected = 'merge not possible for following reasons: This pull request is closed.' | |
134 | assert_error(id_, expected, given=response.body) |
|
133 | assert_error(id_, expected, given=response.body) | |
135 |
|
134 | |||
136 | @pytest.mark.backends("git", "hg") |
|
135 | @pytest.mark.backends("git", "hg") | |
137 | def test_api_merge_pull_request_as_another_user_no_perms_to_merge( |
|
136 | def test_api_merge_pull_request_as_another_user_no_perms_to_merge( | |
138 | self, pr_util, no_notifications, user_util): |
|
137 | self, pr_util, no_notifications, user_util): | |
139 | merge_user = user_util.create_user() |
|
138 | merge_user = user_util.create_user() | |
140 | merge_user_id = merge_user.user_id |
|
139 | merge_user_id = merge_user.user_id | |
141 | merge_user_username = merge_user.username |
|
140 | merge_user_username = merge_user.username | |
142 |
|
141 | |||
143 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
142 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) | |
144 |
|
143 | |||
145 | pull_request_id = pull_request.pull_request_id |
|
144 | pull_request_id = pull_request.pull_request_id | |
146 | pull_request_repo = pull_request.target_repo.repo_name |
|
145 | pull_request_repo = pull_request.target_repo.repo_name | |
147 |
|
146 | |||
148 | id_, params = build_data( |
|
147 | id_, params = build_data( | |
149 | self.apikey, 'comment_pull_request', |
|
148 | self.apikey, 'comment_pull_request', | |
150 | repoid=pull_request_repo, |
|
149 | repoid=pull_request_repo, | |
151 | pullrequestid=pull_request_id, |
|
150 | pullrequestid=pull_request_id, | |
152 | status='approved') |
|
151 | status='approved') | |
153 |
|
152 | |||
154 | response = api_call(self.app, params) |
|
153 | response = api_call(self.app, params) | |
155 | expected = { |
|
154 | expected = { | |
156 | 'comment_id': response.json.get('result', {}).get('comment_id'), |
|
155 | 'comment_id': response.json.get('result', {}).get('comment_id'), | |
157 | 'pull_request_id': pull_request_id, |
|
156 | 'pull_request_id': pull_request_id, | |
158 | 'status': {'given': 'approved', 'was_changed': True} |
|
157 | 'status': {'given': 'approved', 'was_changed': True} | |
159 | } |
|
158 | } | |
160 | assert_ok(id_, expected, given=response.body) |
|
159 | assert_ok(id_, expected, given=response.body) | |
161 | id_, params = build_data( |
|
160 | id_, params = build_data( | |
162 | self.apikey, 'merge_pull_request', |
|
161 | self.apikey, 'merge_pull_request', | |
163 | repoid=pull_request_repo, |
|
162 | repoid=pull_request_repo, | |
164 | pullrequestid=pull_request_id, |
|
163 | pullrequestid=pull_request_id, | |
165 | userid=merge_user_id |
|
164 | userid=merge_user_id | |
166 | ) |
|
165 | ) | |
167 |
|
166 | |||
168 | response = api_call(self.app, params) |
|
167 | response = api_call(self.app, params) | |
169 | expected = 'merge not possible for following reasons: User `{}` ' \ |
|
168 | expected = 'merge not possible for following reasons: User `{}` ' \ | |
170 | 'not allowed to perform merge.'.format(merge_user_username) |
|
169 | 'not allowed to perform merge.'.format(merge_user_username) | |
171 | assert_error(id_, expected, response.body) |
|
170 | assert_error(id_, expected, response.body) | |
172 |
|
171 | |||
173 | @pytest.mark.backends("git", "hg") |
|
172 | @pytest.mark.backends("git", "hg") | |
174 | def test_api_merge_pull_request_as_another_user(self, pr_util, no_notifications, user_util): |
|
173 | def test_api_merge_pull_request_as_another_user(self, pr_util, no_notifications, user_util): | |
175 | merge_user = user_util.create_user() |
|
174 | merge_user = user_util.create_user() | |
176 | merge_user_id = merge_user.user_id |
|
175 | merge_user_id = merge_user.user_id | |
177 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
176 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) | |
178 | user_util.grant_user_permission_to_repo( |
|
177 | user_util.grant_user_permission_to_repo( | |
179 | pull_request.target_repo, merge_user, 'repository.write') |
|
178 | pull_request.target_repo, merge_user, 'repository.write') | |
180 | author = pull_request.user_id |
|
179 | author = pull_request.user_id | |
181 | repo = pull_request.target_repo.repo_id |
|
180 | repo = pull_request.target_repo.repo_id | |
182 | pull_request_id = pull_request.pull_request_id |
|
181 | pull_request_id = pull_request.pull_request_id | |
183 | pull_request_repo = pull_request.target_repo.repo_name |
|
182 | pull_request_repo = pull_request.target_repo.repo_name | |
184 |
|
183 | |||
185 | id_, params = build_data( |
|
184 | id_, params = build_data( | |
186 | self.apikey, 'comment_pull_request', |
|
185 | self.apikey, 'comment_pull_request', | |
187 | repoid=pull_request_repo, |
|
186 | repoid=pull_request_repo, | |
188 | pullrequestid=pull_request_id, |
|
187 | pullrequestid=pull_request_id, | |
189 | status='approved') |
|
188 | status='approved') | |
190 |
|
189 | |||
191 | response = api_call(self.app, params) |
|
190 | response = api_call(self.app, params) | |
192 | expected = { |
|
191 | expected = { | |
193 | 'comment_id': response.json.get('result', {}).get('comment_id'), |
|
192 | 'comment_id': response.json.get('result', {}).get('comment_id'), | |
194 | 'pull_request_id': pull_request_id, |
|
193 | 'pull_request_id': pull_request_id, | |
195 | 'status': {'given': 'approved', 'was_changed': True} |
|
194 | 'status': {'given': 'approved', 'was_changed': True} | |
196 | } |
|
195 | } | |
197 | assert_ok(id_, expected, given=response.body) |
|
196 | assert_ok(id_, expected, given=response.body) | |
198 |
|
197 | |||
199 | id_, params = build_data( |
|
198 | id_, params = build_data( | |
200 | self.apikey, 'merge_pull_request', |
|
199 | self.apikey, 'merge_pull_request', | |
201 | repoid=pull_request_repo, |
|
200 | repoid=pull_request_repo, | |
202 | pullrequestid=pull_request_id, |
|
201 | pullrequestid=pull_request_id, | |
203 | userid=merge_user_id |
|
202 | userid=merge_user_id | |
204 | ) |
|
203 | ) | |
205 |
|
204 | |||
206 | response = api_call(self.app, params) |
|
205 | response = api_call(self.app, params) | |
207 |
|
206 | |||
208 | pull_request = PullRequest.get(pull_request_id) |
|
207 | pull_request = PullRequest.get(pull_request_id) | |
209 |
|
208 | |||
210 | expected = { |
|
209 | expected = { | |
211 | 'executed': True, |
|
210 | 'executed': True, | |
212 | 'failure_reason': 0, |
|
211 | 'failure_reason': 0, | |
213 | 'merge_status_message': 'This pull request can be automatically merged.', |
|
212 | 'merge_status_message': 'This pull request can be automatically merged.', | |
214 | 'possible': True, |
|
213 | 'possible': True, | |
215 | 'merge_commit_id': pull_request.shadow_merge_ref.commit_id, |
|
214 | 'merge_commit_id': pull_request.shadow_merge_ref.commit_id, | |
216 |
'merge_ref': pull_request.shadow_merge_ref. |
|
215 | 'merge_ref': pull_request.shadow_merge_ref.asdict() | |
217 | } |
|
216 | } | |
218 |
|
217 | |||
219 | assert_ok(id_, expected, response.body) |
|
218 | assert_ok(id_, expected, response.body) | |
220 |
|
219 | |||
221 | journal = UserLog.query() \ |
|
220 | journal = UserLog.query() \ | |
222 | .filter(UserLog.user_id == merge_user_id) \ |
|
221 | .filter(UserLog.user_id == merge_user_id) \ | |
223 | .filter(UserLog.repository_id == repo) \ |
|
222 | .filter(UserLog.repository_id == repo) \ | |
224 | .order_by(UserLog.user_log_id.asc()) \ |
|
223 | .order_by(UserLog.user_log_id.asc()) \ | |
225 | .all() |
|
224 | .all() | |
226 | assert journal[-2].action == 'repo.pull_request.merge' |
|
225 | assert journal[-2].action == 'repo.pull_request.merge' | |
227 | assert journal[-1].action == 'repo.pull_request.close' |
|
226 | assert journal[-1].action == 'repo.pull_request.close' | |
228 |
|
227 | |||
229 | id_, params = build_data( |
|
228 | id_, params = build_data( | |
230 | self.apikey, 'merge_pull_request', |
|
229 | self.apikey, 'merge_pull_request', | |
231 | repoid=pull_request_repo, pullrequestid=pull_request_id, userid=merge_user_id) |
|
230 | repoid=pull_request_repo, pullrequestid=pull_request_id, userid=merge_user_id) | |
232 | response = api_call(self.app, params) |
|
231 | response = api_call(self.app, params) | |
233 |
|
232 | |||
234 | expected = 'merge not possible for following reasons: This pull request is closed.' |
|
233 | expected = 'merge not possible for following reasons: This pull request is closed.' | |
235 | assert_error(id_, expected, given=response.body) |
|
234 | assert_error(id_, expected, given=response.body) | |
236 |
|
235 | |||
237 | @pytest.mark.backends("git", "hg") |
|
236 | @pytest.mark.backends("git", "hg") | |
238 | def test_api_merge_pull_request_repo_error(self, pr_util): |
|
237 | def test_api_merge_pull_request_repo_error(self, pr_util): | |
239 | pull_request = pr_util.create_pull_request() |
|
238 | pull_request = pr_util.create_pull_request() | |
240 | id_, params = build_data( |
|
239 | id_, params = build_data( | |
241 | self.apikey, 'merge_pull_request', |
|
240 | self.apikey, 'merge_pull_request', | |
242 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
241 | repoid=666, pullrequestid=pull_request.pull_request_id) | |
243 | response = api_call(self.app, params) |
|
242 | response = api_call(self.app, params) | |
244 |
|
243 | |||
245 | expected = 'repository `666` does not exist' |
|
244 | expected = 'repository `666` does not exist' | |
246 | assert_error(id_, expected, given=response.body) |
|
245 | assert_error(id_, expected, given=response.body) | |
247 |
|
246 | |||
248 | @pytest.mark.backends("git", "hg") |
|
247 | @pytest.mark.backends("git", "hg") | |
249 | def test_api_merge_pull_request_non_admin_with_userid_error(self, pr_util): |
|
248 | def test_api_merge_pull_request_non_admin_with_userid_error(self, pr_util): | |
250 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
249 | pull_request = pr_util.create_pull_request(mergeable=True) | |
251 | id_, params = build_data( |
|
250 | id_, params = build_data( | |
252 | self.apikey_regular, 'merge_pull_request', |
|
251 | self.apikey_regular, 'merge_pull_request', | |
253 | repoid=pull_request.target_repo.repo_name, |
|
252 | repoid=pull_request.target_repo.repo_name, | |
254 | pullrequestid=pull_request.pull_request_id, |
|
253 | pullrequestid=pull_request.pull_request_id, | |
255 | userid=TEST_USER_ADMIN_LOGIN) |
|
254 | userid=TEST_USER_ADMIN_LOGIN) | |
256 | response = api_call(self.app, params) |
|
255 | response = api_call(self.app, params) | |
257 |
|
256 | |||
258 | expected = 'userid is not the same as your user' |
|
257 | expected = 'userid is not the same as your user' | |
259 | assert_error(id_, expected, given=response.body) |
|
258 | assert_error(id_, expected, given=response.body) |
@@ -1,55 +1,54 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import os |
|
20 | import os | |
22 | import mock |
|
21 | import mock | |
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.tests import TESTS_TMP_PATH |
|
24 | from rhodecode.tests import TESTS_TMP_PATH | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_ok, assert_error) |
|
26 | build_data, api_call, assert_ok, assert_error) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestPull(object): |
|
30 | class TestPull(object): | |
32 |
|
31 | |||
33 | @pytest.mark.backends("git", "hg") |
|
32 | @pytest.mark.backends("git", "hg") | |
34 | def test_api_pull(self, backend): |
|
33 | def test_api_pull(self, backend): | |
35 | r = backend.create_repo() |
|
34 | r = backend.create_repo() | |
36 | repo_name = r.repo_name |
|
35 | repo_name = r.repo_name | |
37 | clone_uri = os.path.join(TESTS_TMP_PATH, backend.repo_name) |
|
36 | clone_uri = os.path.join(TESTS_TMP_PATH, backend.repo_name) | |
38 | r.clone_uri = clone_uri |
|
37 | r.clone_uri = clone_uri | |
39 |
|
38 | |||
40 | id_, params = build_data(self.apikey, 'pull', repoid=repo_name,) |
|
39 | id_, params = build_data(self.apikey, 'pull', repoid=repo_name,) | |
41 | with mock.patch('rhodecode.model.scm.url_validator'): |
|
40 | with mock.patch('rhodecode.model.scm.url_validator'): | |
42 | response = api_call(self.app, params) |
|
41 | response = api_call(self.app, params) | |
43 | msg = 'Pulled from url `%s` on repo `%s`' % ( |
|
42 | msg = 'Pulled from url `%s` on repo `%s`' % ( | |
44 | clone_uri, repo_name) |
|
43 | clone_uri, repo_name) | |
45 | expected = {'msg': msg, |
|
44 | expected = {'msg': msg, | |
46 | 'repository': repo_name} |
|
45 | 'repository': repo_name} | |
47 | assert_ok(id_, expected, given=response.body) |
|
46 | assert_ok(id_, expected, given=response.body) | |
48 |
|
47 | |||
49 | def test_api_pull_error(self, backend): |
|
48 | def test_api_pull_error(self, backend): | |
50 | id_, params = build_data( |
|
49 | id_, params = build_data( | |
51 | self.apikey, 'pull', repoid=backend.repo_name) |
|
50 | self.apikey, 'pull', repoid=backend.repo_name) | |
52 | response = api_call(self.app, params) |
|
51 | response = api_call(self.app, params) | |
53 |
|
52 | |||
54 | expected = 'Unable to pull changes from `None`' |
|
53 | expected = 'Unable to pull changes from `None`' | |
55 | assert_error(id_, expected, given=response.body) |
|
54 | assert_error(id_, expected, given=response.body) |
@@ -1,66 +1,65 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.db import Repository, RepositoryField |
|
22 | from rhodecode.model.db import Repository, RepositoryField | |
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestRemoveFieldFromRepo(object): |
|
27 | class TestRemoveFieldFromRepo(object): | |
29 | def test_api_remove_field_from_repo(self, backend): |
|
28 | def test_api_remove_field_from_repo(self, backend): | |
30 | repo = backend.create_repo() |
|
29 | repo = backend.create_repo() | |
31 | repo_name = repo.repo_name |
|
30 | repo_name = repo.repo_name | |
32 |
|
31 | |||
33 | id_, params = build_data( |
|
32 | id_, params = build_data( | |
34 | self.apikey, 'add_field_to_repo', |
|
33 | self.apikey, 'add_field_to_repo', | |
35 | repoid=repo_name, |
|
34 | repoid=repo_name, | |
36 | key='extra_field', |
|
35 | key='extra_field', | |
37 | label='extra_field_label', |
|
36 | label='extra_field_label', | |
38 | description='extra_field_desc') |
|
37 | description='extra_field_desc') | |
39 | response = api_call(self.app, params) |
|
38 | response = api_call(self.app, params) | |
40 | expected = { |
|
39 | expected = { | |
41 | 'msg': 'Added new repository field `extra_field`', |
|
40 | 'msg': 'Added new repository field `extra_field`', | |
42 | 'success': True, |
|
41 | 'success': True, | |
43 | } |
|
42 | } | |
44 | assert_ok(id_, expected, given=response.body) |
|
43 | assert_ok(id_, expected, given=response.body) | |
45 |
|
44 | |||
46 | repo = Repository.get_by_repo_name(repo_name) |
|
45 | repo = Repository.get_by_repo_name(repo_name) | |
47 | repo_field = RepositoryField.get_by_key_name('extra_field', repo) |
|
46 | repo_field = RepositoryField.get_by_key_name('extra_field', repo) | |
48 | _data = repo_field.get_dict() |
|
47 | _data = repo_field.get_dict() | |
49 | assert _data['field_desc'] == 'extra_field_desc' |
|
48 | assert _data['field_desc'] == 'extra_field_desc' | |
50 | assert _data['field_key'] == 'extra_field' |
|
49 | assert _data['field_key'] == 'extra_field' | |
51 | assert _data['field_label'] == 'extra_field_label' |
|
50 | assert _data['field_label'] == 'extra_field_label' | |
52 |
|
51 | |||
53 | id_, params = build_data( |
|
52 | id_, params = build_data( | |
54 | self.apikey, 'remove_field_from_repo', |
|
53 | self.apikey, 'remove_field_from_repo', | |
55 | repoid=repo_name, |
|
54 | repoid=repo_name, | |
56 | key='extra_field') |
|
55 | key='extra_field') | |
57 | response = api_call(self.app, params) |
|
56 | response = api_call(self.app, params) | |
58 | expected = { |
|
57 | expected = { | |
59 | 'msg': 'Deleted repository field `extra_field`', |
|
58 | 'msg': 'Deleted repository field `extra_field`', | |
60 | 'success': True, |
|
59 | 'success': True, | |
61 | } |
|
60 | } | |
62 | assert_ok(id_, expected, given=response.body) |
|
61 | assert_ok(id_, expected, given=response.body) | |
63 | repo = Repository.get_by_repo_name(repo_name) |
|
62 | repo = Repository.get_by_repo_name(repo_name) | |
64 | repo_field = RepositoryField.get_by_key_name('extra_field', repo) |
|
63 | repo_field = RepositoryField.get_by_key_name('extra_field', repo) | |
65 |
|
64 | |||
66 | assert repo_field is None |
|
65 | assert repo_field is None |
@@ -1,58 +1,57 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.user_group import UserGroupModel |
|
23 | from rhodecode.model.user_group import UserGroupModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestRemoveUserFromUserGroup(object): |
|
29 | class TestRemoveUserFromUserGroup(object): | |
31 | def test_api_remove_user_from_user_group(self, user_util): |
|
30 | def test_api_remove_user_from_user_group(self, user_util): | |
32 | user, group = user_util.create_user_with_group() |
|
31 | user, group = user_util.create_user_with_group() | |
33 | user_name = user.username |
|
32 | user_name = user.username | |
34 | group_name = group.users_group_name |
|
33 | group_name = group.users_group_name | |
35 | id_, params = build_data( |
|
34 | id_, params = build_data( | |
36 | self.apikey, 'remove_user_from_user_group', |
|
35 | self.apikey, 'remove_user_from_user_group', | |
37 | usergroupid=group_name, |
|
36 | usergroupid=group_name, | |
38 | userid=user.username) |
|
37 | userid=user.username) | |
39 | response = api_call(self.app, params) |
|
38 | response = api_call(self.app, params) | |
40 |
|
39 | |||
41 | expected = { |
|
40 | expected = { | |
42 | 'msg': 'removed member `%s` from user group `%s`' % ( |
|
41 | 'msg': 'removed member `%s` from user group `%s`' % ( | |
43 | user_name, group_name |
|
42 | user_name, group_name | |
44 | ), |
|
43 | ), | |
45 | 'success': True} |
|
44 | 'success': True} | |
46 | assert_ok(id_, expected, given=response.body) |
|
45 | assert_ok(id_, expected, given=response.body) | |
47 |
|
46 | |||
48 | @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash) |
|
47 | @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash) | |
49 | def test_api_remove_user_from_user_group_exception_occurred( |
|
48 | def test_api_remove_user_from_user_group_exception_occurred( | |
50 | self, user_util): |
|
49 | self, user_util): | |
51 | user, group = user_util.create_user_with_group() |
|
50 | user, group = user_util.create_user_with_group() | |
52 | id_, params = build_data( |
|
51 | id_, params = build_data( | |
53 | self.apikey, 'remove_user_from_user_group', |
|
52 | self.apikey, 'remove_user_from_user_group', | |
54 | usergroupid=group.users_group_name, userid=user.username) |
|
53 | usergroupid=group.users_group_name, userid=user.username) | |
55 | response = api_call(self.app, params) |
|
54 | response = api_call(self.app, params) | |
56 | expected = 'failed to remove member from user group `%s`' % ( |
|
55 | expected = 'failed to remove member from user group `%s`' % ( | |
57 | group.users_group_name) |
|
56 | group.users_group_name) | |
58 | assert_error(id_, expected, given=response.body) |
|
57 | assert_error(id_, expected, given=response.body) |
@@ -1,184 +1,183 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import mock |
|
21 | import mock | |
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.model.db import Repository |
|
24 | from rhodecode.model.db import Repository | |
26 | from rhodecode.model.user import UserModel |
|
25 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.lib.ext_json import json |
|
26 | from rhodecode.lib.ext_json import json | |
28 | from rhodecode.lib.utils2 import time_to_datetime |
|
27 | from rhodecode.lib.utils2 import time_to_datetime | |
29 | from rhodecode.api.tests.utils import ( |
|
28 | from rhodecode.api.tests.utils import ( | |
30 | build_data, api_call, assert_ok, assert_error, crash) |
|
29 | build_data, api_call, assert_ok, assert_error, crash) | |
31 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
30 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
32 |
|
31 | |||
33 |
|
32 | |||
34 | @pytest.mark.usefixtures("testuser_api", "app") |
|
33 | @pytest.mark.usefixtures("testuser_api", "app") | |
35 | class TestLock(object): |
|
34 | class TestLock(object): | |
36 | def test_api_lock_repo_lock_aquire(self, backend): |
|
35 | def test_api_lock_repo_lock_aquire(self, backend): | |
37 | id_, params = build_data( |
|
36 | id_, params = build_data( | |
38 | self.apikey, 'lock', |
|
37 | self.apikey, 'lock', | |
39 | userid=TEST_USER_ADMIN_LOGIN, |
|
38 | userid=TEST_USER_ADMIN_LOGIN, | |
40 | repoid=backend.repo_name, |
|
39 | repoid=backend.repo_name, | |
41 | locked=True) |
|
40 | locked=True) | |
42 | response = api_call(self.app, params) |
|
41 | response = api_call(self.app, params) | |
43 | expected = { |
|
42 | expected = { | |
44 | 'repo': backend.repo_name, 'locked': True, |
|
43 | 'repo': backend.repo_name, 'locked': True, | |
45 | 'locked_since': response.json['result']['locked_since'], |
|
44 | 'locked_since': response.json['result']['locked_since'], | |
46 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
45 | 'locked_by': TEST_USER_ADMIN_LOGIN, | |
47 | 'lock_state_changed': True, |
|
46 | 'lock_state_changed': True, | |
48 | 'lock_reason': Repository.LOCK_API, |
|
47 | 'lock_reason': Repository.LOCK_API, | |
49 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
48 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' | |
50 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, True)) |
|
49 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, True)) | |
51 | } |
|
50 | } | |
52 | assert_ok(id_, expected, given=response.body) |
|
51 | assert_ok(id_, expected, given=response.body) | |
53 |
|
52 | |||
54 | def test_repo_lock_aquire_by_non_admin(self, backend): |
|
53 | def test_repo_lock_aquire_by_non_admin(self, backend): | |
55 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
54 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) | |
56 | repo_name = repo.repo_name |
|
55 | repo_name = repo.repo_name | |
57 | id_, params = build_data( |
|
56 | id_, params = build_data( | |
58 | self.apikey_regular, 'lock', |
|
57 | self.apikey_regular, 'lock', | |
59 | repoid=repo_name, |
|
58 | repoid=repo_name, | |
60 | locked=True) |
|
59 | locked=True) | |
61 | response = api_call(self.app, params) |
|
60 | response = api_call(self.app, params) | |
62 | expected = { |
|
61 | expected = { | |
63 | 'repo': repo_name, |
|
62 | 'repo': repo_name, | |
64 | 'locked': True, |
|
63 | 'locked': True, | |
65 | 'locked_since': response.json['result']['locked_since'], |
|
64 | 'locked_since': response.json['result']['locked_since'], | |
66 | 'locked_by': self.TEST_USER_LOGIN, |
|
65 | 'locked_by': self.TEST_USER_LOGIN, | |
67 | 'lock_state_changed': True, |
|
66 | 'lock_state_changed': True, | |
68 | 'lock_reason': Repository.LOCK_API, |
|
67 | 'lock_reason': Repository.LOCK_API, | |
69 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
68 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' | |
70 | % (self.TEST_USER_LOGIN, repo_name, True)) |
|
69 | % (self.TEST_USER_LOGIN, repo_name, True)) | |
71 | } |
|
70 | } | |
72 | assert_ok(id_, expected, given=response.body) |
|
71 | assert_ok(id_, expected, given=response.body) | |
73 |
|
72 | |||
74 | def test_api_lock_repo_lock_aquire_non_admin_with_userid(self, backend): |
|
73 | def test_api_lock_repo_lock_aquire_non_admin_with_userid(self, backend): | |
75 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
74 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) | |
76 | repo_name = repo.repo_name |
|
75 | repo_name = repo.repo_name | |
77 | id_, params = build_data( |
|
76 | id_, params = build_data( | |
78 | self.apikey_regular, 'lock', |
|
77 | self.apikey_regular, 'lock', | |
79 | userid=TEST_USER_ADMIN_LOGIN, |
|
78 | userid=TEST_USER_ADMIN_LOGIN, | |
80 | repoid=repo_name, |
|
79 | repoid=repo_name, | |
81 | locked=True) |
|
80 | locked=True) | |
82 | response = api_call(self.app, params) |
|
81 | response = api_call(self.app, params) | |
83 | expected = 'userid is not the same as your user' |
|
82 | expected = 'userid is not the same as your user' | |
84 | assert_error(id_, expected, given=response.body) |
|
83 | assert_error(id_, expected, given=response.body) | |
85 |
|
84 | |||
86 | def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self, backend): |
|
85 | def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self, backend): | |
87 | id_, params = build_data( |
|
86 | id_, params = build_data( | |
88 | self.apikey_regular, 'lock', |
|
87 | self.apikey_regular, 'lock', | |
89 | repoid=backend.repo_name, |
|
88 | repoid=backend.repo_name, | |
90 | locked=True) |
|
89 | locked=True) | |
91 | response = api_call(self.app, params) |
|
90 | response = api_call(self.app, params) | |
92 | expected = 'repository `%s` does not exist' % (backend.repo_name, ) |
|
91 | expected = 'repository `%s` does not exist' % (backend.repo_name, ) | |
93 | assert_error(id_, expected, given=response.body) |
|
92 | assert_error(id_, expected, given=response.body) | |
94 |
|
93 | |||
95 | def test_api_lock_repo_lock_release(self, backend): |
|
94 | def test_api_lock_repo_lock_release(self, backend): | |
96 | id_, params = build_data( |
|
95 | id_, params = build_data( | |
97 | self.apikey, 'lock', |
|
96 | self.apikey, 'lock', | |
98 | userid=TEST_USER_ADMIN_LOGIN, |
|
97 | userid=TEST_USER_ADMIN_LOGIN, | |
99 | repoid=backend.repo_name, |
|
98 | repoid=backend.repo_name, | |
100 | locked=False) |
|
99 | locked=False) | |
101 | response = api_call(self.app, params) |
|
100 | response = api_call(self.app, params) | |
102 | expected = { |
|
101 | expected = { | |
103 | 'repo': backend.repo_name, |
|
102 | 'repo': backend.repo_name, | |
104 | 'locked': False, |
|
103 | 'locked': False, | |
105 | 'locked_since': None, |
|
104 | 'locked_since': None, | |
106 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
105 | 'locked_by': TEST_USER_ADMIN_LOGIN, | |
107 | 'lock_state_changed': True, |
|
106 | 'lock_state_changed': True, | |
108 | 'lock_reason': Repository.LOCK_API, |
|
107 | 'lock_reason': Repository.LOCK_API, | |
109 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
108 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' | |
110 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, False)) |
|
109 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, False)) | |
111 | } |
|
110 | } | |
112 | assert_ok(id_, expected, given=response.body) |
|
111 | assert_ok(id_, expected, given=response.body) | |
113 |
|
112 | |||
114 | def test_api_lock_repo_lock_aquire_optional_userid(self, backend): |
|
113 | def test_api_lock_repo_lock_aquire_optional_userid(self, backend): | |
115 | id_, params = build_data( |
|
114 | id_, params = build_data( | |
116 | self.apikey, 'lock', |
|
115 | self.apikey, 'lock', | |
117 | repoid=backend.repo_name, |
|
116 | repoid=backend.repo_name, | |
118 | locked=True) |
|
117 | locked=True) | |
119 | response = api_call(self.app, params) |
|
118 | response = api_call(self.app, params) | |
120 | time_ = response.json['result']['locked_since'] |
|
119 | time_ = response.json['result']['locked_since'] | |
121 | expected = { |
|
120 | expected = { | |
122 | 'repo': backend.repo_name, |
|
121 | 'repo': backend.repo_name, | |
123 | 'locked': True, |
|
122 | 'locked': True, | |
124 | 'locked_since': time_, |
|
123 | 'locked_since': time_, | |
125 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
124 | 'locked_by': TEST_USER_ADMIN_LOGIN, | |
126 | 'lock_state_changed': True, |
|
125 | 'lock_state_changed': True, | |
127 | 'lock_reason': Repository.LOCK_API, |
|
126 | 'lock_reason': Repository.LOCK_API, | |
128 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
127 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' | |
129 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, True)) |
|
128 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, True)) | |
130 | } |
|
129 | } | |
131 |
|
130 | |||
132 | assert_ok(id_, expected, given=response.body) |
|
131 | assert_ok(id_, expected, given=response.body) | |
133 |
|
132 | |||
134 | def test_api_lock_repo_lock_optional_locked(self, backend): |
|
133 | def test_api_lock_repo_lock_optional_locked(self, backend): | |
135 | # TODO: Provide a fixture locked_repository or similar |
|
134 | # TODO: Provide a fixture locked_repository or similar | |
136 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
135 | repo = Repository.get_by_repo_name(backend.repo_name) | |
137 | user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
136 | user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
138 | Repository.lock(repo, user.user_id, lock_reason=Repository.LOCK_API) |
|
137 | Repository.lock(repo, user.user_id, lock_reason=Repository.LOCK_API) | |
139 |
|
138 | |||
140 | id_, params = build_data(self.apikey, 'lock', repoid=backend.repo_name) |
|
139 | id_, params = build_data(self.apikey, 'lock', repoid=backend.repo_name) | |
141 | response = api_call(self.app, params) |
|
140 | response = api_call(self.app, params) | |
142 | time_ = response.json['result']['locked_since'] |
|
141 | time_ = response.json['result']['locked_since'] | |
143 | expected = { |
|
142 | expected = { | |
144 | 'repo': backend.repo_name, |
|
143 | 'repo': backend.repo_name, | |
145 | 'locked': True, |
|
144 | 'locked': True, | |
146 | 'locked_since': time_, |
|
145 | 'locked_since': time_, | |
147 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
146 | 'locked_by': TEST_USER_ADMIN_LOGIN, | |
148 | 'lock_state_changed': False, |
|
147 | 'lock_state_changed': False, | |
149 | 'lock_reason': Repository.LOCK_API, |
|
148 | 'lock_reason': Repository.LOCK_API, | |
150 | 'msg': ('Repo `%s` locked by `%s` on `%s`.' |
|
149 | 'msg': ('Repo `%s` locked by `%s` on `%s`.' | |
151 | % (backend.repo_name, TEST_USER_ADMIN_LOGIN, |
|
150 | % (backend.repo_name, TEST_USER_ADMIN_LOGIN, | |
152 | json.dumps(time_to_datetime(time_)))) |
|
151 | json.dumps(time_to_datetime(time_)))) | |
153 | } |
|
152 | } | |
154 | assert_ok(id_, expected, given=response.body) |
|
153 | assert_ok(id_, expected, given=response.body) | |
155 |
|
154 | |||
156 | def test_api_lock_repo_lock_optional_not_locked(self, backend): |
|
155 | def test_api_lock_repo_lock_optional_not_locked(self, backend): | |
157 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
156 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) | |
158 | repo_name = repo.repo_name |
|
157 | repo_name = repo.repo_name | |
159 | assert repo.locked == [None, None, None] |
|
158 | assert repo.locked == [None, None, None] | |
160 | id_, params = build_data(self.apikey, 'lock', repoid=repo.repo_id) |
|
159 | id_, params = build_data(self.apikey, 'lock', repoid=repo.repo_id) | |
161 | response = api_call(self.app, params) |
|
160 | response = api_call(self.app, params) | |
162 | expected = { |
|
161 | expected = { | |
163 | 'repo': repo_name, |
|
162 | 'repo': repo_name, | |
164 | 'locked': False, |
|
163 | 'locked': False, | |
165 | 'locked_since': None, |
|
164 | 'locked_since': None, | |
166 | 'locked_by': None, |
|
165 | 'locked_by': None, | |
167 | 'lock_state_changed': False, |
|
166 | 'lock_state_changed': False, | |
168 | 'lock_reason': None, |
|
167 | 'lock_reason': None, | |
169 | 'msg': ('Repo `%s` not locked.' % (repo_name,)) |
|
168 | 'msg': ('Repo `%s` not locked.' % (repo_name,)) | |
170 | } |
|
169 | } | |
171 | assert_ok(id_, expected, given=response.body) |
|
170 | assert_ok(id_, expected, given=response.body) | |
172 |
|
171 | |||
173 | @mock.patch.object(Repository, 'lock', crash) |
|
172 | @mock.patch.object(Repository, 'lock', crash) | |
174 | def test_api_lock_error(self, backend): |
|
173 | def test_api_lock_error(self, backend): | |
175 | id_, params = build_data( |
|
174 | id_, params = build_data( | |
176 | self.apikey, 'lock', |
|
175 | self.apikey, 'lock', | |
177 | userid=TEST_USER_ADMIN_LOGIN, |
|
176 | userid=TEST_USER_ADMIN_LOGIN, | |
178 | repoid=backend.repo_name, |
|
177 | repoid=backend.repo_name, | |
179 | locked=True) |
|
178 | locked=True) | |
180 | response = api_call(self.app, params) |
|
179 | response = api_call(self.app, params) | |
181 |
|
180 | |||
182 | expected = 'Error occurred locking repository `%s`' % ( |
|
181 | expected = 'Error occurred locking repository `%s`' % ( | |
183 | backend.repo_name,) |
|
182 | backend.repo_name,) | |
184 | assert_error(id_, expected, given=response.body) |
|
183 | assert_error(id_, expected, given=response.body) |
@@ -1,44 +1,43 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.scm import ScmModel |
|
23 | from rhodecode.model.scm import ScmModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_ok, assert_error, crash) |
|
25 | build_data, api_call, assert_ok, assert_error, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestRescanRepos(object): |
|
29 | class TestRescanRepos(object): | |
31 | def test_api_rescan_repos(self): |
|
30 | def test_api_rescan_repos(self): | |
32 | id_, params = build_data(self.apikey, 'rescan_repos') |
|
31 | id_, params = build_data(self.apikey, 'rescan_repos') | |
33 | response = api_call(self.app, params) |
|
32 | response = api_call(self.app, params) | |
34 |
|
33 | |||
35 | expected = {'added': [], 'removed': []} |
|
34 | expected = {'added': [], 'removed': []} | |
36 | assert_ok(id_, expected, given=response.body) |
|
35 | assert_ok(id_, expected, given=response.body) | |
37 |
|
36 | |||
38 | @mock.patch.object(ScmModel, 'repo_scan', crash) |
|
37 | @mock.patch.object(ScmModel, 'repo_scan', crash) | |
39 | def test_api_rescann_error(self): |
|
38 | def test_api_rescann_error(self): | |
40 | id_, params = build_data(self.apikey, 'rescan_repos', ) |
|
39 | id_, params = build_data(self.apikey, 'rescan_repos', ) | |
41 | response = api_call(self.app, params) |
|
40 | response = api_call(self.app, params) | |
42 |
|
41 | |||
43 | expected = 'Error occurred during rescan repositories action' |
|
42 | expected = 'Error occurred during rescan repositories action' | |
44 | assert_error(id_, expected, given=response.body) |
|
43 | assert_error(id_, expected, given=response.body) |
@@ -1,67 +1,66 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestRevokeUserGroupPermission(object): |
|
29 | class TestRevokeUserGroupPermission(object): | |
31 | def test_api_revoke_user_group_permission(self, backend, user_util): |
|
30 | def test_api_revoke_user_group_permission(self, backend, user_util): | |
32 | repo = backend.create_repo() |
|
31 | repo = backend.create_repo() | |
33 | user_group = user_util.create_user_group() |
|
32 | user_group = user_util.create_user_group() | |
34 | user_util.grant_user_group_permission_to_repo( |
|
33 | user_util.grant_user_group_permission_to_repo( | |
35 | repo, user_group, 'repository.read') |
|
34 | repo, user_group, 'repository.read') | |
36 | id_, params = build_data( |
|
35 | id_, params = build_data( | |
37 | self.apikey, |
|
36 | self.apikey, | |
38 | 'revoke_user_group_permission', |
|
37 | 'revoke_user_group_permission', | |
39 | repoid=backend.repo_name, |
|
38 | repoid=backend.repo_name, | |
40 | usergroupid=user_group.users_group_name) |
|
39 | usergroupid=user_group.users_group_name) | |
41 | response = api_call(self.app, params) |
|
40 | response = api_call(self.app, params) | |
42 |
|
41 | |||
43 | expected = { |
|
42 | expected = { | |
44 | 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % ( |
|
43 | 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % ( | |
45 | user_group.users_group_name, backend.repo_name |
|
44 | user_group.users_group_name, backend.repo_name | |
46 | ), |
|
45 | ), | |
47 | 'success': True |
|
46 | 'success': True | |
48 | } |
|
47 | } | |
49 | assert_ok(id_, expected, given=response.body) |
|
48 | assert_ok(id_, expected, given=response.body) | |
50 |
|
49 | |||
51 | @mock.patch.object(RepoModel, 'revoke_user_group_permission', crash) |
|
50 | @mock.patch.object(RepoModel, 'revoke_user_group_permission', crash) | |
52 | def test_api_revoke_user_group_permission_exception_when_adding( |
|
51 | def test_api_revoke_user_group_permission_exception_when_adding( | |
53 | self, backend, user_util): |
|
52 | self, backend, user_util): | |
54 | user_group = user_util.create_user_group() |
|
53 | user_group = user_util.create_user_group() | |
55 | id_, params = build_data( |
|
54 | id_, params = build_data( | |
56 | self.apikey, |
|
55 | self.apikey, | |
57 | 'revoke_user_group_permission', |
|
56 | 'revoke_user_group_permission', | |
58 | repoid=backend.repo_name, |
|
57 | repoid=backend.repo_name, | |
59 | usergroupid=user_group.users_group_name) |
|
58 | usergroupid=user_group.users_group_name) | |
60 | response = api_call(self.app, params) |
|
59 | response = api_call(self.app, params) | |
61 |
|
60 | |||
62 | expected = ( |
|
61 | expected = ( | |
63 | 'failed to edit permission for user group: `%s` in repo: `%s`' % ( |
|
62 | 'failed to edit permission for user group: `%s` in repo: `%s`' % ( | |
64 | user_group.users_group_name, backend.repo_name |
|
63 | user_group.users_group_name, backend.repo_name | |
65 | ) |
|
64 | ) | |
66 | ) |
|
65 | ) | |
67 | assert_error(id_, expected, given=response.body) |
|
66 | assert_error(id_, expected, given=response.body) |
@@ -1,129 +1,128 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo_group import RepoGroupModel |
|
23 | from rhodecode.model.repo_group import RepoGroupModel | |
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
26 | from rhodecode.api.tests.utils import ( |
|
25 | from rhodecode.api.tests.utils import ( | |
27 | build_data, api_call, assert_error, assert_ok, crash) |
|
26 | build_data, api_call, assert_error, assert_ok, crash) | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | @pytest.mark.usefixtures("testuser_api", "app") | |
31 | class TestRevokeUserGroupPermissionFromRepoGroup(object): |
|
30 | class TestRevokeUserGroupPermissionFromRepoGroup(object): | |
32 | @pytest.mark.parametrize("name, apply_to_children", [ |
|
31 | @pytest.mark.parametrize("name, apply_to_children", [ | |
33 | ('none', 'none'), |
|
32 | ('none', 'none'), | |
34 | ('all', 'all'), |
|
33 | ('all', 'all'), | |
35 | ('repos', 'repos'), |
|
34 | ('repos', 'repos'), | |
36 | ('groups', 'groups'), |
|
35 | ('groups', 'groups'), | |
37 | ]) |
|
36 | ]) | |
38 | def test_api_revoke_user_group_permission_from_repo_group( |
|
37 | def test_api_revoke_user_group_permission_from_repo_group( | |
39 | self, name, apply_to_children, user_util): |
|
38 | self, name, apply_to_children, user_util): | |
40 | user_group = user_util.create_user_group() |
|
39 | user_group = user_util.create_user_group() | |
41 | repo_group = user_util.create_repo_group() |
|
40 | repo_group = user_util.create_repo_group() | |
42 | user_util.grant_user_group_permission_to_repo_group( |
|
41 | user_util.grant_user_group_permission_to_repo_group( | |
43 | repo_group, user_group, 'group.read') |
|
42 | repo_group, user_group, 'group.read') | |
44 |
|
43 | |||
45 | id_, params = build_data( |
|
44 | id_, params = build_data( | |
46 | self.apikey, 'revoke_user_group_permission_from_repo_group', |
|
45 | self.apikey, 'revoke_user_group_permission_from_repo_group', | |
47 | repogroupid=repo_group.name, |
|
46 | repogroupid=repo_group.name, | |
48 | usergroupid=user_group.users_group_name, |
|
47 | usergroupid=user_group.users_group_name, | |
49 | apply_to_children=apply_to_children,) |
|
48 | apply_to_children=apply_to_children,) | |
50 | response = api_call(self.app, params) |
|
49 | response = api_call(self.app, params) | |
51 |
|
50 | |||
52 | expected = { |
|
51 | expected = { | |
53 | 'msg': ( |
|
52 | 'msg': ( | |
54 | 'Revoked perm (recursive:%s) for user group: `%s`' |
|
53 | 'Revoked perm (recursive:%s) for user group: `%s`' | |
55 | ' in repo group: `%s`' % ( |
|
54 | ' in repo group: `%s`' % ( | |
56 | apply_to_children, user_group.users_group_name, |
|
55 | apply_to_children, user_group.users_group_name, | |
57 | repo_group.name |
|
56 | repo_group.name | |
58 | ) |
|
57 | ) | |
59 | ), |
|
58 | ), | |
60 | 'success': True |
|
59 | 'success': True | |
61 | } |
|
60 | } | |
62 | assert_ok(id_, expected, given=response.body) |
|
61 | assert_ok(id_, expected, given=response.body) | |
63 |
|
62 | |||
64 | @pytest.mark.parametrize( |
|
63 | @pytest.mark.parametrize( | |
65 | "name, apply_to_children, grant_admin, access_ok", [ |
|
64 | "name, apply_to_children, grant_admin, access_ok", [ | |
66 | ('none', 'none', False, False), |
|
65 | ('none', 'none', False, False), | |
67 | ('all', 'all', False, False), |
|
66 | ('all', 'all', False, False), | |
68 | ('repos', 'repos', False, False), |
|
67 | ('repos', 'repos', False, False), | |
69 | ('groups', 'groups', False, False), |
|
68 | ('groups', 'groups', False, False), | |
70 |
|
69 | |||
71 | # after granting admin rights |
|
70 | # after granting admin rights | |
72 | ('none', 'none', False, False), |
|
71 | ('none', 'none', False, False), | |
73 | ('all', 'all', False, False), |
|
72 | ('all', 'all', False, False), | |
74 | ('repos', 'repos', False, False), |
|
73 | ('repos', 'repos', False, False), | |
75 | ('groups', 'groups', False, False), |
|
74 | ('groups', 'groups', False, False), | |
76 | ] |
|
75 | ] | |
77 | ) |
|
76 | ) | |
78 | def test_api_revoke_user_group_permission_from_repo_group_by_regular_user( |
|
77 | def test_api_revoke_user_group_permission_from_repo_group_by_regular_user( | |
79 | self, name, apply_to_children, grant_admin, access_ok, user_util): |
|
78 | self, name, apply_to_children, grant_admin, access_ok, user_util): | |
80 | user_group = user_util.create_user_group() |
|
79 | user_group = user_util.create_user_group() | |
81 | repo_group = user_util.create_repo_group() |
|
80 | repo_group = user_util.create_repo_group() | |
82 | user_util.grant_user_group_permission_to_repo_group( |
|
81 | user_util.grant_user_group_permission_to_repo_group( | |
83 | repo_group, user_group, 'group.read') |
|
82 | repo_group, user_group, 'group.read') | |
84 |
|
83 | |||
85 | if grant_admin: |
|
84 | if grant_admin: | |
86 | user_util.grant_user_permission_to_repo_group( |
|
85 | user_util.grant_user_permission_to_repo_group( | |
87 | repo_group.name, self.TEST_USER_LOGIN, 'group.admin') |
|
86 | repo_group.name, self.TEST_USER_LOGIN, 'group.admin') | |
88 |
|
87 | |||
89 | id_, params = build_data( |
|
88 | id_, params = build_data( | |
90 | self.apikey_regular, |
|
89 | self.apikey_regular, | |
91 | 'revoke_user_group_permission_from_repo_group', |
|
90 | 'revoke_user_group_permission_from_repo_group', | |
92 | repogroupid=repo_group.name, |
|
91 | repogroupid=repo_group.name, | |
93 | usergroupid=user_group.users_group_name, |
|
92 | usergroupid=user_group.users_group_name, | |
94 | apply_to_children=apply_to_children,) |
|
93 | apply_to_children=apply_to_children,) | |
95 | response = api_call(self.app, params) |
|
94 | response = api_call(self.app, params) | |
96 | if access_ok: |
|
95 | if access_ok: | |
97 | expected = { |
|
96 | expected = { | |
98 | 'msg': ( |
|
97 | 'msg': ( | |
99 | 'Revoked perm (recursive:%s) for user group: `%s`' |
|
98 | 'Revoked perm (recursive:%s) for user group: `%s`' | |
100 | ' in repo group: `%s`' % ( |
|
99 | ' in repo group: `%s`' % ( | |
101 | apply_to_children, TEST_USER_ADMIN_LOGIN, |
|
100 | apply_to_children, TEST_USER_ADMIN_LOGIN, | |
102 | repo_group.name |
|
101 | repo_group.name | |
103 | ) |
|
102 | ) | |
104 | ), |
|
103 | ), | |
105 | 'success': True |
|
104 | 'success': True | |
106 | } |
|
105 | } | |
107 | assert_ok(id_, expected, given=response.body) |
|
106 | assert_ok(id_, expected, given=response.body) | |
108 | else: |
|
107 | else: | |
109 | expected = 'repository group `%s` does not exist' % ( |
|
108 | expected = 'repository group `%s` does not exist' % ( | |
110 | repo_group.name,) |
|
109 | repo_group.name,) | |
111 | assert_error(id_, expected, given=response.body) |
|
110 | assert_error(id_, expected, given=response.body) | |
112 |
|
111 | |||
113 | @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', crash) |
|
112 | @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', crash) | |
114 | def test_api_revoke_user_group_permission_from_repo_group_exception_on_add( |
|
113 | def test_api_revoke_user_group_permission_from_repo_group_exception_on_add( | |
115 | self, user_util): |
|
114 | self, user_util): | |
116 | user_group = user_util.create_user_group() |
|
115 | user_group = user_util.create_user_group() | |
117 | repo_group = user_util.create_repo_group() |
|
116 | repo_group = user_util.create_repo_group() | |
118 | id_, params = build_data( |
|
117 | id_, params = build_data( | |
119 | self.apikey, 'revoke_user_group_permission_from_repo_group', |
|
118 | self.apikey, 'revoke_user_group_permission_from_repo_group', | |
120 | repogroupid=repo_group.name, |
|
119 | repogroupid=repo_group.name, | |
121 | usergroupid=user_group.users_group_name) |
|
120 | usergroupid=user_group.users_group_name) | |
122 | response = api_call(self.app, params) |
|
121 | response = api_call(self.app, params) | |
123 |
|
122 | |||
124 | expected = ( |
|
123 | expected = ( | |
125 | 'failed to edit permission for user group: `%s`' |
|
124 | 'failed to edit permission for user group: `%s`' | |
126 | ' in repo group: `%s`' % ( |
|
125 | ' in repo group: `%s`' % ( | |
127 | user_group.users_group_name, repo_group.name) |
|
126 | user_group.users_group_name, repo_group.name) | |
128 | ) |
|
127 | ) | |
129 | assert_error(id_, expected, given=response.body) |
|
128 | assert_error(id_, expected, given=response.body) |
@@ -1,58 +1,57 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.model.user import UserModel |
|
22 | from rhodecode.model.user import UserModel | |
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestRevokeUserGroupPermissionFromUserGroup(object): |
|
27 | class TestRevokeUserGroupPermissionFromUserGroup(object): | |
29 | @pytest.mark.parametrize("name", [ |
|
28 | @pytest.mark.parametrize("name", [ | |
30 | ('none',), |
|
29 | ('none',), | |
31 | ('all',), |
|
30 | ('all',), | |
32 | ('repos',), |
|
31 | ('repos',), | |
33 | ('groups',), |
|
32 | ('groups',), | |
34 | ]) |
|
33 | ]) | |
35 | def test_api_revoke_user_group_permission_from_user_group( |
|
34 | def test_api_revoke_user_group_permission_from_user_group( | |
36 | self, name, user_util): |
|
35 | self, name, user_util): | |
37 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
36 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
38 | group = user_util.create_user_group() |
|
37 | group = user_util.create_user_group() | |
39 | source_group = user_util.create_user_group() |
|
38 | source_group = user_util.create_user_group() | |
40 |
|
39 | |||
41 | user_util.grant_user_permission_to_user_group( |
|
40 | user_util.grant_user_permission_to_user_group( | |
42 | group, user, 'usergroup.read') |
|
41 | group, user, 'usergroup.read') | |
43 | user_util.grant_user_group_permission_to_user_group( |
|
42 | user_util.grant_user_group_permission_to_user_group( | |
44 | source_group, group, 'usergroup.read') |
|
43 | source_group, group, 'usergroup.read') | |
45 |
|
44 | |||
46 | id_, params = build_data( |
|
45 | id_, params = build_data( | |
47 | self.apikey, 'revoke_user_group_permission_from_user_group', |
|
46 | self.apikey, 'revoke_user_group_permission_from_user_group', | |
48 | usergroupid=group.users_group_name, |
|
47 | usergroupid=group.users_group_name, | |
49 | sourceusergroupid=source_group.users_group_name) |
|
48 | sourceusergroupid=source_group.users_group_name) | |
50 | response = api_call(self.app, params) |
|
49 | response = api_call(self.app, params) | |
51 |
|
50 | |||
52 | expected = { |
|
51 | expected = { | |
53 | 'msg': 'Revoked perm for user group: `%s` in user group: `%s`' % ( |
|
52 | 'msg': 'Revoked perm for user group: `%s` in user group: `%s`' % ( | |
54 | source_group.users_group_name, group.users_group_name |
|
53 | source_group.users_group_name, group.users_group_name | |
55 | ), |
|
54 | ), | |
56 | 'success': True |
|
55 | 'success': True | |
57 | } |
|
56 | } | |
58 | assert_ok(id_, expected, given=response.body) |
|
57 | assert_ok(id_, expected, given=response.body) |
@@ -1,66 +1,65 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestRevokeUserPermission(object): |
|
29 | class TestRevokeUserPermission(object): | |
31 | def test_api_revoke_user_permission(self, backend, user_util): |
|
30 | def test_api_revoke_user_permission(self, backend, user_util): | |
32 | repo = backend.create_repo() |
|
31 | repo = backend.create_repo() | |
33 | user = user_util.create_user() |
|
32 | user = user_util.create_user() | |
34 | user_util.grant_user_permission_to_repo( |
|
33 | user_util.grant_user_permission_to_repo( | |
35 | repo, user, 'repository.read') |
|
34 | repo, user, 'repository.read') | |
36 |
|
35 | |||
37 | id_, params = build_data( |
|
36 | id_, params = build_data( | |
38 | self.apikey, |
|
37 | self.apikey, | |
39 | 'revoke_user_permission', |
|
38 | 'revoke_user_permission', | |
40 | repoid=repo.repo_name, |
|
39 | repoid=repo.repo_name, | |
41 | userid=user.username) |
|
40 | userid=user.username) | |
42 | response = api_call(self.app, params) |
|
41 | response = api_call(self.app, params) | |
43 |
|
42 | |||
44 | expected = { |
|
43 | expected = { | |
45 | 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % ( |
|
44 | 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % ( | |
46 | user.username, backend.repo_name |
|
45 | user.username, backend.repo_name | |
47 | ), |
|
46 | ), | |
48 | 'success': True |
|
47 | 'success': True | |
49 | } |
|
48 | } | |
50 | assert_ok(id_, expected, given=response.body) |
|
49 | assert_ok(id_, expected, given=response.body) | |
51 |
|
50 | |||
52 | @mock.patch.object(RepoModel, 'revoke_user_permission', crash) |
|
51 | @mock.patch.object(RepoModel, 'revoke_user_permission', crash) | |
53 | def test_api_revoke_user_permission_exception_when_adding( |
|
52 | def test_api_revoke_user_permission_exception_when_adding( | |
54 | self, backend, user_util): |
|
53 | self, backend, user_util): | |
55 | user = user_util.create_user() |
|
54 | user = user_util.create_user() | |
56 | id_, params = build_data( |
|
55 | id_, params = build_data( | |
57 | self.apikey, |
|
56 | self.apikey, | |
58 | 'revoke_user_permission', |
|
57 | 'revoke_user_permission', | |
59 | repoid=backend.repo_name, |
|
58 | repoid=backend.repo_name, | |
60 | userid=user.username) |
|
59 | userid=user.username) | |
61 | response = api_call(self.app, params) |
|
60 | response = api_call(self.app, params) | |
62 |
|
61 | |||
63 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
|
62 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( | |
64 | user.username, backend.repo_name |
|
63 | user.username, backend.repo_name | |
65 | ) |
|
64 | ) | |
66 | assert_error(id_, expected, given=response.body) |
|
65 | assert_error(id_, expected, given=response.body) |
@@ -1,126 +1,125 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo_group import RepoGroupModel |
|
23 | from rhodecode.model.repo_group import RepoGroupModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestRevokeUserPermissionFromRepoGroup(object): |
|
29 | class TestRevokeUserPermissionFromRepoGroup(object): | |
31 | @pytest.mark.parametrize("name, apply_to_children", [ |
|
30 | @pytest.mark.parametrize("name, apply_to_children", [ | |
32 | ('none', 'none'), |
|
31 | ('none', 'none'), | |
33 | ('all', 'all'), |
|
32 | ('all', 'all'), | |
34 | ('repos', 'repos'), |
|
33 | ('repos', 'repos'), | |
35 | ('groups', 'groups'), |
|
34 | ('groups', 'groups'), | |
36 | ]) |
|
35 | ]) | |
37 | def test_api_revoke_user_permission_from_repo_group( |
|
36 | def test_api_revoke_user_permission_from_repo_group( | |
38 | self, name, apply_to_children, user_util): |
|
37 | self, name, apply_to_children, user_util): | |
39 | user = user_util.create_user() |
|
38 | user = user_util.create_user() | |
40 | repo_group = user_util.create_repo_group() |
|
39 | repo_group = user_util.create_repo_group() | |
41 | user_util.grant_user_permission_to_repo_group( |
|
40 | user_util.grant_user_permission_to_repo_group( | |
42 | repo_group, user, 'group.read') |
|
41 | repo_group, user, 'group.read') | |
43 |
|
42 | |||
44 | id_, params = build_data( |
|
43 | id_, params = build_data( | |
45 | self.apikey, |
|
44 | self.apikey, | |
46 | 'revoke_user_permission_from_repo_group', |
|
45 | 'revoke_user_permission_from_repo_group', | |
47 | repogroupid=repo_group.name, |
|
46 | repogroupid=repo_group.name, | |
48 | userid=user.username, |
|
47 | userid=user.username, | |
49 | apply_to_children=apply_to_children,) |
|
48 | apply_to_children=apply_to_children,) | |
50 | response = api_call(self.app, params) |
|
49 | response = api_call(self.app, params) | |
51 |
|
50 | |||
52 | expected = { |
|
51 | expected = { | |
53 | 'msg': ( |
|
52 | 'msg': ( | |
54 | 'Revoked perm (recursive:%s) for user: `%s`' |
|
53 | 'Revoked perm (recursive:%s) for user: `%s`' | |
55 | ' in repo group: `%s`' % ( |
|
54 | ' in repo group: `%s`' % ( | |
56 | apply_to_children, user.username, repo_group.name |
|
55 | apply_to_children, user.username, repo_group.name | |
57 | ) |
|
56 | ) | |
58 | ), |
|
57 | ), | |
59 | 'success': True |
|
58 | 'success': True | |
60 | } |
|
59 | } | |
61 | assert_ok(id_, expected, given=response.body) |
|
60 | assert_ok(id_, expected, given=response.body) | |
62 |
|
61 | |||
63 | @pytest.mark.parametrize( |
|
62 | @pytest.mark.parametrize( | |
64 | "name, apply_to_children, grant_admin, access_ok", [ |
|
63 | "name, apply_to_children, grant_admin, access_ok", [ | |
65 | ('none', 'none', False, False), |
|
64 | ('none', 'none', False, False), | |
66 | ('all', 'all', False, False), |
|
65 | ('all', 'all', False, False), | |
67 | ('repos', 'repos', False, False), |
|
66 | ('repos', 'repos', False, False), | |
68 | ('groups', 'groups', False, False), |
|
67 | ('groups', 'groups', False, False), | |
69 |
|
68 | |||
70 | # after granting admin rights |
|
69 | # after granting admin rights | |
71 | ('none', 'none', False, False), |
|
70 | ('none', 'none', False, False), | |
72 | ('all', 'all', False, False), |
|
71 | ('all', 'all', False, False), | |
73 | ('repos', 'repos', False, False), |
|
72 | ('repos', 'repos', False, False), | |
74 | ('groups', 'groups', False, False), |
|
73 | ('groups', 'groups', False, False), | |
75 | ] |
|
74 | ] | |
76 | ) |
|
75 | ) | |
77 | def test_api_revoke_user_permission_from_repo_group_by_regular_user( |
|
76 | def test_api_revoke_user_permission_from_repo_group_by_regular_user( | |
78 | self, name, apply_to_children, grant_admin, access_ok, user_util): |
|
77 | self, name, apply_to_children, grant_admin, access_ok, user_util): | |
79 | user = user_util.create_user() |
|
78 | user = user_util.create_user() | |
80 | repo_group = user_util.create_repo_group() |
|
79 | repo_group = user_util.create_repo_group() | |
81 | permission = 'group.admin' if grant_admin else 'group.read' |
|
80 | permission = 'group.admin' if grant_admin else 'group.read' | |
82 | user_util.grant_user_permission_to_repo_group( |
|
81 | user_util.grant_user_permission_to_repo_group( | |
83 | repo_group, user, permission) |
|
82 | repo_group, user, permission) | |
84 |
|
83 | |||
85 | id_, params = build_data( |
|
84 | id_, params = build_data( | |
86 | self.apikey_regular, |
|
85 | self.apikey_regular, | |
87 | 'revoke_user_permission_from_repo_group', |
|
86 | 'revoke_user_permission_from_repo_group', | |
88 | repogroupid=repo_group.name, |
|
87 | repogroupid=repo_group.name, | |
89 | userid=user.username, |
|
88 | userid=user.username, | |
90 | apply_to_children=apply_to_children,) |
|
89 | apply_to_children=apply_to_children,) | |
91 | response = api_call(self.app, params) |
|
90 | response = api_call(self.app, params) | |
92 | if access_ok: |
|
91 | if access_ok: | |
93 | expected = { |
|
92 | expected = { | |
94 | 'msg': ( |
|
93 | 'msg': ( | |
95 | 'Revoked perm (recursive:%s) for user: `%s`' |
|
94 | 'Revoked perm (recursive:%s) for user: `%s`' | |
96 | ' in repo group: `%s`' % ( |
|
95 | ' in repo group: `%s`' % ( | |
97 | apply_to_children, user.username, repo_group.name |
|
96 | apply_to_children, user.username, repo_group.name | |
98 | ) |
|
97 | ) | |
99 | ), |
|
98 | ), | |
100 | 'success': True |
|
99 | 'success': True | |
101 | } |
|
100 | } | |
102 | assert_ok(id_, expected, given=response.body) |
|
101 | assert_ok(id_, expected, given=response.body) | |
103 | else: |
|
102 | else: | |
104 | expected = 'repository group `%s` does not exist' % ( |
|
103 | expected = 'repository group `%s` does not exist' % ( | |
105 | repo_group.name) |
|
104 | repo_group.name) | |
106 | assert_error(id_, expected, given=response.body) |
|
105 | assert_error(id_, expected, given=response.body) | |
107 |
|
106 | |||
108 | @mock.patch.object(RepoGroupModel, 'revoke_user_permission', crash) |
|
107 | @mock.patch.object(RepoGroupModel, 'revoke_user_permission', crash) | |
109 | def test_api_revoke_user_permission_from_repo_group_exception_when_adding( |
|
108 | def test_api_revoke_user_permission_from_repo_group_exception_when_adding( | |
110 | self, user_util): |
|
109 | self, user_util): | |
111 | user = user_util.create_user() |
|
110 | user = user_util.create_user() | |
112 | repo_group = user_util.create_repo_group() |
|
111 | repo_group = user_util.create_repo_group() | |
113 | id_, params = build_data( |
|
112 | id_, params = build_data( | |
114 | self.apikey, |
|
113 | self.apikey, | |
115 | 'revoke_user_permission_from_repo_group', |
|
114 | 'revoke_user_permission_from_repo_group', | |
116 | repogroupid=repo_group.name, |
|
115 | repogroupid=repo_group.name, | |
117 | userid=user.username |
|
116 | userid=user.username | |
118 | ) |
|
117 | ) | |
119 | response = api_call(self.app, params) |
|
118 | response = api_call(self.app, params) | |
120 |
|
119 | |||
121 | expected = ( |
|
120 | expected = ( | |
122 | 'failed to edit permission for user: `%s` in repo group: `%s`' % ( |
|
121 | 'failed to edit permission for user: `%s` in repo group: `%s`' % ( | |
123 | user.username, repo_group.name |
|
122 | user.username, repo_group.name | |
124 | ) |
|
123 | ) | |
125 | ) |
|
124 | ) | |
126 | assert_error(id_, expected, given=response.body) |
|
125 | assert_error(id_, expected, given=response.body) |
@@ -1,112 +1,111 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.user_group import UserGroupModel |
|
23 | from rhodecode.model.user_group import UserGroupModel | |
25 | from rhodecode.api.tests.utils import ( |
|
24 | from rhodecode.api.tests.utils import ( | |
26 | build_data, api_call, assert_error, assert_ok, crash) |
|
25 | build_data, api_call, assert_error, assert_ok, crash) | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | @pytest.mark.usefixtures("testuser_api", "app") | |
30 | class TestRevokeUserPermissionFromUserGroup(object): |
|
29 | class TestRevokeUserPermissionFromUserGroup(object): | |
31 | @pytest.mark.parametrize("name", [ |
|
30 | @pytest.mark.parametrize("name", [ | |
32 | ('none',), |
|
31 | ('none',), | |
33 | ('all',), |
|
32 | ('all',), | |
34 | ('repos',), |
|
33 | ('repos',), | |
35 | ('groups',), |
|
34 | ('groups',), | |
36 | ]) |
|
35 | ]) | |
37 | def test_api_revoke_user_permission_from_user_group(self, name, user_util): |
|
36 | def test_api_revoke_user_permission_from_user_group(self, name, user_util): | |
38 | user = user_util.create_user() |
|
37 | user = user_util.create_user() | |
39 | group = user_util.create_user_group() |
|
38 | group = user_util.create_user_group() | |
40 | user_util.grant_user_permission_to_user_group( |
|
39 | user_util.grant_user_permission_to_user_group( | |
41 | group, user, 'usergroup.admin') |
|
40 | group, user, 'usergroup.admin') | |
42 |
|
41 | |||
43 | id_, params = build_data( |
|
42 | id_, params = build_data( | |
44 | self.apikey, |
|
43 | self.apikey, | |
45 | 'revoke_user_permission_from_user_group', |
|
44 | 'revoke_user_permission_from_user_group', | |
46 | usergroupid=group.users_group_name, |
|
45 | usergroupid=group.users_group_name, | |
47 | userid=user.username) |
|
46 | userid=user.username) | |
48 | response = api_call(self.app, params) |
|
47 | response = api_call(self.app, params) | |
49 |
|
48 | |||
50 | expected = { |
|
49 | expected = { | |
51 | 'msg': 'Revoked perm for user: `%s` in user group: `%s`' % ( |
|
50 | 'msg': 'Revoked perm for user: `%s` in user group: `%s`' % ( | |
52 | user.username, group.users_group_name |
|
51 | user.username, group.users_group_name | |
53 | ), |
|
52 | ), | |
54 | 'success': True |
|
53 | 'success': True | |
55 | } |
|
54 | } | |
56 | assert_ok(id_, expected, given=response.body) |
|
55 | assert_ok(id_, expected, given=response.body) | |
57 |
|
56 | |||
58 | @pytest.mark.parametrize("name, grant_admin, access_ok", [ |
|
57 | @pytest.mark.parametrize("name, grant_admin, access_ok", [ | |
59 | ('none', False, False), |
|
58 | ('none', False, False), | |
60 | ('all', False, False), |
|
59 | ('all', False, False), | |
61 | ('repos', False, False), |
|
60 | ('repos', False, False), | |
62 | ('groups', False, False), |
|
61 | ('groups', False, False), | |
63 |
|
62 | |||
64 | # after granting admin rights |
|
63 | # after granting admin rights | |
65 | ('none', False, False), |
|
64 | ('none', False, False), | |
66 | ('all', False, False), |
|
65 | ('all', False, False), | |
67 | ('repos', False, False), |
|
66 | ('repos', False, False), | |
68 | ('groups', False, False), |
|
67 | ('groups', False, False), | |
69 | ]) |
|
68 | ]) | |
70 | def test_api_revoke_user_permission_from_user_group_by_regular_user( |
|
69 | def test_api_revoke_user_permission_from_user_group_by_regular_user( | |
71 | self, name, grant_admin, access_ok, user_util): |
|
70 | self, name, grant_admin, access_ok, user_util): | |
72 | user = user_util.create_user() |
|
71 | user = user_util.create_user() | |
73 | group = user_util.create_user_group() |
|
72 | group = user_util.create_user_group() | |
74 | permission = 'usergroup.admin' if grant_admin else 'usergroup.read' |
|
73 | permission = 'usergroup.admin' if grant_admin else 'usergroup.read' | |
75 | user_util.grant_user_permission_to_user_group(group, user, permission) |
|
74 | user_util.grant_user_permission_to_user_group(group, user, permission) | |
76 |
|
75 | |||
77 | id_, params = build_data( |
|
76 | id_, params = build_data( | |
78 | self.apikey_regular, |
|
77 | self.apikey_regular, | |
79 | 'revoke_user_permission_from_user_group', |
|
78 | 'revoke_user_permission_from_user_group', | |
80 | usergroupid=group.users_group_name, |
|
79 | usergroupid=group.users_group_name, | |
81 | userid=user.username) |
|
80 | userid=user.username) | |
82 | response = api_call(self.app, params) |
|
81 | response = api_call(self.app, params) | |
83 | if access_ok: |
|
82 | if access_ok: | |
84 | expected = { |
|
83 | expected = { | |
85 | 'msg': 'Revoked perm for user: `%s` in user group: `%s`' % ( |
|
84 | 'msg': 'Revoked perm for user: `%s` in user group: `%s`' % ( | |
86 | user.username, group.users_group_name |
|
85 | user.username, group.users_group_name | |
87 | ), |
|
86 | ), | |
88 | 'success': True |
|
87 | 'success': True | |
89 | } |
|
88 | } | |
90 | assert_ok(id_, expected, given=response.body) |
|
89 | assert_ok(id_, expected, given=response.body) | |
91 | else: |
|
90 | else: | |
92 | expected = 'user group `%s` does not exist' % ( |
|
91 | expected = 'user group `%s` does not exist' % ( | |
93 | group.users_group_name) |
|
92 | group.users_group_name) | |
94 | assert_error(id_, expected, given=response.body) |
|
93 | assert_error(id_, expected, given=response.body) | |
95 |
|
94 | |||
96 | @mock.patch.object(UserGroupModel, 'revoke_user_permission', crash) |
|
95 | @mock.patch.object(UserGroupModel, 'revoke_user_permission', crash) | |
97 | def test_api_revoke_user_permission_from_user_group_exception_when_adding( |
|
96 | def test_api_revoke_user_permission_from_user_group_exception_when_adding( | |
98 | self, user_util): |
|
97 | self, user_util): | |
99 | user = user_util.create_user() |
|
98 | user = user_util.create_user() | |
100 | group = user_util.create_user_group() |
|
99 | group = user_util.create_user_group() | |
101 | id_, params = build_data( |
|
100 | id_, params = build_data( | |
102 | self.apikey, |
|
101 | self.apikey, | |
103 | 'revoke_user_permission_from_user_group', |
|
102 | 'revoke_user_permission_from_user_group', | |
104 | usergroupid=group.users_group_name, |
|
103 | usergroupid=group.users_group_name, | |
105 | userid=user.username) |
|
104 | userid=user.username) | |
106 | response = api_call(self.app, params) |
|
105 | response = api_call(self.app, params) | |
107 |
|
106 | |||
108 | expected = ( |
|
107 | expected = ( | |
109 | 'failed to edit permission for user: `%s` in user group: `%s`' % ( |
|
108 | 'failed to edit permission for user: `%s` in user group: `%s`' % ( | |
110 | user.username, group.users_group_name) |
|
109 | user.username, group.users_group_name) | |
111 | ) |
|
110 | ) | |
112 | assert_error(id_, expected, given=response.body) |
|
111 | assert_error(id_, expected, given=response.body) |
@@ -1,59 +1,58 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok, assert_error |
|
23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok, assert_error | |
25 |
|
24 | |||
26 |
|
25 | |||
27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
26 | @pytest.mark.usefixtures("testuser_api", "app") | |
28 | class TestStoreException(object): |
|
27 | class TestStoreException(object): | |
29 |
|
28 | |||
30 | def test_store_exception_invalid_json(self): |
|
29 | def test_store_exception_invalid_json(self): | |
31 | id_, params = build_data(self.apikey, 'store_exception', |
|
30 | id_, params = build_data(self.apikey, 'store_exception', | |
32 | exc_data_json='XXX,{') |
|
31 | exc_data_json='XXX,{') | |
33 | response = api_call(self.app, params) |
|
32 | response = api_call(self.app, params) | |
34 |
|
33 | |||
35 | expected = 'Failed to parse JSON data from exc_data_json field. ' \ |
|
34 | expected = 'Failed to parse JSON data from exc_data_json field. ' \ | |
36 | 'Please make sure it contains a valid JSON.' |
|
35 | 'Please make sure it contains a valid JSON.' | |
37 | assert_error(id_, expected, given=response.body) |
|
36 | assert_error(id_, expected, given=response.body) | |
38 |
|
37 | |||
39 | def test_store_exception_missing_json_params_json(self): |
|
38 | def test_store_exception_missing_json_params_json(self): | |
40 | id_, params = build_data(self.apikey, 'store_exception', |
|
39 | id_, params = build_data(self.apikey, 'store_exception', | |
41 | exc_data_json='{"foo":"bar"}') |
|
40 | exc_data_json='{"foo":"bar"}') | |
42 | response = api_call(self.app, params) |
|
41 | response = api_call(self.app, params) | |
43 |
|
42 | |||
44 | expected = "Missing exc_traceback, or exc_type_name in " \ |
|
43 | expected = "Missing exc_traceback, or exc_type_name in " \ | |
45 | "exc_data_json field. Missing: 'exc_traceback'" |
|
44 | "exc_data_json field. Missing: 'exc_traceback'" | |
46 | assert_error(id_, expected, given=response.body) |
|
45 | assert_error(id_, expected, given=response.body) | |
47 |
|
46 | |||
48 | def test_store_exception(self): |
|
47 | def test_store_exception(self): | |
49 | id_, params = build_data( |
|
48 | id_, params = build_data( | |
50 | self.apikey, 'store_exception', |
|
49 | self.apikey, 'store_exception', | |
51 | exc_data_json='{"exc_traceback": "invalid", "exc_type_name":"ValueError"}') |
|
50 | exc_data_json='{"exc_traceback": "invalid", "exc_type_name":"ValueError"}') | |
52 | response = api_call(self.app, params) |
|
51 | response = api_call(self.app, params) | |
53 | exc_id = response.json['result']['exc_id'] |
|
52 | exc_id = response.json['result']['exc_id'] | |
54 |
|
53 | |||
55 | expected = { |
|
54 | expected = { | |
56 | 'exc_id': exc_id, |
|
55 | 'exc_id': exc_id, | |
57 | 'exc_url': 'http://example.com/_admin/settings/exceptions/{}'.format(exc_id) |
|
56 | 'exc_url': 'http://example.com/_admin/settings/exceptions/{}'.format(exc_id) | |
58 | } |
|
57 | } | |
59 | assert_ok(id_, expected, given=response.body) |
|
58 | assert_ok(id_, expected, given=response.body) |
@@ -1,215 +1,214 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import pytest |
|
20 | import pytest | |
22 |
|
21 | |||
23 | from rhodecode.lib.vcs.nodes import FileNode |
|
22 | from rhodecode.lib.vcs.nodes import FileNode | |
24 | from rhodecode.model.db import User |
|
23 | from rhodecode.model.db import User | |
25 | from rhodecode.model.pull_request import PullRequestModel |
|
24 | from rhodecode.model.pull_request import PullRequestModel | |
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_ok, assert_error) |
|
27 | build_data, api_call, assert_ok, assert_error) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestUpdatePullRequest(object): |
|
31 | class TestUpdatePullRequest(object): | |
33 |
|
32 | |||
34 | @pytest.mark.backends("git", "hg") |
|
33 | @pytest.mark.backends("git", "hg") | |
35 | def test_api_update_pull_request_title_or_description( |
|
34 | def test_api_update_pull_request_title_or_description( | |
36 | self, pr_util, no_notifications): |
|
35 | self, pr_util, no_notifications): | |
37 | pull_request = pr_util.create_pull_request() |
|
36 | pull_request = pr_util.create_pull_request() | |
38 |
|
37 | |||
39 | id_, params = build_data( |
|
38 | id_, params = build_data( | |
40 | self.apikey, 'update_pull_request', |
|
39 | self.apikey, 'update_pull_request', | |
41 | repoid=pull_request.target_repo.repo_name, |
|
40 | repoid=pull_request.target_repo.repo_name, | |
42 | pullrequestid=pull_request.pull_request_id, |
|
41 | pullrequestid=pull_request.pull_request_id, | |
43 | title='New TITLE OF A PR', |
|
42 | title='New TITLE OF A PR', | |
44 | description='New DESC OF A PR', |
|
43 | description='New DESC OF A PR', | |
45 | ) |
|
44 | ) | |
46 | response = api_call(self.app, params) |
|
45 | response = api_call(self.app, params) | |
47 |
|
46 | |||
48 | expected = { |
|
47 | expected = { | |
49 | "msg": "Updated pull request `{}`".format( |
|
48 | "msg": "Updated pull request `{}`".format( | |
50 | pull_request.pull_request_id), |
|
49 | pull_request.pull_request_id), | |
51 | "pull_request": response.json['result']['pull_request'], |
|
50 | "pull_request": response.json['result']['pull_request'], | |
52 | "updated_commits": {"added": [], "common": [], "removed": []}, |
|
51 | "updated_commits": {"added": [], "common": [], "removed": []}, | |
53 | "updated_reviewers": {"added": [], "removed": []}, |
|
52 | "updated_reviewers": {"added": [], "removed": []}, | |
54 | "updated_observers": {"added": [], "removed": []}, |
|
53 | "updated_observers": {"added": [], "removed": []}, | |
55 | } |
|
54 | } | |
56 |
|
55 | |||
57 | response_json = response.json['result'] |
|
56 | response_json = response.json['result'] | |
58 | assert response_json == expected |
|
57 | assert response_json == expected | |
59 | pr = response_json['pull_request'] |
|
58 | pr = response_json['pull_request'] | |
60 | assert pr['title'] == 'New TITLE OF A PR' |
|
59 | assert pr['title'] == 'New TITLE OF A PR' | |
61 | assert pr['description'] == 'New DESC OF A PR' |
|
60 | assert pr['description'] == 'New DESC OF A PR' | |
62 |
|
61 | |||
63 | @pytest.mark.backends("git", "hg") |
|
62 | @pytest.mark.backends("git", "hg") | |
64 | def test_api_try_update_closed_pull_request( |
|
63 | def test_api_try_update_closed_pull_request( | |
65 | self, pr_util, no_notifications): |
|
64 | self, pr_util, no_notifications): | |
66 | pull_request = pr_util.create_pull_request() |
|
65 | pull_request = pr_util.create_pull_request() | |
67 | PullRequestModel().close_pull_request( |
|
66 | PullRequestModel().close_pull_request( | |
68 | pull_request, TEST_USER_ADMIN_LOGIN) |
|
67 | pull_request, TEST_USER_ADMIN_LOGIN) | |
69 |
|
68 | |||
70 | id_, params = build_data( |
|
69 | id_, params = build_data( | |
71 | self.apikey, 'update_pull_request', |
|
70 | self.apikey, 'update_pull_request', | |
72 | repoid=pull_request.target_repo.repo_name, |
|
71 | repoid=pull_request.target_repo.repo_name, | |
73 | pullrequestid=pull_request.pull_request_id) |
|
72 | pullrequestid=pull_request.pull_request_id) | |
74 | response = api_call(self.app, params) |
|
73 | response = api_call(self.app, params) | |
75 |
|
74 | |||
76 | expected = 'pull request `{}` update failed, pull request ' \ |
|
75 | expected = 'pull request `{}` update failed, pull request ' \ | |
77 | 'is closed'.format(pull_request.pull_request_id) |
|
76 | 'is closed'.format(pull_request.pull_request_id) | |
78 |
|
77 | |||
79 | assert_error(id_, expected, response.body) |
|
78 | assert_error(id_, expected, response.body) | |
80 |
|
79 | |||
81 | @pytest.mark.backends("git", "hg") |
|
80 | @pytest.mark.backends("git", "hg") | |
82 | def test_api_update_update_commits(self, pr_util, no_notifications): |
|
81 | def test_api_update_update_commits(self, pr_util, no_notifications): | |
83 | commits = [ |
|
82 | commits = [ | |
84 | {'message': 'a'}, |
|
83 | {'message': 'a'}, | |
85 | {'message': 'b', 'added': [FileNode('file_b', 'test_content\n')]}, |
|
84 | {'message': 'b', 'added': [FileNode(b'file_b', b'test_content\n')]}, | |
86 | {'message': 'c', 'added': [FileNode('file_c', 'test_content\n')]}, |
|
85 | {'message': 'c', 'added': [FileNode(b'file_c', b'test_content\n')]}, | |
87 | ] |
|
86 | ] | |
88 | pull_request = pr_util.create_pull_request( |
|
87 | pull_request = pr_util.create_pull_request( | |
89 | commits=commits, target_head='a', source_head='b', revisions=['b']) |
|
88 | commits=commits, target_head='a', source_head='b', revisions=['b']) | |
90 | pr_util.update_source_repository(head='c') |
|
89 | pr_util.update_source_repository(head='c') | |
91 | repo = pull_request.source_repo.scm_instance() |
|
90 | repo = pull_request.source_repo.scm_instance() | |
92 | commits = [x for x in repo.get_commits()] |
|
91 | commits = [x for x in repo.get_commits()] | |
93 |
|
92 | |||
94 | added_commit_id = commits[-1].raw_id # c commit |
|
93 | added_commit_id = commits[-1].raw_id # c commit | |
95 | common_commit_id = commits[1].raw_id # b commit is common ancestor |
|
94 | common_commit_id = commits[1].raw_id # b commit is common ancestor | |
96 | total_commits = [added_commit_id, common_commit_id] |
|
95 | total_commits = [added_commit_id, common_commit_id] | |
97 |
|
96 | |||
98 | id_, params = build_data( |
|
97 | id_, params = build_data( | |
99 | self.apikey, 'update_pull_request', |
|
98 | self.apikey, 'update_pull_request', | |
100 | repoid=pull_request.target_repo.repo_name, |
|
99 | repoid=pull_request.target_repo.repo_name, | |
101 | pullrequestid=pull_request.pull_request_id, |
|
100 | pullrequestid=pull_request.pull_request_id, | |
102 | update_commits=True |
|
101 | update_commits=True | |
103 | ) |
|
102 | ) | |
104 | response = api_call(self.app, params) |
|
103 | response = api_call(self.app, params) | |
105 |
|
104 | |||
106 | expected = { |
|
105 | expected = { | |
107 | "msg": "Updated pull request `{}`".format( |
|
106 | "msg": "Updated pull request `{}`".format( | |
108 | pull_request.pull_request_id), |
|
107 | pull_request.pull_request_id), | |
109 | "pull_request": response.json['result']['pull_request'], |
|
108 | "pull_request": response.json['result']['pull_request'], | |
110 | "updated_commits": {"added": [added_commit_id], |
|
109 | "updated_commits": {"added": [added_commit_id], | |
111 | "common": [common_commit_id], |
|
110 | "common": [common_commit_id], | |
112 | "total": total_commits, |
|
111 | "total": total_commits, | |
113 | "removed": []}, |
|
112 | "removed": []}, | |
114 | "updated_reviewers": {"added": [], "removed": []}, |
|
113 | "updated_reviewers": {"added": [], "removed": []}, | |
115 | "updated_observers": {"added": [], "removed": []}, |
|
114 | "updated_observers": {"added": [], "removed": []}, | |
116 | } |
|
115 | } | |
117 |
|
116 | |||
118 | assert_ok(id_, expected, response.body) |
|
117 | assert_ok(id_, expected, response.body) | |
119 |
|
118 | |||
120 | @pytest.mark.backends("git", "hg") |
|
119 | @pytest.mark.backends("git", "hg") | |
121 | def test_api_update_change_reviewers( |
|
120 | def test_api_update_change_reviewers( | |
122 | self, user_util, pr_util, no_notifications): |
|
121 | self, user_util, pr_util, no_notifications): | |
123 | a = user_util.create_user() |
|
122 | a = user_util.create_user() | |
124 | b = user_util.create_user() |
|
123 | b = user_util.create_user() | |
125 | c = user_util.create_user() |
|
124 | c = user_util.create_user() | |
126 | new_reviewers = [ |
|
125 | new_reviewers = [ | |
127 | {'username': b.username, 'reasons': ['updated via API'], |
|
126 | {'username': b.username, 'reasons': ['updated via API'], | |
128 | 'mandatory':False}, |
|
127 | 'mandatory':False}, | |
129 | {'username': c.username, 'reasons': ['updated via API'], |
|
128 | {'username': c.username, 'reasons': ['updated via API'], | |
130 | 'mandatory':False}, |
|
129 | 'mandatory':False}, | |
131 | ] |
|
130 | ] | |
132 |
|
131 | |||
133 | added = [b.username, c.username] |
|
132 | added = [b.username, c.username] | |
134 | removed = [a.username] |
|
133 | removed = [a.username] | |
135 |
|
134 | |||
136 | pull_request = pr_util.create_pull_request( |
|
135 | pull_request = pr_util.create_pull_request( | |
137 | reviewers=[(a.username, ['added via API'], False, 'reviewer', [])]) |
|
136 | reviewers=[(a.username, ['added via API'], False, 'reviewer', [])]) | |
138 |
|
137 | |||
139 | id_, params = build_data( |
|
138 | id_, params = build_data( | |
140 | self.apikey, 'update_pull_request', |
|
139 | self.apikey, 'update_pull_request', | |
141 | repoid=pull_request.target_repo.repo_name, |
|
140 | repoid=pull_request.target_repo.repo_name, | |
142 | pullrequestid=pull_request.pull_request_id, |
|
141 | pullrequestid=pull_request.pull_request_id, | |
143 | reviewers=new_reviewers) |
|
142 | reviewers=new_reviewers) | |
144 | response = api_call(self.app, params) |
|
143 | response = api_call(self.app, params) | |
145 | expected = { |
|
144 | expected = { | |
146 | "msg": "Updated pull request `{}`".format( |
|
145 | "msg": "Updated pull request `{}`".format( | |
147 | pull_request.pull_request_id), |
|
146 | pull_request.pull_request_id), | |
148 | "pull_request": response.json['result']['pull_request'], |
|
147 | "pull_request": response.json['result']['pull_request'], | |
149 | "updated_commits": {"added": [], "common": [], "removed": []}, |
|
148 | "updated_commits": {"added": [], "common": [], "removed": []}, | |
150 | "updated_reviewers": {"added": added, "removed": removed}, |
|
149 | "updated_reviewers": {"added": added, "removed": removed}, | |
151 | "updated_observers": {"added": [], "removed": []}, |
|
150 | "updated_observers": {"added": [], "removed": []}, | |
152 | } |
|
151 | } | |
153 |
|
152 | |||
154 | assert_ok(id_, expected, response.body) |
|
153 | assert_ok(id_, expected, response.body) | |
155 |
|
154 | |||
156 | @pytest.mark.backends("git", "hg") |
|
155 | @pytest.mark.backends("git", "hg") | |
157 | def test_api_update_bad_user_in_reviewers(self, pr_util): |
|
156 | def test_api_update_bad_user_in_reviewers(self, pr_util): | |
158 | pull_request = pr_util.create_pull_request() |
|
157 | pull_request = pr_util.create_pull_request() | |
159 |
|
158 | |||
160 | id_, params = build_data( |
|
159 | id_, params = build_data( | |
161 | self.apikey, 'update_pull_request', |
|
160 | self.apikey, 'update_pull_request', | |
162 | repoid=pull_request.target_repo.repo_name, |
|
161 | repoid=pull_request.target_repo.repo_name, | |
163 | pullrequestid=pull_request.pull_request_id, |
|
162 | pullrequestid=pull_request.pull_request_id, | |
164 | reviewers=[{'username': 'bad_name'}]) |
|
163 | reviewers=[{'username': 'bad_name'}]) | |
165 | response = api_call(self.app, params) |
|
164 | response = api_call(self.app, params) | |
166 |
|
165 | |||
167 | expected = 'user `bad_name` does not exist' |
|
166 | expected = 'user `bad_name` does not exist' | |
168 |
|
167 | |||
169 | assert_error(id_, expected, response.body) |
|
168 | assert_error(id_, expected, response.body) | |
170 |
|
169 | |||
171 | @pytest.mark.backends("git", "hg") |
|
170 | @pytest.mark.backends("git", "hg") | |
172 | def test_api_update_repo_error(self, pr_util): |
|
171 | def test_api_update_repo_error(self, pr_util): | |
173 | pull_request = pr_util.create_pull_request() |
|
172 | pull_request = pr_util.create_pull_request() | |
174 | id_, params = build_data( |
|
173 | id_, params = build_data( | |
175 | self.apikey, 'update_pull_request', |
|
174 | self.apikey, 'update_pull_request', | |
176 | repoid='fake', |
|
175 | repoid='fake', | |
177 | pullrequestid=pull_request.pull_request_id, |
|
176 | pullrequestid=pull_request.pull_request_id, | |
178 | reviewers=[{'username': 'bad_name'}]) |
|
177 | reviewers=[{'username': 'bad_name'}]) | |
179 | response = api_call(self.app, params) |
|
178 | response = api_call(self.app, params) | |
180 |
|
179 | |||
181 | expected = 'repository `fake` does not exist' |
|
180 | expected = 'repository `fake` does not exist' | |
182 |
|
181 | |||
183 | response_json = response.json['error'] |
|
182 | response_json = response.json['error'] | |
184 | assert response_json == expected |
|
183 | assert response_json == expected | |
185 |
|
184 | |||
186 | @pytest.mark.backends("git", "hg") |
|
185 | @pytest.mark.backends("git", "hg") | |
187 | def test_api_update_pull_request_error(self, pr_util): |
|
186 | def test_api_update_pull_request_error(self, pr_util): | |
188 | pull_request = pr_util.create_pull_request() |
|
187 | pull_request = pr_util.create_pull_request() | |
189 |
|
188 | |||
190 | id_, params = build_data( |
|
189 | id_, params = build_data( | |
191 | self.apikey, 'update_pull_request', |
|
190 | self.apikey, 'update_pull_request', | |
192 | repoid=pull_request.target_repo.repo_name, |
|
191 | repoid=pull_request.target_repo.repo_name, | |
193 | pullrequestid=999999, |
|
192 | pullrequestid=999999, | |
194 | reviewers=[{'username': 'bad_name'}]) |
|
193 | reviewers=[{'username': 'bad_name'}]) | |
195 | response = api_call(self.app, params) |
|
194 | response = api_call(self.app, params) | |
196 |
|
195 | |||
197 | expected = 'pull request `999999` does not exist' |
|
196 | expected = 'pull request `999999` does not exist' | |
198 | assert_error(id_, expected, response.body) |
|
197 | assert_error(id_, expected, response.body) | |
199 |
|
198 | |||
200 | @pytest.mark.backends("git", "hg") |
|
199 | @pytest.mark.backends("git", "hg") | |
201 | def test_api_update_pull_request_no_perms_to_update( |
|
200 | def test_api_update_pull_request_no_perms_to_update( | |
202 | self, user_util, pr_util): |
|
201 | self, user_util, pr_util): | |
203 | user = user_util.create_user() |
|
202 | user = user_util.create_user() | |
204 | pull_request = pr_util.create_pull_request() |
|
203 | pull_request = pr_util.create_pull_request() | |
205 |
|
204 | |||
206 | id_, params = build_data( |
|
205 | id_, params = build_data( | |
207 | user.api_key, 'update_pull_request', |
|
206 | user.api_key, 'update_pull_request', | |
208 | repoid=pull_request.target_repo.repo_name, |
|
207 | repoid=pull_request.target_repo.repo_name, | |
209 | pullrequestid=pull_request.pull_request_id,) |
|
208 | pullrequestid=pull_request.pull_request_id,) | |
210 | response = api_call(self.app, params) |
|
209 | response = api_call(self.app, params) | |
211 |
|
210 | |||
212 | expected = ('pull request `%s` update failed, ' |
|
211 | expected = ('pull request `%s` update failed, ' | |
213 | 'no permission to update.') % pull_request.pull_request_id |
|
212 | 'no permission to update.') % pull_request.pull_request_id | |
214 |
|
213 | |||
215 | assert_error(id_, expected, response.body) |
|
214 | assert_error(id_, expected, response.body) |
@@ -1,210 +1,209 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.repo import RepoModel |
|
23 | from rhodecode.model.repo import RepoModel | |
25 | from rhodecode.model.scm import ScmModel |
|
24 | from rhodecode.model.scm import ScmModel | |
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN |
|
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_ok, crash, jsonify) |
|
27 | build_data, api_call, assert_error, assert_ok, crash, jsonify) | |
29 | from rhodecode.tests.fixture import Fixture |
|
28 | from rhodecode.tests.fixture import Fixture | |
30 | from rhodecode.tests.fixture_mods.fixture_utils import plain_http_host_only_stub |
|
29 | from rhodecode.tests.fixture_mods.fixture_utils import plain_http_host_only_stub | |
31 |
|
30 | |||
32 | fixture = Fixture() |
|
31 | fixture = Fixture() | |
33 |
|
32 | |||
34 | UPDATE_REPO_NAME = 'api_update_me' |
|
33 | UPDATE_REPO_NAME = 'api_update_me' | |
35 |
|
34 | |||
36 |
|
35 | |||
37 | class SAME_AS_UPDATES(object): |
|
36 | class SAME_AS_UPDATES(object): | |
38 | """ Constant used for tests below """ |
|
37 | """ Constant used for tests below """ | |
39 |
|
38 | |||
40 |
|
39 | |||
41 | @pytest.mark.usefixtures("testuser_api", "app") |
|
40 | @pytest.mark.usefixtures("testuser_api", "app") | |
42 | class TestApiUpdateRepo(object): |
|
41 | class TestApiUpdateRepo(object): | |
43 |
|
42 | |||
44 | @pytest.mark.parametrize("updates, expected", [ |
|
43 | @pytest.mark.parametrize("updates, expected", [ | |
45 | ({'owner': TEST_USER_REGULAR_LOGIN}, |
|
44 | ({'owner': TEST_USER_REGULAR_LOGIN}, | |
46 | SAME_AS_UPDATES), |
|
45 | SAME_AS_UPDATES), | |
47 |
|
46 | |||
48 | ({'description': 'new description'}, |
|
47 | ({'description': 'new description'}, | |
49 | SAME_AS_UPDATES), |
|
48 | SAME_AS_UPDATES), | |
50 |
|
49 | |||
51 | ({'clone_uri': 'http://foo.com/repo'}, |
|
50 | ({'clone_uri': 'http://foo.com/repo'}, | |
52 | SAME_AS_UPDATES), |
|
51 | SAME_AS_UPDATES), | |
53 |
|
52 | |||
54 | ({'clone_uri': None}, |
|
53 | ({'clone_uri': None}, | |
55 | {'clone_uri': ''}), |
|
54 | {'clone_uri': ''}), | |
56 |
|
55 | |||
57 | ({'clone_uri': ''}, |
|
56 | ({'clone_uri': ''}, | |
58 | {'clone_uri': ''}), |
|
57 | {'clone_uri': ''}), | |
59 |
|
58 | |||
60 | ({'clone_uri': 'http://example.com/repo_pull'}, |
|
59 | ({'clone_uri': 'http://example.com/repo_pull'}, | |
61 | {'clone_uri': 'http://example.com/repo_pull'}), |
|
60 | {'clone_uri': 'http://example.com/repo_pull'}), | |
62 |
|
61 | |||
63 | ({'push_uri': ''}, |
|
62 | ({'push_uri': ''}, | |
64 | {'push_uri': ''}), |
|
63 | {'push_uri': ''}), | |
65 |
|
64 | |||
66 | ({'push_uri': 'http://example.com/repo_push'}, |
|
65 | ({'push_uri': 'http://example.com/repo_push'}, | |
67 | {'push_uri': 'http://example.com/repo_push'}), |
|
66 | {'push_uri': 'http://example.com/repo_push'}), | |
68 |
|
67 | |||
69 | ({'landing_rev': None}, # auto-updated based on type of repo |
|
68 | ({'landing_rev': None}, # auto-updated based on type of repo | |
70 | {'landing_rev': [None, None]}), |
|
69 | {'landing_rev': [None, None]}), | |
71 |
|
70 | |||
72 | ({'enable_statistics': True}, |
|
71 | ({'enable_statistics': True}, | |
73 | SAME_AS_UPDATES), |
|
72 | SAME_AS_UPDATES), | |
74 |
|
73 | |||
75 | ({'enable_locking': True}, |
|
74 | ({'enable_locking': True}, | |
76 | SAME_AS_UPDATES), |
|
75 | SAME_AS_UPDATES), | |
77 |
|
76 | |||
78 | ({'enable_downloads': True}, |
|
77 | ({'enable_downloads': True}, | |
79 | SAME_AS_UPDATES), |
|
78 | SAME_AS_UPDATES), | |
80 |
|
79 | |||
81 | ({'repo_name': 'new_repo_name'}, |
|
80 | ({'repo_name': 'new_repo_name'}, | |
82 | { |
|
81 | { | |
83 | 'repo_name': 'new_repo_name', |
|
82 | 'repo_name': 'new_repo_name', | |
84 | 'url': 'http://{}/new_repo_name'.format(plain_http_host_only_stub()) |
|
83 | 'url': 'http://{}/new_repo_name'.format(plain_http_host_only_stub()) | |
85 | }), |
|
84 | }), | |
86 |
|
85 | |||
87 | ({'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), |
|
86 | ({'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), | |
88 | '_group': 'test_group_for_update'}, |
|
87 | '_group': 'test_group_for_update'}, | |
89 | { |
|
88 | { | |
90 | 'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), |
|
89 | 'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), | |
91 | 'url': 'http://{}/test_group_for_update/{}'.format( |
|
90 | 'url': 'http://{}/test_group_for_update/{}'.format( | |
92 | plain_http_host_only_stub(), UPDATE_REPO_NAME) |
|
91 | plain_http_host_only_stub(), UPDATE_REPO_NAME) | |
93 | }), |
|
92 | }), | |
94 | ]) |
|
93 | ]) | |
95 | def test_api_update_repo(self, updates, expected, backend): |
|
94 | def test_api_update_repo(self, updates, expected, backend): | |
96 | repo_name = UPDATE_REPO_NAME |
|
95 | repo_name = UPDATE_REPO_NAME | |
97 | repo = fixture.create_repo(repo_name, repo_type=backend.alias) |
|
96 | repo = fixture.create_repo(repo_name, repo_type=backend.alias) | |
98 | if updates.get('_group'): |
|
97 | if updates.get('_group'): | |
99 | fixture.create_repo_group(updates['_group']) |
|
98 | fixture.create_repo_group(updates['_group']) | |
100 |
|
99 | |||
101 | if 'landing_rev' in updates: |
|
100 | if 'landing_rev' in updates: | |
102 | default_landing_ref, _lbl = ScmModel.backend_landing_ref(backend.alias) |
|
101 | default_landing_ref, _lbl = ScmModel.backend_landing_ref(backend.alias) | |
103 | _type, _name = default_landing_ref.split(':') |
|
102 | _type, _name = default_landing_ref.split(':') | |
104 | updates['landing_rev'] = default_landing_ref |
|
103 | updates['landing_rev'] = default_landing_ref | |
105 | expected['landing_rev'] = [_type, _name] |
|
104 | expected['landing_rev'] = [_type, _name] | |
106 |
|
105 | |||
107 | expected_api_data = repo.get_api_data(include_secrets=True) |
|
106 | expected_api_data = repo.get_api_data(include_secrets=True) | |
108 | if expected is SAME_AS_UPDATES: |
|
107 | if expected is SAME_AS_UPDATES: | |
109 | expected_api_data.update(updates) |
|
108 | expected_api_data.update(updates) | |
110 | else: |
|
109 | else: | |
111 | expected_api_data.update(expected) |
|
110 | expected_api_data.update(expected) | |
112 |
|
111 | |||
113 | id_, params = build_data( |
|
112 | id_, params = build_data( | |
114 | self.apikey, 'update_repo', repoid=repo_name, **updates) |
|
113 | self.apikey, 'update_repo', repoid=repo_name, **updates) | |
115 |
|
114 | |||
116 | with mock.patch('rhodecode.model.validation_schema.validators.url_validator'): |
|
115 | with mock.patch('rhodecode.model.validation_schema.validators.url_validator'): | |
117 | response = api_call(self.app, params) |
|
116 | response = api_call(self.app, params) | |
118 |
|
117 | |||
119 | if updates.get('repo_name'): |
|
118 | if updates.get('repo_name'): | |
120 | repo_name = updates['repo_name'] |
|
119 | repo_name = updates['repo_name'] | |
121 |
|
120 | |||
122 | try: |
|
121 | try: | |
123 | expected = { |
|
122 | expected = { | |
124 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), |
|
123 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), | |
125 | 'repository': jsonify(expected_api_data) |
|
124 | 'repository': jsonify(expected_api_data) | |
126 | } |
|
125 | } | |
127 | assert_ok(id_, expected, given=response.body) |
|
126 | assert_ok(id_, expected, given=response.body) | |
128 | finally: |
|
127 | finally: | |
129 | fixture.destroy_repo(repo_name) |
|
128 | fixture.destroy_repo(repo_name) | |
130 | if updates.get('_group'): |
|
129 | if updates.get('_group'): | |
131 | fixture.destroy_repo_group(updates['_group']) |
|
130 | fixture.destroy_repo_group(updates['_group']) | |
132 |
|
131 | |||
133 | def test_api_update_repo_fork_of_field(self, backend): |
|
132 | def test_api_update_repo_fork_of_field(self, backend): | |
134 | master_repo = backend.create_repo() |
|
133 | master_repo = backend.create_repo() | |
135 | repo = backend.create_repo() |
|
134 | repo = backend.create_repo() | |
136 | updates = { |
|
135 | updates = { | |
137 | 'fork_of': master_repo.repo_name, |
|
136 | 'fork_of': master_repo.repo_name, | |
138 | 'fork_of_id': master_repo.repo_id |
|
137 | 'fork_of_id': master_repo.repo_id | |
139 | } |
|
138 | } | |
140 | expected_api_data = repo.get_api_data(include_secrets=True) |
|
139 | expected_api_data = repo.get_api_data(include_secrets=True) | |
141 | expected_api_data.update(updates) |
|
140 | expected_api_data.update(updates) | |
142 |
|
141 | |||
143 | id_, params = build_data( |
|
142 | id_, params = build_data( | |
144 | self.apikey, 'update_repo', repoid=repo.repo_name, **updates) |
|
143 | self.apikey, 'update_repo', repoid=repo.repo_name, **updates) | |
145 | response = api_call(self.app, params) |
|
144 | response = api_call(self.app, params) | |
146 | expected = { |
|
145 | expected = { | |
147 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo.repo_name), |
|
146 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo.repo_name), | |
148 | 'repository': jsonify(expected_api_data) |
|
147 | 'repository': jsonify(expected_api_data) | |
149 | } |
|
148 | } | |
150 | assert_ok(id_, expected, given=response.body) |
|
149 | assert_ok(id_, expected, given=response.body) | |
151 | result = response.json['result']['repository'] |
|
150 | result = response.json['result']['repository'] | |
152 | assert result['fork_of'] == master_repo.repo_name |
|
151 | assert result['fork_of'] == master_repo.repo_name | |
153 | assert result['fork_of_id'] == master_repo.repo_id |
|
152 | assert result['fork_of_id'] == master_repo.repo_id | |
154 |
|
153 | |||
155 | def test_api_update_repo_fork_of_not_found(self, backend): |
|
154 | def test_api_update_repo_fork_of_not_found(self, backend): | |
156 | master_repo_name = 'fake-parent-repo' |
|
155 | master_repo_name = 'fake-parent-repo' | |
157 | repo = backend.create_repo() |
|
156 | repo = backend.create_repo() | |
158 | updates = { |
|
157 | updates = { | |
159 | 'fork_of': master_repo_name |
|
158 | 'fork_of': master_repo_name | |
160 | } |
|
159 | } | |
161 | id_, params = build_data( |
|
160 | id_, params = build_data( | |
162 | self.apikey, 'update_repo', repoid=repo.repo_name, **updates) |
|
161 | self.apikey, 'update_repo', repoid=repo.repo_name, **updates) | |
163 | response = api_call(self.app, params) |
|
162 | response = api_call(self.app, params) | |
164 | expected = { |
|
163 | expected = { | |
165 | 'repo_fork_of': 'Fork with id `{}` does not exists'.format( |
|
164 | 'repo_fork_of': 'Fork with id `{}` does not exists'.format( | |
166 | master_repo_name)} |
|
165 | master_repo_name)} | |
167 | assert_error(id_, expected, given=response.body) |
|
166 | assert_error(id_, expected, given=response.body) | |
168 |
|
167 | |||
169 | def test_api_update_repo_with_repo_group_not_existing(self): |
|
168 | def test_api_update_repo_with_repo_group_not_existing(self): | |
170 | repo_name = 'admin_owned' |
|
169 | repo_name = 'admin_owned' | |
171 | fake_repo_group = 'test_group_for_update' |
|
170 | fake_repo_group = 'test_group_for_update' | |
172 | fixture.create_repo(repo_name) |
|
171 | fixture.create_repo(repo_name) | |
173 | updates = {'repo_name': '{}/{}'.format(fake_repo_group, repo_name)} |
|
172 | updates = {'repo_name': '{}/{}'.format(fake_repo_group, repo_name)} | |
174 | id_, params = build_data( |
|
173 | id_, params = build_data( | |
175 | self.apikey, 'update_repo', repoid=repo_name, **updates) |
|
174 | self.apikey, 'update_repo', repoid=repo_name, **updates) | |
176 | response = api_call(self.app, params) |
|
175 | response = api_call(self.app, params) | |
177 | try: |
|
176 | try: | |
178 | expected = { |
|
177 | expected = { | |
179 | 'repo_group': 'Repository group `{}` does not exist'.format(fake_repo_group) |
|
178 | 'repo_group': 'Repository group `{}` does not exist'.format(fake_repo_group) | |
180 | } |
|
179 | } | |
181 | assert_error(id_, expected, given=response.body) |
|
180 | assert_error(id_, expected, given=response.body) | |
182 | finally: |
|
181 | finally: | |
183 | fixture.destroy_repo(repo_name) |
|
182 | fixture.destroy_repo(repo_name) | |
184 |
|
183 | |||
185 | def test_api_update_repo_regular_user_not_allowed(self): |
|
184 | def test_api_update_repo_regular_user_not_allowed(self): | |
186 | repo_name = 'admin_owned' |
|
185 | repo_name = 'admin_owned' | |
187 | fixture.create_repo(repo_name) |
|
186 | fixture.create_repo(repo_name) | |
188 | updates = {'active': False} |
|
187 | updates = {'active': False} | |
189 | id_, params = build_data( |
|
188 | id_, params = build_data( | |
190 | self.apikey_regular, 'update_repo', repoid=repo_name, **updates) |
|
189 | self.apikey_regular, 'update_repo', repoid=repo_name, **updates) | |
191 | response = api_call(self.app, params) |
|
190 | response = api_call(self.app, params) | |
192 | try: |
|
191 | try: | |
193 | expected = 'repository `%s` does not exist' % (repo_name,) |
|
192 | expected = 'repository `%s` does not exist' % (repo_name,) | |
194 | assert_error(id_, expected, given=response.body) |
|
193 | assert_error(id_, expected, given=response.body) | |
195 | finally: |
|
194 | finally: | |
196 | fixture.destroy_repo(repo_name) |
|
195 | fixture.destroy_repo(repo_name) | |
197 |
|
196 | |||
198 | @mock.patch.object(RepoModel, 'update', crash) |
|
197 | @mock.patch.object(RepoModel, 'update', crash) | |
199 | def test_api_update_repo_exception_occurred(self, backend): |
|
198 | def test_api_update_repo_exception_occurred(self, backend): | |
200 | repo_name = UPDATE_REPO_NAME |
|
199 | repo_name = UPDATE_REPO_NAME | |
201 | fixture.create_repo(repo_name, repo_type=backend.alias) |
|
200 | fixture.create_repo(repo_name, repo_type=backend.alias) | |
202 | id_, params = build_data( |
|
201 | id_, params = build_data( | |
203 | self.apikey, 'update_repo', repoid=repo_name, |
|
202 | self.apikey, 'update_repo', repoid=repo_name, | |
204 | owner=TEST_USER_ADMIN_LOGIN,) |
|
203 | owner=TEST_USER_ADMIN_LOGIN,) | |
205 | response = api_call(self.app, params) |
|
204 | response = api_call(self.app, params) | |
206 | try: |
|
205 | try: | |
207 | expected = 'failed to update repo `%s`' % (repo_name,) |
|
206 | expected = 'failed to update repo `%s`' % (repo_name,) | |
208 | assert_error(id_, expected, given=response.body) |
|
207 | assert_error(id_, expected, given=response.body) | |
209 | finally: |
|
208 | finally: | |
210 | fixture.destroy_repo(repo_name) |
|
209 | fixture.destroy_repo(repo_name) |
@@ -1,150 +1,149 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import os |
|
20 | import os | |
22 |
|
21 | |||
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.model.repo_group import RepoGroupModel |
|
24 | from rhodecode.model.repo_group import RepoGroupModel | |
26 | from rhodecode.model.user import UserModel |
|
25 | from rhodecode.model.user import UserModel | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_ok) |
|
27 | build_data, api_call, assert_error, assert_ok) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestApiUpdateRepoGroup(object): |
|
31 | class TestApiUpdateRepoGroup(object): | |
33 |
|
32 | |||
34 | def test_update_group_name(self, user_util): |
|
33 | def test_update_group_name(self, user_util): | |
35 | new_group_name = 'new-group' |
|
34 | new_group_name = 'new-group' | |
36 | initial_name = self._update(user_util, group_name=new_group_name) |
|
35 | initial_name = self._update(user_util, group_name=new_group_name) | |
37 | assert RepoGroupModel()._get_repo_group(initial_name) is None |
|
36 | assert RepoGroupModel()._get_repo_group(initial_name) is None | |
38 | new_group = RepoGroupModel()._get_repo_group(new_group_name) |
|
37 | new_group = RepoGroupModel()._get_repo_group(new_group_name) | |
39 | assert new_group is not None |
|
38 | assert new_group is not None | |
40 | assert new_group.full_path == new_group_name |
|
39 | assert new_group.full_path == new_group_name | |
41 |
|
40 | |||
42 | def test_update_group_name_change_parent(self, user_util): |
|
41 | def test_update_group_name_change_parent(self, user_util): | |
43 |
|
42 | |||
44 | parent_group = user_util.create_repo_group() |
|
43 | parent_group = user_util.create_repo_group() | |
45 | parent_group_name = parent_group.name |
|
44 | parent_group_name = parent_group.name | |
46 |
|
45 | |||
47 | expected_group_name = '{}/{}'.format(parent_group_name, 'new-group') |
|
46 | expected_group_name = '{}/{}'.format(parent_group_name, 'new-group') | |
48 | initial_name = self._update(user_util, group_name=expected_group_name) |
|
47 | initial_name = self._update(user_util, group_name=expected_group_name) | |
49 |
|
48 | |||
50 | repo_group = RepoGroupModel()._get_repo_group(expected_group_name) |
|
49 | repo_group = RepoGroupModel()._get_repo_group(expected_group_name) | |
51 |
|
50 | |||
52 | assert repo_group is not None |
|
51 | assert repo_group is not None | |
53 | assert repo_group.group_name == expected_group_name |
|
52 | assert repo_group.group_name == expected_group_name | |
54 | assert repo_group.full_path == expected_group_name |
|
53 | assert repo_group.full_path == expected_group_name | |
55 | assert RepoGroupModel()._get_repo_group(initial_name) is None |
|
54 | assert RepoGroupModel()._get_repo_group(initial_name) is None | |
56 |
|
55 | |||
57 | new_path = os.path.join( |
|
56 | new_path = os.path.join( | |
58 | RepoGroupModel().repos_path, *repo_group.full_path_splitted) |
|
57 | RepoGroupModel().repos_path, *repo_group.full_path_splitted) | |
59 | assert os.path.exists(new_path) |
|
58 | assert os.path.exists(new_path) | |
60 |
|
59 | |||
61 | def test_update_enable_locking(self, user_util): |
|
60 | def test_update_enable_locking(self, user_util): | |
62 | initial_name = self._update(user_util, enable_locking=True) |
|
61 | initial_name = self._update(user_util, enable_locking=True) | |
63 | repo_group = RepoGroupModel()._get_repo_group(initial_name) |
|
62 | repo_group = RepoGroupModel()._get_repo_group(initial_name) | |
64 | assert repo_group.enable_locking is True |
|
63 | assert repo_group.enable_locking is True | |
65 |
|
64 | |||
66 | def test_update_description(self, user_util): |
|
65 | def test_update_description(self, user_util): | |
67 | description = 'New description' |
|
66 | description = 'New description' | |
68 | initial_name = self._update(user_util, description=description) |
|
67 | initial_name = self._update(user_util, description=description) | |
69 | repo_group = RepoGroupModel()._get_repo_group(initial_name) |
|
68 | repo_group = RepoGroupModel()._get_repo_group(initial_name) | |
70 | assert repo_group.group_description == description |
|
69 | assert repo_group.group_description == description | |
71 |
|
70 | |||
72 | def test_update_owner(self, user_util): |
|
71 | def test_update_owner(self, user_util): | |
73 | owner = self.TEST_USER_LOGIN |
|
72 | owner = self.TEST_USER_LOGIN | |
74 | initial_name = self._update(user_util, owner=owner) |
|
73 | initial_name = self._update(user_util, owner=owner) | |
75 | repo_group = RepoGroupModel()._get_repo_group(initial_name) |
|
74 | repo_group = RepoGroupModel()._get_repo_group(initial_name) | |
76 | assert repo_group.user.username == owner |
|
75 | assert repo_group.user.username == owner | |
77 |
|
76 | |||
78 | def test_update_group_name_conflict_with_existing(self, user_util): |
|
77 | def test_update_group_name_conflict_with_existing(self, user_util): | |
79 | group_1 = user_util.create_repo_group() |
|
78 | group_1 = user_util.create_repo_group() | |
80 | group_2 = user_util.create_repo_group() |
|
79 | group_2 = user_util.create_repo_group() | |
81 | repo_group_name_1 = group_1.group_name |
|
80 | repo_group_name_1 = group_1.group_name | |
82 | repo_group_name_2 = group_2.group_name |
|
81 | repo_group_name_2 = group_2.group_name | |
83 |
|
82 | |||
84 | id_, params = build_data( |
|
83 | id_, params = build_data( | |
85 | self.apikey, 'update_repo_group', repogroupid=repo_group_name_1, |
|
84 | self.apikey, 'update_repo_group', repogroupid=repo_group_name_1, | |
86 | group_name=repo_group_name_2) |
|
85 | group_name=repo_group_name_2) | |
87 | response = api_call(self.app, params) |
|
86 | response = api_call(self.app, params) | |
88 | expected = { |
|
87 | expected = { | |
89 | 'unique_repo_group_name': |
|
88 | 'unique_repo_group_name': | |
90 | 'Repository group with name `{}` already exists'.format( |
|
89 | 'Repository group with name `{}` already exists'.format( | |
91 | repo_group_name_2)} |
|
90 | repo_group_name_2)} | |
92 | assert_error(id_, expected, given=response.body) |
|
91 | assert_error(id_, expected, given=response.body) | |
93 |
|
92 | |||
94 | def test_api_update_repo_group_by_regular_user_no_permission(self, user_util): |
|
93 | def test_api_update_repo_group_by_regular_user_no_permission(self, user_util): | |
95 | temp_user = user_util.create_user() |
|
94 | temp_user = user_util.create_user() | |
96 | temp_user_api_key = temp_user.api_key |
|
95 | temp_user_api_key = temp_user.api_key | |
97 | parent_group = user_util.create_repo_group() |
|
96 | parent_group = user_util.create_repo_group() | |
98 | repo_group_name = parent_group.group_name |
|
97 | repo_group_name = parent_group.group_name | |
99 | id_, params = build_data( |
|
98 | id_, params = build_data( | |
100 | temp_user_api_key, 'update_repo_group', repogroupid=repo_group_name) |
|
99 | temp_user_api_key, 'update_repo_group', repogroupid=repo_group_name) | |
101 | response = api_call(self.app, params) |
|
100 | response = api_call(self.app, params) | |
102 | expected = 'repository group `%s` does not exist' % (repo_group_name,) |
|
101 | expected = 'repository group `%s` does not exist' % (repo_group_name,) | |
103 | assert_error(id_, expected, given=response.body) |
|
102 | assert_error(id_, expected, given=response.body) | |
104 |
|
103 | |||
105 | def test_api_update_repo_group_regular_user_no_root_write_permissions( |
|
104 | def test_api_update_repo_group_regular_user_no_root_write_permissions( | |
106 | self, user_util): |
|
105 | self, user_util): | |
107 | temp_user = user_util.create_user() |
|
106 | temp_user = user_util.create_user() | |
108 | temp_user_api_key = temp_user.api_key |
|
107 | temp_user_api_key = temp_user.api_key | |
109 | parent_group = user_util.create_repo_group(owner=temp_user.username) |
|
108 | parent_group = user_util.create_repo_group(owner=temp_user.username) | |
110 | repo_group_name = parent_group.group_name |
|
109 | repo_group_name = parent_group.group_name | |
111 |
|
110 | |||
112 | id_, params = build_data( |
|
111 | id_, params = build_data( | |
113 | temp_user_api_key, 'update_repo_group', repogroupid=repo_group_name, |
|
112 | temp_user_api_key, 'update_repo_group', repogroupid=repo_group_name, | |
114 | group_name='at-root-level') |
|
113 | group_name='at-root-level') | |
115 | response = api_call(self.app, params) |
|
114 | response = api_call(self.app, params) | |
116 | expected = { |
|
115 | expected = { | |
117 | 'repo_group': 'You do not have the permission to store ' |
|
116 | 'repo_group': 'You do not have the permission to store ' | |
118 | 'repository groups in the root location.'} |
|
117 | 'repository groups in the root location.'} | |
119 | assert_error(id_, expected, given=response.body) |
|
118 | assert_error(id_, expected, given=response.body) | |
120 |
|
119 | |||
121 | def _update(self, user_util, **kwargs): |
|
120 | def _update(self, user_util, **kwargs): | |
122 | repo_group = user_util.create_repo_group() |
|
121 | repo_group = user_util.create_repo_group() | |
123 | initial_name = repo_group.name |
|
122 | initial_name = repo_group.name | |
124 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
123 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
125 | user_util.grant_user_permission_to_repo_group( |
|
124 | user_util.grant_user_permission_to_repo_group( | |
126 | repo_group, user, 'group.admin') |
|
125 | repo_group, user, 'group.admin') | |
127 |
|
126 | |||
128 | id_, params = build_data( |
|
127 | id_, params = build_data( | |
129 | self.apikey, 'update_repo_group', repogroupid=initial_name, |
|
128 | self.apikey, 'update_repo_group', repogroupid=initial_name, | |
130 | **kwargs) |
|
129 | **kwargs) | |
131 | response = api_call(self.app, params) |
|
130 | response = api_call(self.app, params) | |
132 |
|
131 | |||
133 | repo_group = RepoGroupModel.cls.get(repo_group.group_id) |
|
132 | repo_group = RepoGroupModel.cls.get(repo_group.group_id) | |
134 |
|
133 | |||
135 | expected = { |
|
134 | expected = { | |
136 | 'msg': 'updated repository group ID:{} {}'.format( |
|
135 | 'msg': 'updated repository group ID:{} {}'.format( | |
137 | repo_group.group_id, repo_group.group_name), |
|
136 | repo_group.group_id, repo_group.group_name), | |
138 | 'repo_group': { |
|
137 | 'repo_group': { | |
139 | 'repositories': [], |
|
138 | 'repositories': [], | |
140 | 'group_name': repo_group.group_name, |
|
139 | 'group_name': repo_group.group_name, | |
141 | 'group_description': repo_group.group_description, |
|
140 | 'group_description': repo_group.group_description, | |
142 | 'owner': repo_group.user.username, |
|
141 | 'owner': repo_group.user.username, | |
143 | 'group_id': repo_group.group_id, |
|
142 | 'group_id': repo_group.group_id, | |
144 | 'parent_group': ( |
|
143 | 'parent_group': ( | |
145 | repo_group.parent_group.name |
|
144 | repo_group.parent_group.name | |
146 | if repo_group.parent_group else None) |
|
145 | if repo_group.parent_group else None) | |
147 | } |
|
146 | } | |
148 | } |
|
147 | } | |
149 | assert_ok(id_, expected, given=response.body) |
|
148 | assert_ok(id_, expected, given=response.body) | |
150 | return initial_name |
|
149 | return initial_name |
@@ -1,121 +1,120 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.db import User |
|
23 | from rhodecode.model.db import User | |
25 | from rhodecode.model.user import UserModel |
|
24 | from rhodecode.model.user import UserModel | |
26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_ok, assert_error, crash, jsonify) |
|
27 | build_data, api_call, assert_ok, assert_error, crash, jsonify) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestUpdateUser(object): |
|
31 | class TestUpdateUser(object): | |
33 | @pytest.mark.parametrize("name, expected", [ |
|
32 | @pytest.mark.parametrize("name, expected", [ | |
34 | ('firstname', 'new_username'), |
|
33 | ('firstname', 'new_username'), | |
35 | ('lastname', 'new_username'), |
|
34 | ('lastname', 'new_username'), | |
36 | ('email', 'new_username'), |
|
35 | ('email', 'new_username'), | |
37 | ('admin', True), |
|
36 | ('admin', True), | |
38 | ('admin', False), |
|
37 | ('admin', False), | |
39 | ('extern_type', 'ldap'), |
|
38 | ('extern_type', 'ldap'), | |
40 | ('extern_type', None), |
|
39 | ('extern_type', None), | |
41 | ('extern_name', 'test'), |
|
40 | ('extern_name', 'test'), | |
42 | ('extern_name', None), |
|
41 | ('extern_name', None), | |
43 | ('active', False), |
|
42 | ('active', False), | |
44 | ('active', True), |
|
43 | ('active', True), | |
45 | ('password', 'newpass'), |
|
44 | ('password', 'newpass'), | |
46 | ('description', 'CTO 4 Life') |
|
45 | ('description', 'CTO 4 Life') | |
47 | ]) |
|
46 | ]) | |
48 | def test_api_update_user(self, name, expected, user_util): |
|
47 | def test_api_update_user(self, name, expected, user_util): | |
49 | usr = user_util.create_user() |
|
48 | usr = user_util.create_user() | |
50 |
|
49 | |||
51 | kw = {name: expected, 'userid': usr.user_id} |
|
50 | kw = {name: expected, 'userid': usr.user_id} | |
52 | id_, params = build_data(self.apikey, 'update_user', **kw) |
|
51 | id_, params = build_data(self.apikey, 'update_user', **kw) | |
53 | response = api_call(self.app, params) |
|
52 | response = api_call(self.app, params) | |
54 |
|
53 | |||
55 | ret = { |
|
54 | ret = { | |
56 | 'msg': 'updated user ID:%s %s' % (usr.user_id, usr.username), |
|
55 | 'msg': 'updated user ID:%s %s' % (usr.user_id, usr.username), | |
57 | 'user': jsonify( |
|
56 | 'user': jsonify( | |
58 | UserModel() |
|
57 | UserModel() | |
59 | .get_by_username(usr.username) |
|
58 | .get_by_username(usr.username) | |
60 | .get_api_data(include_secrets=True) |
|
59 | .get_api_data(include_secrets=True) | |
61 | ) |
|
60 | ) | |
62 | } |
|
61 | } | |
63 |
|
62 | |||
64 | expected = ret |
|
63 | expected = ret | |
65 | assert_ok(id_, expected, given=response.body) |
|
64 | assert_ok(id_, expected, given=response.body) | |
66 |
|
65 | |||
67 | def test_api_update_user_no_changed_params(self): |
|
66 | def test_api_update_user_no_changed_params(self): | |
68 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
67 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
69 | ret = jsonify(usr.get_api_data(include_secrets=True)) |
|
68 | ret = jsonify(usr.get_api_data(include_secrets=True)) | |
70 | id_, params = build_data( |
|
69 | id_, params = build_data( | |
71 | self.apikey, 'update_user', userid=TEST_USER_ADMIN_LOGIN) |
|
70 | self.apikey, 'update_user', userid=TEST_USER_ADMIN_LOGIN) | |
72 |
|
71 | |||
73 | response = api_call(self.app, params) |
|
72 | response = api_call(self.app, params) | |
74 | ret = { |
|
73 | ret = { | |
75 | 'msg': 'updated user ID:%s %s' % ( |
|
74 | 'msg': 'updated user ID:%s %s' % ( | |
76 | usr.user_id, TEST_USER_ADMIN_LOGIN), |
|
75 | usr.user_id, TEST_USER_ADMIN_LOGIN), | |
77 | 'user': ret |
|
76 | 'user': ret | |
78 | } |
|
77 | } | |
79 | expected = ret |
|
78 | expected = ret | |
80 | expected['user']['last_activity'] = response.json['result']['user'][ |
|
79 | expected['user']['last_activity'] = response.json['result']['user'][ | |
81 | 'last_activity'] |
|
80 | 'last_activity'] | |
82 | assert_ok(id_, expected, given=response.body) |
|
81 | assert_ok(id_, expected, given=response.body) | |
83 |
|
82 | |||
84 | def test_api_update_user_by_user_id(self): |
|
83 | def test_api_update_user_by_user_id(self): | |
85 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
84 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
86 | ret = jsonify(usr.get_api_data(include_secrets=True)) |
|
85 | ret = jsonify(usr.get_api_data(include_secrets=True)) | |
87 | id_, params = build_data( |
|
86 | id_, params = build_data( | |
88 | self.apikey, 'update_user', userid=usr.user_id) |
|
87 | self.apikey, 'update_user', userid=usr.user_id) | |
89 |
|
88 | |||
90 | response = api_call(self.app, params) |
|
89 | response = api_call(self.app, params) | |
91 | ret = { |
|
90 | ret = { | |
92 | 'msg': 'updated user ID:%s %s' % ( |
|
91 | 'msg': 'updated user ID:%s %s' % ( | |
93 | usr.user_id, TEST_USER_ADMIN_LOGIN), |
|
92 | usr.user_id, TEST_USER_ADMIN_LOGIN), | |
94 | 'user': ret |
|
93 | 'user': ret | |
95 | } |
|
94 | } | |
96 | expected = ret |
|
95 | expected = ret | |
97 | expected['user']['last_activity'] = response.json['result']['user'][ |
|
96 | expected['user']['last_activity'] = response.json['result']['user'][ | |
98 | 'last_activity'] |
|
97 | 'last_activity'] | |
99 | assert_ok(id_, expected, given=response.body) |
|
98 | assert_ok(id_, expected, given=response.body) | |
100 |
|
99 | |||
101 | def test_api_update_user_default_user(self): |
|
100 | def test_api_update_user_default_user(self): | |
102 | usr = User.get_default_user() |
|
101 | usr = User.get_default_user() | |
103 | id_, params = build_data( |
|
102 | id_, params = build_data( | |
104 | self.apikey, 'update_user', userid=usr.user_id) |
|
103 | self.apikey, 'update_user', userid=usr.user_id) | |
105 |
|
104 | |||
106 | response = api_call(self.app, params) |
|
105 | response = api_call(self.app, params) | |
107 | expected = 'editing default user is forbidden' |
|
106 | expected = 'editing default user is forbidden' | |
108 | assert_error(id_, expected, given=response.body) |
|
107 | assert_error(id_, expected, given=response.body) | |
109 |
|
108 | |||
110 | @mock.patch.object(UserModel, 'update_user', crash) |
|
109 | @mock.patch.object(UserModel, 'update_user', crash) | |
111 | def test_api_update_user_when_exception_happens(self): |
|
110 | def test_api_update_user_when_exception_happens(self): | |
112 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
111 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
113 | ret = jsonify(usr.get_api_data(include_secrets=True)) |
|
112 | ret = jsonify(usr.get_api_data(include_secrets=True)) | |
114 | id_, params = build_data( |
|
113 | id_, params = build_data( | |
115 | self.apikey, 'update_user', userid=usr.user_id) |
|
114 | self.apikey, 'update_user', userid=usr.user_id) | |
116 |
|
115 | |||
117 | response = api_call(self.app, params) |
|
116 | response = api_call(self.app, params) | |
118 | ret = 'failed to update user `%s`' % (usr.user_id,) |
|
117 | ret = 'failed to update user `%s`' % (usr.user_id,) | |
119 |
|
118 | |||
120 | expected = ret |
|
119 | expected = ret | |
121 | assert_error(id_, expected, given=response.body) |
|
120 | assert_error(id_, expected, given=response.body) |
@@ -1,125 +1,124 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 | import mock |
|
20 | import mock | |
22 | import pytest |
|
21 | import pytest | |
23 |
|
22 | |||
24 | from rhodecode.model.user import UserModel |
|
23 | from rhodecode.model.user import UserModel | |
25 | from rhodecode.model.user_group import UserGroupModel |
|
24 | from rhodecode.model.user_group import UserGroupModel | |
26 | from rhodecode.tests import TEST_USER_ADMIN_EMAIL |
|
25 | from rhodecode.tests import TEST_USER_ADMIN_EMAIL | |
27 | from rhodecode.api.tests.utils import ( |
|
26 | from rhodecode.api.tests.utils import ( | |
28 | build_data, api_call, assert_error, assert_ok, crash, jsonify) |
|
27 | build_data, api_call, assert_error, assert_ok, crash, jsonify) | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | @pytest.mark.usefixtures("testuser_api", "app") | |
32 | class TestUpdateUserGroup(object): |
|
31 | class TestUpdateUserGroup(object): | |
33 | @pytest.mark.parametrize("changing_attr, updates", [ |
|
32 | @pytest.mark.parametrize("changing_attr, updates", [ | |
34 | ('group_name', {'group_name': 'new_group_name'}), |
|
33 | ('group_name', {'group_name': 'new_group_name'}), | |
35 | ('group_name', {'group_name': 'test_group_for_update'}), |
|
34 | ('group_name', {'group_name': 'test_group_for_update'}), | |
36 | # ('owner', {'owner': TEST_USER_REGULAR_LOGIN}), |
|
35 | # ('owner', {'owner': TEST_USER_REGULAR_LOGIN}), | |
37 | ('owner_email', {'owner_email': TEST_USER_ADMIN_EMAIL}), |
|
36 | ('owner_email', {'owner_email': TEST_USER_ADMIN_EMAIL}), | |
38 | ('active', {'active': False}), |
|
37 | ('active', {'active': False}), | |
39 | ('active', {'active': True}), |
|
38 | ('active', {'active': True}), | |
40 | ('sync', {'sync': False}), |
|
39 | ('sync', {'sync': False}), | |
41 | ('sync', {'sync': True}) |
|
40 | ('sync', {'sync': True}) | |
42 | ]) |
|
41 | ]) | |
43 | def test_api_update_user_group(self, changing_attr, updates, user_util): |
|
42 | def test_api_update_user_group(self, changing_attr, updates, user_util): | |
44 | user_group = user_util.create_user_group() |
|
43 | user_group = user_util.create_user_group() | |
45 | group_name = user_group.users_group_name |
|
44 | group_name = user_group.users_group_name | |
46 | expected_api_data = user_group.get_api_data() |
|
45 | expected_api_data = user_group.get_api_data() | |
47 | expected_api_data.update(updates) |
|
46 | expected_api_data.update(updates) | |
48 |
|
47 | |||
49 | id_, params = build_data( |
|
48 | id_, params = build_data( | |
50 | self.apikey, 'update_user_group', usergroupid=group_name, |
|
49 | self.apikey, 'update_user_group', usergroupid=group_name, | |
51 | **updates) |
|
50 | **updates) | |
52 | response = api_call(self.app, params) |
|
51 | response = api_call(self.app, params) | |
53 |
|
52 | |||
54 | # special case for sync |
|
53 | # special case for sync | |
55 | if changing_attr == 'sync' and updates['sync'] is False: |
|
54 | if changing_attr == 'sync' and updates['sync'] is False: | |
56 | expected_api_data['sync'] = None |
|
55 | expected_api_data['sync'] = None | |
57 | elif changing_attr == 'sync' and updates['sync'] is True: |
|
56 | elif changing_attr == 'sync' and updates['sync'] is True: | |
58 | expected_api_data['sync'] = 'manual_api' |
|
57 | expected_api_data['sync'] = 'manual_api' | |
59 |
|
58 | |||
60 | expected = { |
|
59 | expected = { | |
61 | 'msg': 'updated user group ID:%s %s' % ( |
|
60 | 'msg': 'updated user group ID:%s %s' % ( | |
62 | user_group.users_group_id, user_group.users_group_name), |
|
61 | user_group.users_group_id, user_group.users_group_name), | |
63 | 'user_group': jsonify(expected_api_data) |
|
62 | 'user_group': jsonify(expected_api_data) | |
64 | } |
|
63 | } | |
65 | assert_ok(id_, expected, given=response.body) |
|
64 | assert_ok(id_, expected, given=response.body) | |
66 |
|
65 | |||
67 | @pytest.mark.parametrize("changing_attr, updates", [ |
|
66 | @pytest.mark.parametrize("changing_attr, updates", [ | |
68 | # TODO: mikhail: decide if we need to test against the commented params |
|
67 | # TODO: mikhail: decide if we need to test against the commented params | |
69 | # ('group_name', {'group_name': 'new_group_name'}), |
|
68 | # ('group_name', {'group_name': 'new_group_name'}), | |
70 | # ('group_name', {'group_name': 'test_group_for_update'}), |
|
69 | # ('group_name', {'group_name': 'test_group_for_update'}), | |
71 | # ('owner', {'owner': TEST_USER_REGULAR_LOGIN}), |
|
70 | # ('owner', {'owner': TEST_USER_REGULAR_LOGIN}), | |
72 | ('owner_email', {'owner_email': TEST_USER_ADMIN_EMAIL}), |
|
71 | ('owner_email', {'owner_email': TEST_USER_ADMIN_EMAIL}), | |
73 | ('active', {'active': False}), |
|
72 | ('active', {'active': False}), | |
74 | ('active', {'active': True}), |
|
73 | ('active', {'active': True}), | |
75 | ('sync', {'sync': False}), |
|
74 | ('sync', {'sync': False}), | |
76 | ('sync', {'sync': True}) |
|
75 | ('sync', {'sync': True}) | |
77 | ]) |
|
76 | ]) | |
78 | def test_api_update_user_group_regular_user( |
|
77 | def test_api_update_user_group_regular_user( | |
79 | self, changing_attr, updates, user_util): |
|
78 | self, changing_attr, updates, user_util): | |
80 | user_group = user_util.create_user_group() |
|
79 | user_group = user_util.create_user_group() | |
81 | group_name = user_group.users_group_name |
|
80 | group_name = user_group.users_group_name | |
82 | expected_api_data = user_group.get_api_data() |
|
81 | expected_api_data = user_group.get_api_data() | |
83 | expected_api_data.update(updates) |
|
82 | expected_api_data.update(updates) | |
84 |
|
83 | |||
85 | # grant permission to this user |
|
84 | # grant permission to this user | |
86 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
85 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) | |
87 |
|
86 | |||
88 | user_util.grant_user_permission_to_user_group( |
|
87 | user_util.grant_user_permission_to_user_group( | |
89 | user_group, user, 'usergroup.admin') |
|
88 | user_group, user, 'usergroup.admin') | |
90 | id_, params = build_data( |
|
89 | id_, params = build_data( | |
91 | self.apikey_regular, 'update_user_group', |
|
90 | self.apikey_regular, 'update_user_group', | |
92 | usergroupid=group_name, **updates) |
|
91 | usergroupid=group_name, **updates) | |
93 | response = api_call(self.app, params) |
|
92 | response = api_call(self.app, params) | |
94 | # special case for sync |
|
93 | # special case for sync | |
95 | if changing_attr == 'sync' and updates['sync'] is False: |
|
94 | if changing_attr == 'sync' and updates['sync'] is False: | |
96 | expected_api_data['sync'] = None |
|
95 | expected_api_data['sync'] = None | |
97 | elif changing_attr == 'sync' and updates['sync'] is True: |
|
96 | elif changing_attr == 'sync' and updates['sync'] is True: | |
98 | expected_api_data['sync'] = 'manual_api' |
|
97 | expected_api_data['sync'] = 'manual_api' | |
99 |
|
98 | |||
100 | expected = { |
|
99 | expected = { | |
101 | 'msg': 'updated user group ID:%s %s' % ( |
|
100 | 'msg': 'updated user group ID:%s %s' % ( | |
102 | user_group.users_group_id, user_group.users_group_name), |
|
101 | user_group.users_group_id, user_group.users_group_name), | |
103 | 'user_group': jsonify(expected_api_data) |
|
102 | 'user_group': jsonify(expected_api_data) | |
104 | } |
|
103 | } | |
105 | assert_ok(id_, expected, given=response.body) |
|
104 | assert_ok(id_, expected, given=response.body) | |
106 |
|
105 | |||
107 | def test_api_update_user_group_regular_user_no_permission(self, user_util): |
|
106 | def test_api_update_user_group_regular_user_no_permission(self, user_util): | |
108 | user_group = user_util.create_user_group() |
|
107 | user_group = user_util.create_user_group() | |
109 | group_name = user_group.users_group_name |
|
108 | group_name = user_group.users_group_name | |
110 | id_, params = build_data( |
|
109 | id_, params = build_data( | |
111 | self.apikey_regular, 'update_user_group', usergroupid=group_name) |
|
110 | self.apikey_regular, 'update_user_group', usergroupid=group_name) | |
112 | response = api_call(self.app, params) |
|
111 | response = api_call(self.app, params) | |
113 |
|
112 | |||
114 | expected = 'user group `%s` does not exist' % (group_name) |
|
113 | expected = 'user group `%s` does not exist' % (group_name) | |
115 | assert_error(id_, expected, given=response.body) |
|
114 | assert_error(id_, expected, given=response.body) | |
116 |
|
115 | |||
117 | @mock.patch.object(UserGroupModel, 'update', crash) |
|
116 | @mock.patch.object(UserGroupModel, 'update', crash) | |
118 | def test_api_update_user_group_exception_occurred(self, user_util): |
|
117 | def test_api_update_user_group_exception_occurred(self, user_util): | |
119 | user_group = user_util.create_user_group() |
|
118 | user_group = user_util.create_user_group() | |
120 | group_name = user_group.users_group_name |
|
119 | group_name = user_group.users_group_name | |
121 | id_, params = build_data( |
|
120 | id_, params = build_data( | |
122 | self.apikey, 'update_user_group', usergroupid=group_name) |
|
121 | self.apikey, 'update_user_group', usergroupid=group_name) | |
123 | response = api_call(self.app, params) |
|
122 | response = api_call(self.app, params) | |
124 | expected = 'failed to update user group `%s`' % (group_name,) |
|
123 | expected = 'failed to update user group `%s`' % (group_name,) | |
125 | assert_error(id_, expected, given=response.body) |
|
124 | assert_error(id_, expected, given=response.body) |
@@ -1,295 +1,297 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import pytest |
|
21 | import pytest | |
23 | from mock import Mock, patch |
|
22 | from mock import Mock, patch | |
24 |
|
23 | |||
25 | from rhodecode.api import utils |
|
24 | from rhodecode.api import utils | |
26 | from rhodecode.api import JSONRPCError |
|
25 | from rhodecode.api import JSONRPCError | |
27 | from rhodecode.lib.vcs.exceptions import RepositoryError |
|
26 | from rhodecode.lib.vcs.exceptions import RepositoryError | |
28 |
|
27 | |||
29 |
|
28 | |||
30 | class TestGetCommitOrError(object): |
|
29 | class TestGetCommitOrError(object): | |
31 | def setup(self): |
|
30 | ||
|
31 | def setup_method(self): | |||
32 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
32 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' | |
33 |
|
33 | |||
34 | @pytest.mark.parametrize("ref", ['ref', '12345', 'a:b:c:d', 'branch:name']) |
|
34 | @pytest.mark.parametrize("ref", ['ref', '12345', 'a:b:c:d', 'branch:name']) | |
35 | def test_ref_cannot_be_parsed(self, ref): |
|
35 | def test_ref_cannot_be_parsed(self, ref): | |
36 | repo = Mock() |
|
36 | repo = Mock() | |
37 | with pytest.raises(JSONRPCError) as excinfo: |
|
37 | with pytest.raises(JSONRPCError) as excinfo: | |
38 | utils.get_commit_or_error(ref, repo) |
|
38 | utils.get_commit_or_error(ref, repo) | |
39 | expected_message = ( |
|
39 | expected_message = ( | |
40 | 'Ref `{ref}` given in a wrong format. Please check the API' |
|
40 | 'Ref `{ref}` given in a wrong format. Please check the API' | |
41 | ' documentation for more details'.format(ref=ref) |
|
41 | ' documentation for more details'.format(ref=ref) | |
42 | ) |
|
42 | ) | |
43 | assert excinfo.value.message == expected_message |
|
43 | assert excinfo.value.message == expected_message | |
44 |
|
44 | |||
45 | def test_success_with_hash_specified(self): |
|
45 | def test_success_with_hash_specified(self): | |
46 | repo = Mock() |
|
46 | repo = Mock() | |
47 | ref_type = 'branch' |
|
47 | ref_type = 'branch' | |
48 | ref = '{}:master:{}'.format(ref_type, self.commit_hash) |
|
48 | ref = '{}:master:{}'.format(ref_type, self.commit_hash) | |
49 |
|
49 | |||
50 | with patch('rhodecode.api.utils.get_commit_from_ref_name') as get_commit: |
|
50 | with patch('rhodecode.api.utils.get_commit_from_ref_name') as get_commit: | |
51 | result = utils.get_commit_or_error(ref, repo) |
|
51 | result = utils.get_commit_or_error(ref, repo) | |
52 | get_commit.assert_called_once_with( |
|
52 | get_commit.assert_called_once_with( | |
53 | repo, self.commit_hash) |
|
53 | repo, self.commit_hash) | |
54 | assert result == get_commit() |
|
54 | assert result == get_commit() | |
55 |
|
55 | |||
56 | def test_raises_an_error_when_commit_not_found(self): |
|
56 | def test_raises_an_error_when_commit_not_found(self): | |
57 | repo = Mock() |
|
57 | repo = Mock() | |
58 | ref = 'branch:master:{}'.format(self.commit_hash) |
|
58 | ref = 'branch:master:{}'.format(self.commit_hash) | |
59 |
|
59 | |||
60 | with patch('rhodecode.api.utils.get_commit_from_ref_name') as get_commit: |
|
60 | with patch('rhodecode.api.utils.get_commit_from_ref_name') as get_commit: | |
61 | get_commit.side_effect = RepositoryError('Commit not found') |
|
61 | get_commit.side_effect = RepositoryError('Commit not found') | |
62 | with pytest.raises(JSONRPCError) as excinfo: |
|
62 | with pytest.raises(JSONRPCError) as excinfo: | |
63 | utils.get_commit_or_error(ref, repo) |
|
63 | utils.get_commit_or_error(ref, repo) | |
64 | expected_message = 'Ref `{}` does not exist'.format(ref) |
|
64 | expected_message = 'Ref `{}` does not exist'.format(ref) | |
65 | assert excinfo.value.message == expected_message |
|
65 | assert excinfo.value.message == expected_message | |
66 |
|
66 | |||
67 |
|
67 | |||
68 | class TestResolveRefOrError(object): |
|
68 | class TestResolveRefOrError(object): | |
69 | def setup(self): |
|
69 | ||
|
70 | def setup_method(self): | |||
70 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
71 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' | |
71 |
|
72 | |||
72 | def test_success_with_no_hash_specified(self): |
|
73 | def test_success_with_no_hash_specified(self): | |
73 | repo = Mock() |
|
74 | repo = Mock() | |
74 | ref_type = 'branch' |
|
75 | ref_type = 'branch' | |
75 | ref_name = 'master' |
|
76 | ref_name = 'master' | |
76 | ref = '{}:{}'.format(ref_type, ref_name) |
|
77 | ref = '{}:{}'.format(ref_type, ref_name) | |
77 |
|
78 | |||
78 | with patch('rhodecode.api.utils._get_ref_hash') \ |
|
79 | with patch('rhodecode.api.utils._get_ref_hash') \ | |
79 | as _get_ref_hash: |
|
80 | as _get_ref_hash: | |
80 | _get_ref_hash.return_value = self.commit_hash |
|
81 | _get_ref_hash.return_value = self.commit_hash | |
81 | result = utils.resolve_ref_or_error(ref, repo) |
|
82 | result = utils.resolve_ref_or_error(ref, repo) | |
82 | _get_ref_hash.assert_called_once_with(repo, ref_type, ref_name) |
|
83 | _get_ref_hash.assert_called_once_with(repo, ref_type, ref_name) | |
83 | assert result == '{}:{}'.format(ref, self.commit_hash) |
|
84 | assert result == '{}:{}'.format(ref, self.commit_hash) | |
84 |
|
85 | |||
85 | def test_non_supported_refs(self): |
|
86 | def test_non_supported_refs(self): | |
86 | repo = Mock() |
|
87 | repo = Mock() | |
87 | ref = 'bookmark:ref' |
|
88 | ref = 'bookmark:ref' | |
88 | with pytest.raises(JSONRPCError) as excinfo: |
|
89 | with pytest.raises(JSONRPCError) as excinfo: | |
89 | utils.resolve_ref_or_error(ref, repo) |
|
90 | utils.resolve_ref_or_error(ref, repo) | |
90 | expected_message = ( |
|
91 | expected_message = ( | |
91 | 'The specified value:bookmark:`ref` does not exist, or is not allowed.') |
|
92 | 'The specified value:bookmark:`ref` does not exist, or is not allowed.') | |
92 | assert excinfo.value.message == expected_message |
|
93 | assert excinfo.value.message == expected_message | |
93 |
|
94 | |||
94 | def test_branch_is_not_found(self): |
|
95 | def test_branch_is_not_found(self): | |
95 | repo = Mock() |
|
96 | repo = Mock() | |
96 | ref = 'branch:non-existing-one' |
|
97 | ref = 'branch:non-existing-one' | |
97 | with patch('rhodecode.api.utils._get_ref_hash')\ |
|
98 | with patch('rhodecode.api.utils._get_ref_hash')\ | |
98 | as _get_ref_hash: |
|
99 | as _get_ref_hash: | |
99 | _get_ref_hash.side_effect = KeyError() |
|
100 | _get_ref_hash.side_effect = KeyError() | |
100 | with pytest.raises(JSONRPCError) as excinfo: |
|
101 | with pytest.raises(JSONRPCError) as excinfo: | |
101 | utils.resolve_ref_or_error(ref, repo) |
|
102 | utils.resolve_ref_or_error(ref, repo) | |
102 | expected_message = ( |
|
103 | expected_message = ( | |
103 | 'The specified value:branch:`non-existing-one` does not exist, or is not allowed.') |
|
104 | 'The specified value:branch:`non-existing-one` does not exist, or is not allowed.') | |
104 | assert excinfo.value.message == expected_message |
|
105 | assert excinfo.value.message == expected_message | |
105 |
|
106 | |||
106 | def test_bookmark_is_not_found(self): |
|
107 | def test_bookmark_is_not_found(self): | |
107 | repo = Mock() |
|
108 | repo = Mock() | |
108 | ref = 'bookmark:non-existing-one' |
|
109 | ref = 'bookmark:non-existing-one' | |
109 | with patch('rhodecode.api.utils._get_ref_hash')\ |
|
110 | with patch('rhodecode.api.utils._get_ref_hash')\ | |
110 | as _get_ref_hash: |
|
111 | as _get_ref_hash: | |
111 | _get_ref_hash.side_effect = KeyError() |
|
112 | _get_ref_hash.side_effect = KeyError() | |
112 | with pytest.raises(JSONRPCError) as excinfo: |
|
113 | with pytest.raises(JSONRPCError) as excinfo: | |
113 | utils.resolve_ref_or_error(ref, repo) |
|
114 | utils.resolve_ref_or_error(ref, repo) | |
114 | expected_message = ( |
|
115 | expected_message = ( | |
115 | 'The specified value:bookmark:`non-existing-one` does not exist, or is not allowed.') |
|
116 | 'The specified value:bookmark:`non-existing-one` does not exist, or is not allowed.') | |
116 | assert excinfo.value.message == expected_message |
|
117 | assert excinfo.value.message == expected_message | |
117 |
|
118 | |||
118 | @pytest.mark.parametrize("ref", ['ref', '12345', 'a:b:c:d']) |
|
119 | @pytest.mark.parametrize("ref", ['ref', '12345', 'a:b:c:d']) | |
119 | def test_ref_cannot_be_parsed(self, ref): |
|
120 | def test_ref_cannot_be_parsed(self, ref): | |
120 | repo = Mock() |
|
121 | repo = Mock() | |
121 | with pytest.raises(JSONRPCError) as excinfo: |
|
122 | with pytest.raises(JSONRPCError) as excinfo: | |
122 | utils.resolve_ref_or_error(ref, repo) |
|
123 | utils.resolve_ref_or_error(ref, repo) | |
123 | expected_message = ( |
|
124 | expected_message = ( | |
124 | 'Ref `{ref}` given in a wrong format. Please check the API' |
|
125 | 'Ref `{ref}` given in a wrong format. Please check the API' | |
125 | ' documentation for more details'.format(ref=ref) |
|
126 | ' documentation for more details'.format(ref=ref) | |
126 | ) |
|
127 | ) | |
127 | assert excinfo.value.message == expected_message |
|
128 | assert excinfo.value.message == expected_message | |
128 |
|
129 | |||
129 |
|
130 | |||
130 | class TestGetRefHash(object): |
|
131 | class TestGetRefHash(object): | |
131 | def setup(self): |
|
132 | ||
|
133 | def setup_method(self): | |||
132 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
134 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' | |
133 | self.bookmark_name = 'test-bookmark' |
|
135 | self.bookmark_name = 'test-bookmark' | |
134 |
|
136 | |||
135 | @pytest.mark.parametrize("alias, branch_name", [ |
|
137 | @pytest.mark.parametrize("alias, branch_name", [ | |
136 | ("git", "master"), |
|
138 | ("git", "master"), | |
137 | ("hg", "default") |
|
139 | ("hg", "default") | |
138 | ]) |
|
140 | ]) | |
139 | def test_returns_hash_by_branch_name(self, alias, branch_name): |
|
141 | def test_returns_hash_by_branch_name(self, alias, branch_name): | |
140 | with patch('rhodecode.model.db.Repository') as repo: |
|
142 | with patch('rhodecode.model.db.Repository') as repo: | |
141 | repo.scm_instance().alias = alias |
|
143 | repo.scm_instance().alias = alias | |
142 | repo.scm_instance().branches = {branch_name: self.commit_hash} |
|
144 | repo.scm_instance().branches = {branch_name: self.commit_hash} | |
143 | result_hash = utils._get_ref_hash(repo, 'branch', branch_name) |
|
145 | result_hash = utils._get_ref_hash(repo, 'branch', branch_name) | |
144 | assert result_hash == self.commit_hash |
|
146 | assert result_hash == self.commit_hash | |
145 |
|
147 | |||
146 | @pytest.mark.parametrize("alias, branch_name", [ |
|
148 | @pytest.mark.parametrize("alias, branch_name", [ | |
147 | ("git", "master"), |
|
149 | ("git", "master"), | |
148 | ("hg", "default") |
|
150 | ("hg", "default") | |
149 | ]) |
|
151 | ]) | |
150 | def test_raises_error_when_branch_is_not_found(self, alias, branch_name): |
|
152 | def test_raises_error_when_branch_is_not_found(self, alias, branch_name): | |
151 | with patch('rhodecode.model.db.Repository') as repo: |
|
153 | with patch('rhodecode.model.db.Repository') as repo: | |
152 | repo.scm_instance().alias = alias |
|
154 | repo.scm_instance().alias = alias | |
153 | repo.scm_instance().branches = {} |
|
155 | repo.scm_instance().branches = {} | |
154 | with pytest.raises(KeyError): |
|
156 | with pytest.raises(KeyError): | |
155 | utils._get_ref_hash(repo, 'branch', branch_name) |
|
157 | utils._get_ref_hash(repo, 'branch', branch_name) | |
156 |
|
158 | |||
157 | def test_returns_hash_when_bookmark_is_specified_for_hg(self): |
|
159 | def test_returns_hash_when_bookmark_is_specified_for_hg(self): | |
158 | with patch('rhodecode.model.db.Repository') as repo: |
|
160 | with patch('rhodecode.model.db.Repository') as repo: | |
159 | repo.scm_instance().alias = 'hg' |
|
161 | repo.scm_instance().alias = 'hg' | |
160 | repo.scm_instance().bookmarks = { |
|
162 | repo.scm_instance().bookmarks = { | |
161 | self.bookmark_name: self.commit_hash} |
|
163 | self.bookmark_name: self.commit_hash} | |
162 | result_hash = utils._get_ref_hash( |
|
164 | result_hash = utils._get_ref_hash( | |
163 | repo, 'bookmark', self.bookmark_name) |
|
165 | repo, 'bookmark', self.bookmark_name) | |
164 | assert result_hash == self.commit_hash |
|
166 | assert result_hash == self.commit_hash | |
165 |
|
167 | |||
166 | def test_raises_error_when_bookmark_is_not_found_in_hg_repo(self): |
|
168 | def test_raises_error_when_bookmark_is_not_found_in_hg_repo(self): | |
167 | with patch('rhodecode.model.db.Repository') as repo: |
|
169 | with patch('rhodecode.model.db.Repository') as repo: | |
168 | repo.scm_instance().alias = 'hg' |
|
170 | repo.scm_instance().alias = 'hg' | |
169 | repo.scm_instance().bookmarks = {} |
|
171 | repo.scm_instance().bookmarks = {} | |
170 | with pytest.raises(KeyError): |
|
172 | with pytest.raises(KeyError): | |
171 | utils._get_ref_hash(repo, 'bookmark', self.bookmark_name) |
|
173 | utils._get_ref_hash(repo, 'bookmark', self.bookmark_name) | |
172 |
|
174 | |||
173 | def test_raises_error_when_bookmark_is_specified_for_git(self): |
|
175 | def test_raises_error_when_bookmark_is_specified_for_git(self): | |
174 | with patch('rhodecode.model.db.Repository') as repo: |
|
176 | with patch('rhodecode.model.db.Repository') as repo: | |
175 | repo.scm_instance().alias = 'git' |
|
177 | repo.scm_instance().alias = 'git' | |
176 | repo.scm_instance().bookmarks = { |
|
178 | repo.scm_instance().bookmarks = { | |
177 | self.bookmark_name: self.commit_hash} |
|
179 | self.bookmark_name: self.commit_hash} | |
178 | with pytest.raises(ValueError): |
|
180 | with pytest.raises(ValueError): | |
179 | utils._get_ref_hash(repo, 'bookmark', self.bookmark_name) |
|
181 | utils._get_ref_hash(repo, 'bookmark', self.bookmark_name) | |
180 |
|
182 | |||
181 |
|
183 | |||
182 | class TestUserByNameOrError(object): |
|
184 | class TestUserByNameOrError(object): | |
183 | def test_user_found_by_id(self): |
|
185 | def test_user_found_by_id(self): | |
184 | fake_user = Mock(id=123) |
|
186 | fake_user = Mock(id=123) | |
185 |
|
187 | |||
186 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
188 | patcher = patch('rhodecode.model.user.UserModel.get_user') | |
187 | with patcher as get_user: |
|
189 | with patcher as get_user: | |
188 | get_user.return_value = fake_user |
|
190 | get_user.return_value = fake_user | |
189 |
|
191 | |||
190 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
192 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') | |
191 | with patcher as get_by_username: |
|
193 | with patcher as get_by_username: | |
192 | result = utils.get_user_or_error(123) |
|
194 | result = utils.get_user_or_error(123) | |
193 | assert result == fake_user |
|
195 | assert result == fake_user | |
194 |
|
196 | |||
195 | def test_user_not_found_by_id_as_str(self): |
|
197 | def test_user_not_found_by_id_as_str(self): | |
196 | fake_user = Mock(id=123) |
|
198 | fake_user = Mock(id=123) | |
197 |
|
199 | |||
198 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
200 | patcher = patch('rhodecode.model.user.UserModel.get_user') | |
199 | with patcher as get_user: |
|
201 | with patcher as get_user: | |
200 | get_user.return_value = fake_user |
|
202 | get_user.return_value = fake_user | |
201 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
203 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') | |
202 | with patcher as get_by_username: |
|
204 | with patcher as get_by_username: | |
203 | get_by_username.return_value = None |
|
205 | get_by_username.return_value = None | |
204 |
|
206 | |||
205 | with pytest.raises(JSONRPCError): |
|
207 | with pytest.raises(JSONRPCError): | |
206 | utils.get_user_or_error('123') |
|
208 | utils.get_user_or_error('123') | |
207 |
|
209 | |||
208 | def test_user_found_by_name(self): |
|
210 | def test_user_found_by_name(self): | |
209 | fake_user = Mock(id=123) |
|
211 | fake_user = Mock(id=123) | |
210 |
|
212 | |||
211 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
213 | patcher = patch('rhodecode.model.user.UserModel.get_user') | |
212 | with patcher as get_user: |
|
214 | with patcher as get_user: | |
213 | get_user.return_value = None |
|
215 | get_user.return_value = None | |
214 |
|
216 | |||
215 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
217 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') | |
216 | with patcher as get_by_username: |
|
218 | with patcher as get_by_username: | |
217 | get_by_username.return_value = fake_user |
|
219 | get_by_username.return_value = fake_user | |
218 |
|
220 | |||
219 | result = utils.get_user_or_error('test') |
|
221 | result = utils.get_user_or_error('test') | |
220 | assert result == fake_user |
|
222 | assert result == fake_user | |
221 |
|
223 | |||
222 | def test_user_not_found_by_id(self): |
|
224 | def test_user_not_found_by_id(self): | |
223 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
225 | patcher = patch('rhodecode.model.user.UserModel.get_user') | |
224 | with patcher as get_user: |
|
226 | with patcher as get_user: | |
225 | get_user.return_value = None |
|
227 | get_user.return_value = None | |
226 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
228 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') | |
227 | with patcher as get_by_username: |
|
229 | with patcher as get_by_username: | |
228 | get_by_username.return_value = None |
|
230 | get_by_username.return_value = None | |
229 |
|
231 | |||
230 | with pytest.raises(JSONRPCError) as excinfo: |
|
232 | with pytest.raises(JSONRPCError) as excinfo: | |
231 | utils.get_user_or_error(123) |
|
233 | utils.get_user_or_error(123) | |
232 |
|
234 | |||
233 | expected_message = 'user `123` does not exist' |
|
235 | expected_message = 'user `123` does not exist' | |
234 | assert excinfo.value.message == expected_message |
|
236 | assert excinfo.value.message == expected_message | |
235 |
|
237 | |||
236 | def test_user_not_found_by_name(self): |
|
238 | def test_user_not_found_by_name(self): | |
237 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
239 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') | |
238 | with patcher as get_by_username: |
|
240 | with patcher as get_by_username: | |
239 | get_by_username.return_value = None |
|
241 | get_by_username.return_value = None | |
240 | with pytest.raises(JSONRPCError) as excinfo: |
|
242 | with pytest.raises(JSONRPCError) as excinfo: | |
241 | utils.get_user_or_error('test') |
|
243 | utils.get_user_or_error('test') | |
242 |
|
244 | |||
243 | expected_message = 'user `test` does not exist' |
|
245 | expected_message = 'user `test` does not exist' | |
244 | assert excinfo.value.message == expected_message |
|
246 | assert excinfo.value.message == expected_message | |
245 |
|
247 | |||
246 |
|
248 | |||
247 | class TestGetCommitDict(object): |
|
249 | class TestGetCommitDict(object): | |
248 | @pytest.mark.parametrize('filename, expected', [ |
|
250 | @pytest.mark.parametrize('filename, expected', [ | |
249 | (b'sp\xc3\xa4cial', u'sp\xe4cial'), |
|
251 | (b'sp\xc3\xa4cial', u'sp\xe4cial'), | |
250 | (b'sp\xa4cial', u'sp\ufffdcial'), |
|
252 | (b'sp\xa4cial', u'sp\ufffdcial'), | |
251 | ]) |
|
253 | ]) | |
252 | def test_decodes_filenames_to_unicode(self, filename, expected): |
|
254 | def test_decodes_filenames_to_unicode(self, filename, expected): | |
253 | result = utils._get_commit_dict(filename=filename, op='A') |
|
255 | result = utils._get_commit_dict(filename=filename, op='A') | |
254 | assert result['filename'] == expected |
|
256 | assert result['filename'] == expected | |
255 |
|
257 | |||
256 |
|
258 | |||
257 | class TestRepoAccess(object): |
|
259 | class TestRepoAccess(object): | |
258 | def setup_method(self, method): |
|
260 | def setup_method(self, method): | |
259 |
|
261 | |||
260 | self.admin_perm_patch = patch( |
|
262 | self.admin_perm_patch = patch( | |
261 | 'rhodecode.api.utils.HasPermissionAnyApi') |
|
263 | 'rhodecode.api.utils.HasPermissionAnyApi') | |
262 | self.repo_perm_patch = patch( |
|
264 | self.repo_perm_patch = patch( | |
263 | 'rhodecode.api.utils.HasRepoPermissionAnyApi') |
|
265 | 'rhodecode.api.utils.HasRepoPermissionAnyApi') | |
264 |
|
266 | |||
265 | def test_has_superadmin_permission_checks_for_admin(self): |
|
267 | def test_has_superadmin_permission_checks_for_admin(self): | |
266 | admin_mock = Mock() |
|
268 | admin_mock = Mock() | |
267 | with self.admin_perm_patch as amock: |
|
269 | with self.admin_perm_patch as amock: | |
268 | amock.return_value = admin_mock |
|
270 | amock.return_value = admin_mock | |
269 | assert utils.has_superadmin_permission('fake_user') |
|
271 | assert utils.has_superadmin_permission('fake_user') | |
270 | amock.assert_called_once_with('hg.admin') |
|
272 | amock.assert_called_once_with('hg.admin') | |
271 |
|
273 | |||
272 | admin_mock.assert_called_once_with(user='fake_user') |
|
274 | admin_mock.assert_called_once_with(user='fake_user') | |
273 |
|
275 | |||
274 | def test_has_repo_permissions_checks_for_repo_access(self): |
|
276 | def test_has_repo_permissions_checks_for_repo_access(self): | |
275 | repo_mock = Mock() |
|
277 | repo_mock = Mock() | |
276 | fake_repo = Mock() |
|
278 | fake_repo = Mock() | |
277 | with self.repo_perm_patch as rmock: |
|
279 | with self.repo_perm_patch as rmock: | |
278 | rmock.return_value = repo_mock |
|
280 | rmock.return_value = repo_mock | |
279 | assert utils.validate_repo_permissions( |
|
281 | assert utils.validate_repo_permissions( | |
280 | 'fake_user', 'fake_repo_id', fake_repo, |
|
282 | 'fake_user', 'fake_repo_id', fake_repo, | |
281 | ['perm1', 'perm2']) |
|
283 | ['perm1', 'perm2']) | |
282 | rmock.assert_called_once_with(*['perm1', 'perm2']) |
|
284 | rmock.assert_called_once_with(*['perm1', 'perm2']) | |
283 |
|
285 | |||
284 | repo_mock.assert_called_once_with( |
|
286 | repo_mock.assert_called_once_with( | |
285 | user='fake_user', repo_name=fake_repo.repo_name) |
|
287 | user='fake_user', repo_name=fake_repo.repo_name) | |
286 |
|
288 | |||
287 | def test_has_repo_permissions_raises_not_found(self): |
|
289 | def test_has_repo_permissions_raises_not_found(self): | |
288 | repo_mock = Mock(return_value=False) |
|
290 | repo_mock = Mock(return_value=False) | |
289 | fake_repo = Mock() |
|
291 | fake_repo = Mock() | |
290 | with self.repo_perm_patch as rmock: |
|
292 | with self.repo_perm_patch as rmock: | |
291 | rmock.return_value = repo_mock |
|
293 | rmock.return_value = repo_mock | |
292 | with pytest.raises(JSONRPCError) as excinfo: |
|
294 | with pytest.raises(JSONRPCError) as excinfo: | |
293 | utils.validate_repo_permissions( |
|
295 | utils.validate_repo_permissions( | |
294 | 'fake_user', 'fake_repo_id', fake_repo, 'perms') |
|
296 | 'fake_user', 'fake_repo_id', fake_repo, 'perms') | |
295 | assert 'fake_repo_id' in excinfo |
|
297 | assert 'fake_repo_id' in excinfo |
@@ -1,124 +1,123 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
|||
2 |
|
|
1 | ||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
2 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
3 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
4 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
6 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
7 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
8 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
11 | # GNU General Public License for more details. | |
13 | # |
|
12 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
13 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
15 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
16 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
19 | |||
21 |
|
20 | |||
22 | import random |
|
21 | import random | |
23 | import pytest |
|
22 | import pytest | |
24 |
|
23 | |||
25 | from rhodecode.api.utils import get_origin |
|
24 | from rhodecode.api.utils import get_origin | |
26 | from rhodecode.lib.ext_json import json |
|
25 | from rhodecode.lib.ext_json import json | |
27 |
|
26 | |||
28 |
|
27 | |||
29 | def jsonify(obj): |
|
28 | def jsonify(obj): | |
30 | return json.loads(json.dumps(obj)) |
|
29 | return json.loads(json.dumps(obj)) | |
31 |
|
30 | |||
32 |
|
31 | |||
33 | API_URL = '/_admin/api' |
|
32 | API_URL = '/_admin/api' | |
34 |
|
33 | |||
35 |
|
34 | |||
36 | def assert_call_ok(id_, given): |
|
35 | def assert_call_ok(id_, given): | |
37 | expected = jsonify({ |
|
36 | expected = jsonify({ | |
38 | 'id': id_, |
|
37 | 'id': id_, | |
39 | 'error': None, |
|
38 | 'error': None, | |
40 | 'result': None |
|
39 | 'result': None | |
41 | }) |
|
40 | }) | |
42 | given = json.loads(given) |
|
41 | given = json.loads(given) | |
43 |
|
42 | |||
44 | assert expected['id'] == given['id'] |
|
43 | assert expected['id'] == given['id'] | |
45 | assert expected['error'] == given['error'] |
|
44 | assert expected['error'] == given['error'] | |
46 | return given['result'] |
|
45 | return given['result'] | |
47 |
|
46 | |||
48 |
|
47 | |||
49 | def assert_ok(id_, expected, given): |
|
48 | def assert_ok(id_, expected, given): | |
50 | given = json.loads(given) |
|
49 | given = json.loads(given) | |
51 | if given.get('error'): |
|
50 | if given.get('error'): | |
52 | err = given['error'] |
|
51 | err = given['error'] | |
53 |
pytest.fail( |
|
52 | pytest.fail(f"Unexpected ERROR in expected success response: `{err}`") | |
54 |
|
53 | |||
55 | expected = jsonify({ |
|
54 | expected = jsonify({ | |
56 | 'id': id_, |
|
55 | 'id': id_, | |
57 | 'error': None, |
|
56 | 'error': None, | |
58 | 'result': expected |
|
57 | 'result': expected | |
59 | }) |
|
58 | }) | |
60 |
|
59 | |||
61 | assert expected == given |
|
60 | assert expected == given | |
62 |
|
61 | |||
63 |
|
62 | |||
64 | def assert_error(id_, expected, given): |
|
63 | def assert_error(id_, expected, given): | |
65 | expected = jsonify({ |
|
64 | expected = jsonify({ | |
66 | 'id': id_, |
|
65 | 'id': id_, | |
67 | 'error': expected, |
|
66 | 'error': expected, | |
68 | 'result': None |
|
67 | 'result': None | |
69 | }) |
|
68 | }) | |
70 | given = json.loads(given) |
|
69 | given = json.loads(given) | |
71 | assert expected == given |
|
70 | assert expected == given | |
72 |
|
71 | |||
73 |
|
72 | |||
74 | def build_data(apikey, method, **kw): |
|
73 | def build_data(apikey, method, **kw): | |
75 | """ |
|
74 | """ | |
76 | Builds API data with given random ID |
|
75 | Builds API data with given random ID | |
77 | """ |
|
76 | """ | |
78 | random_id = random.randrange(1, 9999) |
|
77 | random_id = random.randrange(1, 9999) | |
79 | return random_id, json.dumps({ |
|
78 | return random_id, json.dumps({ | |
80 | "id": random_id, |
|
79 | "id": random_id, | |
81 | "api_key": apikey, |
|
80 | "api_key": apikey, | |
82 | "method": method, |
|
81 | "method": method, | |
83 | "args": kw |
|
82 | "args": kw | |
84 | }) |
|
83 | }) | |
85 |
|
84 | |||
86 |
|
85 | |||
87 | def api_call(app, params, status=None): |
|
86 | def api_call(app, params, status=None): | |
88 | response = app.post( |
|
87 | response = app.post( | |
89 | API_URL, content_type='application/json', params=params, status=status, |
|
88 | API_URL, content_type='application/json', params=params, status=status, | |
90 | headers=[('Content-Type', 'application/json')]) |
|
89 | headers=[('Content-Type', 'application/json')]) | |
91 | return response |
|
90 | return response | |
92 |
|
91 | |||
93 |
|
92 | |||
94 | def crash(*args, **kwargs): |
|
93 | def crash(*args, **kwargs): | |
95 | raise Exception('Total Crash !') |
|
94 | raise Exception('Total Crash !') | |
96 |
|
95 | |||
97 |
|
96 | |||
98 | def expected_permissions(object_with_permissions): |
|
97 | def expected_permissions(object_with_permissions): | |
99 | """ |
|
98 | """ | |
100 | Returns the expected permissions structure for the given object. |
|
99 | Returns the expected permissions structure for the given object. | |
101 |
|
100 | |||
102 | The object is expected to be a `Repository`, `RepositoryGroup`, |
|
101 | The object is expected to be a `Repository`, `RepositoryGroup`, | |
103 | or `UserGroup`. They all implement the same permission handling |
|
102 | or `UserGroup`. They all implement the same permission handling | |
104 | API. |
|
103 | API. | |
105 | """ |
|
104 | """ | |
106 | permissions = [] |
|
105 | permissions = [] | |
107 | for _user in object_with_permissions.permissions(): |
|
106 | for _user in object_with_permissions.permissions(): | |
108 | user_data = { |
|
107 | user_data = { | |
109 | 'name': _user.username, |
|
108 | 'name': _user.username, | |
110 | 'permission': _user.permission, |
|
109 | 'permission': _user.permission, | |
111 | 'origin': get_origin(_user), |
|
110 | 'origin': get_origin(_user), | |
112 | 'type': "user", |
|
111 | 'type': "user", | |
113 | } |
|
112 | } | |
114 | permissions.append(user_data) |
|
113 | permissions.append(user_data) | |
115 |
|
114 | |||
116 | for _user_group in object_with_permissions.permission_user_groups(): |
|
115 | for _user_group in object_with_permissions.permission_user_groups(): | |
117 | user_group_data = { |
|
116 | user_group_data = { | |
118 | 'name': _user_group.users_group_name, |
|
117 | 'name': _user_group.users_group_name, | |
119 | 'permission': _user_group.permission, |
|
118 | 'permission': _user_group.permission, | |
120 | 'origin': get_origin(_user_group), |
|
119 | 'origin': get_origin(_user_group), | |
121 | 'type': "user_group", |
|
120 | 'type': "user_group", | |
122 | } |
|
121 | } | |
123 | permissions.append(user_group_data) |
|
122 | permissions.append(user_group_data) | |
124 | return permissions |
|
123 | return permissions |
@@ -1,152 +1,152 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | ||
2 |
|
2 | |||
3 | # Copyright (C) 2011-2020 RhodeCode GmbH |
|
3 | # Copyright (C) 2011-2020 RhodeCode GmbH | |
4 | # |
|
4 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
5 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
7 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
8 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
12 | # GNU General Public License for more details. | |
13 | # |
|
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
16 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 |
|
21 | |||
22 | import logging |
|
22 | import logging | |
23 |
|
23 | |||
24 | from rhodecode.api import jsonrpc_method |
|
24 | from rhodecode.api import jsonrpc_method | |
25 | from rhodecode.api.exc import JSONRPCValidationError, JSONRPCForbidden |
|
25 | from rhodecode.api.exc import JSONRPCValidationError, JSONRPCForbidden | |
26 | from rhodecode.api.utils import Optional, has_superadmin_permission |
|
26 | from rhodecode.api.utils import Optional, has_superadmin_permission | |
27 | from rhodecode.lib.index import searcher_from_config |
|
27 | from rhodecode.lib.index import searcher_from_config | |
28 | from rhodecode.lib.user_log_filter import user_log_filter |
|
28 | from rhodecode.lib.user_log_filter import user_log_filter | |
29 | from rhodecode.model import validation_schema |
|
29 | from rhodecode.model import validation_schema | |
30 | from rhodecode.model.db import joinedload, UserLog |
|
30 | from rhodecode.model.db import joinedload, UserLog | |
31 | from rhodecode.model.validation_schema.schemas import search_schema |
|
31 | from rhodecode.model.validation_schema.schemas import search_schema | |
32 |
|
32 | |||
33 | log = logging.getLogger(__name__) |
|
33 | log = logging.getLogger(__name__) | |
34 |
|
34 | |||
35 |
|
35 | |||
36 | @jsonrpc_method() |
|
36 | @jsonrpc_method() | |
37 | def search(request, apiuser, search_query, search_type, page_limit=Optional(10), |
|
37 | def search(request, apiuser, search_query, search_type, page_limit=Optional(10), | |
38 | page=Optional(1), search_sort=Optional('desc:date'), |
|
38 | page=Optional(1), search_sort=Optional('desc:date'), | |
39 | repo_name=Optional(None), repo_group_name=Optional(None)): |
|
39 | repo_name=Optional(None), repo_group_name=Optional(None)): | |
40 | """ |
|
40 | """ | |
41 | Fetch Full Text Search results using API. |
|
41 | Fetch Full Text Search results using API. | |
42 |
|
42 | |||
43 | :param apiuser: This is filled automatically from the |authtoken|. |
|
43 | :param apiuser: This is filled automatically from the |authtoken|. | |
44 | :type apiuser: AuthUser |
|
44 | :type apiuser: AuthUser | |
45 | :param search_query: Search query. |
|
45 | :param search_query: Search query. | |
46 | :type search_query: str |
|
46 | :type search_query: str | |
47 | :param search_type: Search type. The following are valid options: |
|
47 | :param search_type: Search type. The following are valid options: | |
48 | * commit |
|
48 | * commit | |
49 | * content |
|
49 | * content | |
50 | * path |
|
50 | * path | |
51 | :type search_type: str |
|
51 | :type search_type: str | |
52 | :param page_limit: Page item limit, from 1 to 500. Default 10 items. |
|
52 | :param page_limit: Page item limit, from 1 to 500. Default 10 items. | |
53 | :type page_limit: Optional(int) |
|
53 | :type page_limit: Optional(int) | |
54 | :param page: Page number. Default first page. |
|
54 | :param page: Page number. Default first page. | |
55 | :type page: Optional(int) |
|
55 | :type page: Optional(int) | |
56 | :param search_sort: Search sort order.Must start with asc: or desc: Default desc:date. |
|
56 | :param search_sort: Search sort order.Must start with asc: or desc: Default desc:date. | |
57 | The following are valid options: |
|
57 | The following are valid options: | |
58 | * asc|desc:message.raw |
|
58 | * asc|desc:message.raw | |
59 | * asc|desc:date |
|
59 | * asc|desc:date | |
60 | * asc|desc:author.email.raw |
|
60 | * asc|desc:author.email.raw | |
61 | * asc|desc:message.raw |
|
61 | * asc|desc:message.raw | |
62 | * newfirst (old legacy equal to desc:date) |
|
62 | * newfirst (old legacy equal to desc:date) | |
63 | * oldfirst (old legacy equal to asc:date) |
|
63 | * oldfirst (old legacy equal to asc:date) | |
64 |
|
64 | |||
65 | :type search_sort: Optional(str) |
|
65 | :type search_sort: Optional(str) | |
66 | :param repo_name: Filter by one repo. Default is all. |
|
66 | :param repo_name: Filter by one repo. Default is all. | |
67 | :type repo_name: Optional(str) |
|
67 | :type repo_name: Optional(str) | |
68 | :param repo_group_name: Filter by one repo group. Default is all. |
|
68 | :param repo_group_name: Filter by one repo group. Default is all. | |
69 | :type repo_group_name: Optional(str) |
|
69 | :type repo_group_name: Optional(str) | |
70 | """ |
|
70 | """ | |
71 |
|
71 | |||
72 | data = {'execution_time': ''} |
|
72 | data = {'execution_time': ''} | |
73 | repo_name = Optional.extract(repo_name) |
|
73 | repo_name = Optional.extract(repo_name) | |
74 | repo_group_name = Optional.extract(repo_group_name) |
|
74 | repo_group_name = Optional.extract(repo_group_name) | |
75 |
|
75 | |||
76 | schema = search_schema.SearchParamsSchema() |
|
76 | schema = search_schema.SearchParamsSchema() | |
77 |
|
77 | |||
78 | try: |
|
78 | try: | |
79 | search_params = schema.deserialize( |
|
79 | search_params = schema.deserialize( | |
80 | dict(search_query=search_query, |
|
80 | dict(search_query=search_query, | |
81 | search_type=search_type, |
|
81 | search_type=search_type, | |
82 | search_sort=Optional.extract(search_sort), |
|
82 | search_sort=Optional.extract(search_sort), | |
83 | page_limit=Optional.extract(page_limit), |
|
83 | page_limit=Optional.extract(page_limit), | |
84 | requested_page=Optional.extract(page)) |
|
84 | requested_page=Optional.extract(page)) | |
85 | ) |
|
85 | ) | |
86 | except validation_schema.Invalid as err: |
|
86 | except validation_schema.Invalid as err: | |
87 | raise JSONRPCValidationError(colander_exc=err) |
|
87 | raise JSONRPCValidationError(colander_exc=err) | |
88 |
|
88 | |||
89 | search_query = search_params.get('search_query') |
|
89 | search_query = search_params.get('search_query') | |
90 | search_type = search_params.get('search_type') |
|
90 | search_type = search_params.get('search_type') | |
91 | search_sort = search_params.get('search_sort') |
|
91 | search_sort = search_params.get('search_sort') | |
92 |
|
92 | |||
93 | if search_params.get('search_query'): |
|
93 | if search_params.get('search_query'): | |
94 | page_limit = search_params['page_limit'] |
|
94 | page_limit = search_params['page_limit'] | |
95 | requested_page = search_params['requested_page'] |
|
95 | requested_page = search_params['requested_page'] | |
96 |
|
96 | |||
97 | searcher = searcher_from_config(request.registry.settings) |
|
97 | searcher = searcher_from_config(request.registry.settings) | |
98 |
|
98 | |||
99 | try: |
|
99 | try: | |
100 | search_result = searcher.search( |
|
100 | search_result = searcher.search( | |
101 | search_query, search_type, apiuser, repo_name, repo_group_name, |
|
101 | search_query, search_type, apiuser, repo_name, repo_group_name, | |
102 | requested_page=requested_page, page_limit=page_limit, sort=search_sort) |
|
102 | requested_page=requested_page, page_limit=page_limit, sort=search_sort) | |
103 |
|
103 | |||
104 | data.update(dict( |
|
104 | data.update(dict( | |
105 | results=list(search_result['results']), page=requested_page, |
|
105 | results=list(search_result['results']), page=requested_page, | |
106 | item_count=search_result['count'], |
|
106 | item_count=search_result['count'], | |
107 | items_per_page=page_limit)) |
|
107 | items_per_page=page_limit)) | |
108 | finally: |
|
108 | finally: | |
109 | searcher.cleanup() |
|
109 | searcher.cleanup() | |
110 |
|
110 | |||
111 | if not search_result['error']: |
|
111 | if not search_result['error']: | |
112 | data['execution_time'] = '%s results (%.4f seconds)' % ( |
|
112 | data['execution_time'] = '%s results (%.4f seconds)' % ( | |
113 | search_result['count'], |
|
113 | search_result['count'], | |
114 | search_result['runtime']) |
|
114 | search_result['runtime']) | |
115 | else: |
|
115 | else: | |
116 | node = schema['search_query'] |
|
116 | node = schema['search_query'] | |
117 | raise JSONRPCValidationError( |
|
117 | raise JSONRPCValidationError( | |
118 | colander_exc=validation_schema.Invalid(node, search_result['error'])) |
|
118 | colander_exc=validation_schema.Invalid(node, search_result['error'])) | |
119 |
|
119 | |||
120 | return data |
|
120 | return data | |
121 |
|
121 | |||
122 |
|
122 | |||
123 | @jsonrpc_method() |
|
123 | @jsonrpc_method() | |
124 | def get_audit_logs(request, apiuser, query): |
|
124 | def get_audit_logs(request, apiuser, query): | |
125 | """ |
|
125 | """ | |
126 | return full audit logs based on the query. |
|
126 | return full audit logs based on the query. | |
127 |
|
127 | |||
128 | Please see `example query in admin > settings > audit logs` for examples |
|
128 | Please see `example query in admin > settings > audit logs` for examples | |
129 |
|
129 | |||
130 | :param apiuser: This is filled automatically from the |authtoken|. |
|
130 | :param apiuser: This is filled automatically from the |authtoken|. | |
131 | :type apiuser: AuthUser |
|
131 | :type apiuser: AuthUser | |
132 | :param query: filter query, example: action:repo.artifact.add date:[20200401 TO 20200601]" |
|
132 | :param query: filter query, example: action:repo.artifact.add date:[20200401 TO 20200601]" | |
133 | :type query: str |
|
133 | :type query: str | |
134 | """ |
|
134 | """ | |
135 |
|
135 | |||
136 | if not has_superadmin_permission(apiuser): |
|
136 | if not has_superadmin_permission(apiuser): | |
137 | raise JSONRPCForbidden() |
|
137 | raise JSONRPCForbidden() | |
138 |
|
138 | |||
139 | filter_term = query |
|
139 | filter_term = query | |
140 | ret = [] |
|
140 | ret = [] | |
141 |
|
141 | |||
142 | # show all user actions |
|
142 | # show all user actions | |
143 | user_log = UserLog.query() \ |
|
143 | user_log = UserLog.query() \ | |
144 | .options(joinedload(UserLog.user)) \ |
|
144 | .options(joinedload(UserLog.user)) \ | |
145 | .options(joinedload(UserLog.repository)) \ |
|
145 | .options(joinedload(UserLog.repository)) \ | |
146 | .order_by(UserLog.action_date.desc()) |
|
146 | .order_by(UserLog.action_date.desc()) | |
147 |
|
147 | |||
148 | audit_log = user_log_filter(user_log, filter_term) |
|
148 | audit_log = user_log_filter(user_log, filter_term) | |
149 |
|
149 | |||
150 | for entry in audit_log: |
|
150 | for entry in audit_log: | |
151 | ret.append(entry) |
|
151 | ret.append(entry) | |
152 | return ret |
|
152 | return ret |
General Comments 0
You need to be logged in to leave comments.
Login now