##// END OF EJS Templates
api: make all tests for API pass
super-admin -
r5048:a6860778 default
parent child Browse files
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': None,
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_regular,
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".format(comment_id, 1)
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_unicode(expected_name))
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_unicode(expected_name))
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 u'filename1.txt': {'content': u'hello world'},
57 b'filename1.txt': {'content': b'hello world'},
58 u'filename1Ä….txt': {'content': u'hello worldÄ™'}
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:u'note'>",
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.utils2 import safe_unicode
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_unicode(
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_unicode(
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_unicode(
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_unicode(
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 <type 'int'> instead"
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 <type 'int'> instead"
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 sorted(result['result']) == sorted(expected_list)
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._asdict()
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._asdict()
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(u"Unexpected ERROR in success response: {}".format(err))
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