##// END OF EJS Templates
events: added new fts build event
milka -
r4583:d1df4ac3 stable
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,80 +1,83 b''
1 1 # Copyright (C) 2016-2020 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 import logging
20 20 from pyramid.threadlocal import get_current_registry
21 21 from rhodecode.events.base import RhodeCodeIntegrationEvent
22 22
23
24 log = logging.getLogger(__name__)
25
26
27 def trigger(event, registry=None):
28 """
29 Helper method to send an event. This wraps the pyramid logic to send an
30 event.
31 """
32 # For the first step we are using pyramids thread locals here. If the
33 # event mechanism works out as a good solution we should think about
34 # passing the registry as an argument to get rid of it.
35 event_name = event.__class__
36 log.debug('event %s sent for execution', event_name)
37 registry = registry or get_current_registry()
38 registry.notify(event)
39 log.debug('event %s triggered using registry %s', event_name, registry)
40
41 # Send the events to integrations directly
42 from rhodecode.integrations import integrations_event_handler
43 if isinstance(event, RhodeCodeIntegrationEvent):
44 integrations_event_handler(event)
45
23 from rhodecode.events.base import ( # pragma: no cover
24 FtsBuild
25 )
46 26
47 27 from rhodecode.events.user import ( # pragma: no cover
48 28 UserPreCreate,
49 29 UserPostCreate,
50 30 UserPreUpdate,
51 31 UserRegistered,
52 32 UserPermissionsChange,
53 33 )
54 34
55 35 from rhodecode.events.repo import ( # pragma: no cover
56 36 RepoEvent,
57 37 RepoCommitCommentEvent, RepoCommitCommentEditEvent,
58 38 RepoPreCreateEvent, RepoCreateEvent,
59 39 RepoPreDeleteEvent, RepoDeleteEvent,
60 40 RepoPrePushEvent, RepoPushEvent,
61 41 RepoPrePullEvent, RepoPullEvent,
62 42 )
63 43
64 44 from rhodecode.events.repo_group import ( # pragma: no cover
65 45 RepoGroupEvent,
66 46 RepoGroupCreateEvent,
67 47 RepoGroupUpdateEvent,
68 48 RepoGroupDeleteEvent,
69 49 )
70 50
71 51 from rhodecode.events.pullrequest import ( # pragma: no cover
72 52 PullRequestEvent,
73 53 PullRequestCreateEvent,
74 54 PullRequestUpdateEvent,
75 55 PullRequestCommentEvent,
76 56 PullRequestCommentEditEvent,
77 57 PullRequestReviewEvent,
78 58 PullRequestMergeEvent,
79 59 PullRequestCloseEvent,
80 60 )
61
62
63 log = logging.getLogger(__name__)
64
65
66 def trigger(event, registry=None):
67 """
68 Helper method to send an event. This wraps the pyramid logic to send an
69 event.
70 """
71 # For the first step we are using pyramids thread locals here. If the
72 # event mechanism works out as a good solution we should think about
73 # passing the registry as an argument to get rid of it.
74 event_name = event.__class__
75 log.debug('event %s sent for execution', event_name)
76 registry = registry or get_current_registry()
77 registry.notify(event)
78 log.debug('event %s triggered using registry %s', event_name, registry)
79
80 # Send the events to integrations directly
81 from rhodecode.integrations import integrations_event_handler
82 if isinstance(event, RhodeCodeIntegrationEvent):
83 integrations_event_handler(event)
@@ -1,122 +1,130 b''
1 1 # Copyright (C) 2016-2020 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18 import logging
19 19 import datetime
20 20
21 21 from zope.cachedescriptors.property import Lazy as LazyProperty
22 22 from pyramid.threadlocal import get_current_request
23 23
24 24 from rhodecode.lib.utils2 import AttributeDict
25 25
26 26
27 27 # this is a user object to be used for events caused by the system (eg. shell)
28 28 SYSTEM_USER = AttributeDict(dict(
29 29 username='__SYSTEM__',
30 30 user_id='__SYSTEM_ID__'
31 31 ))
32 32
33 33 log = logging.getLogger(__name__)
34 34
35 35
36 36 class RhodecodeEvent(object):
37 37 """
38 38 Base event class for all RhodeCode events
39 39 """
40 40 name = "RhodeCodeEvent"
41 41 no_url_set = '<no server_url available>'
42 42
43 43 def __init__(self, request=None):
44 44 self._request = request
45 45 self.utc_timestamp = datetime.datetime.utcnow()
46 46
47 47 def __repr__(self):
48 48 return '<%s:(%s)>' % (self.__class__.__name__, self.name)
49 49
50 50 def get_request(self):
51 51 if self._request:
52 52 return self._request
53 53 return get_current_request()
54 54
55 55 @LazyProperty
56 56 def request(self):
57 57 return self.get_request()
58 58
59 59 @property
60 60 def auth_user(self):
61 61 if not self.request:
62 62 return
63 63
64 64 user = getattr(self.request, 'user', None)
65 65 if user:
66 66 return user
67 67
68 68 api_user = getattr(self.request, 'rpc_user', None)
69 69 if api_user:
70 70 return api_user
71 71
72 72 @property
73 73 def actor(self):
74 74 auth_user = self.auth_user
75 75 if auth_user:
76 76 instance = auth_user.get_instance()
77 77 if not instance:
78 78 return AttributeDict(dict(
79 79 username=auth_user.username,
80 80 user_id=auth_user.user_id,
81 81 ))
82 82 return instance
83 83
84 84 return SYSTEM_USER
85 85
86 86 @property
87 87 def actor_ip(self):
88 88 auth_user = self.auth_user
89 89 if auth_user:
90 90 return auth_user.ip_addr
91 91 return '<no ip available>'
92 92
93 93 @property
94 94 def server_url(self):
95 95 if self.request:
96 96 try:
97 97 return self.request.route_url('home')
98 98 except Exception:
99 99 log.exception('Failed to fetch URL for server')
100 100 return self.no_url_set
101 101
102 102 return self.no_url_set
103 103
104 104 def as_dict(self):
105 105 data = {
106 106 'name': self.name,
107 107 'utc_timestamp': self.utc_timestamp,
108 108 'actor_ip': self.actor_ip,
109 109 'actor': {
110 110 'username': self.actor.username,
111 111 'user_id': self.actor.user_id
112 112 },
113 113 'server_url': self.server_url
114 114 }
115 115 return data
116 116
117 117
118 118 class RhodeCodeIntegrationEvent(RhodecodeEvent):
119 119 """
120 120 Special subclass for Integration events
121 121 """
122 122 description = ''
123
124
125 class FtsBuild(RhodecodeEvent):
126 """
127 This event will be triggered when FTS Build is triggered
128 """
129 name = 'fts-build'
130 display_name = 'Start FTS Build'
@@ -1,379 +1,379 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2020 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 RhodeCode task modules, containing all task that suppose to be run
23 23 by celery daemon
24 24 """
25 25
26 26 import os
27 27 import time
28 28
29 29 from pyramid import compat
30 30 from pyramid_mailer.mailer import Mailer
31 31 from pyramid_mailer.message import Message
32 32 from email.utils import formatdate
33 33
34 34 import rhodecode
35 35 from rhodecode.lib import audit_logger
36 36 from rhodecode.lib.celerylib import get_logger, async_task, RequestContextTask
37 37 from rhodecode.lib import hooks_base
38 38 from rhodecode.lib.utils2 import safe_int, str2bool
39 39 from rhodecode.model.db import (
40 40 Session, IntegrityError, true, Repository, RepoGroup, User)
41 41
42 42
43 43 @async_task(ignore_result=True, base=RequestContextTask)
44 44 def send_email(recipients, subject, body='', html_body='', email_config=None,
45 45 extra_headers=None):
46 46 """
47 47 Sends an email with defined parameters from the .ini files.
48 48
49 49 :param recipients: list of recipients, it this is empty the defined email
50 50 address from field 'email_to' is used instead
51 51 :param subject: subject of the mail
52 52 :param body: body of the mail
53 53 :param html_body: html version of body
54 54 :param email_config: specify custom configuration for mailer
55 55 :param extra_headers: specify custom headers
56 56 """
57 57 log = get_logger(send_email)
58 58
59 59 email_config = email_config or rhodecode.CONFIG
60 60
61 61 mail_server = email_config.get('smtp_server') or None
62 62 if mail_server is None:
63 63 log.error("SMTP server information missing. Sending email failed. "
64 64 "Make sure that `smtp_server` variable is configured "
65 65 "inside the .ini file")
66 66 return False
67 67
68 68 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
69 69
70 70 if recipients:
71 71 if isinstance(recipients, compat.string_types):
72 72 recipients = recipients.split(',')
73 73 else:
74 74 # if recipients are not defined we send to email_config + all admins
75 75 admins = []
76 76 for u in User.query().filter(User.admin == true()).all():
77 77 if u.email:
78 78 admins.append(u.email)
79 79 recipients = []
80 80 config_email = email_config.get('email_to')
81 81 if config_email:
82 82 recipients += [config_email]
83 83 recipients += admins
84 84
85 85 # translate our LEGACY config into the one that pyramid_mailer supports
86 86 email_conf = dict(
87 87 host=mail_server,
88 88 port=email_config.get('smtp_port', 25),
89 89 username=email_config.get('smtp_username'),
90 90 password=email_config.get('smtp_password'),
91 91
92 92 tls=str2bool(email_config.get('smtp_use_tls')),
93 93 ssl=str2bool(email_config.get('smtp_use_ssl')),
94 94
95 95 # SSL key file
96 96 # keyfile='',
97 97
98 98 # SSL certificate file
99 99 # certfile='',
100 100
101 101 # Location of maildir
102 102 # queue_path='',
103 103
104 104 default_sender=email_config.get('app_email_from', 'RhodeCode'),
105 105
106 106 debug=str2bool(email_config.get('smtp_debug')),
107 107 # /usr/sbin/sendmail Sendmail executable
108 108 # sendmail_app='',
109 109
110 110 # {sendmail_app} -t -i -f {sender} Template for sendmail execution
111 111 # sendmail_template='',
112 112 )
113 113
114 114 if extra_headers is None:
115 115 extra_headers = {}
116 116
117 117 extra_headers.setdefault('Date', formatdate(time.time()))
118 118
119 119 if 'thread_ids' in extra_headers:
120 120 thread_ids = extra_headers.pop('thread_ids')
121 121 extra_headers['References'] = ' '.join('<{}>'.format(t) for t in thread_ids)
122 122
123 123 try:
124 124 mailer = Mailer(**email_conf)
125 125
126 126 message = Message(subject=subject,
127 127 sender=email_conf['default_sender'],
128 128 recipients=recipients,
129 129 body=body, html=html_body,
130 130 extra_headers=extra_headers)
131 131 mailer.send_immediately(message)
132 132
133 133 except Exception:
134 134 log.exception('Mail sending failed')
135 135 return False
136 136 return True
137 137
138 138
139 139 @async_task(ignore_result=True, base=RequestContextTask)
140 140 def create_repo(form_data, cur_user):
141 141 from rhodecode.model.repo import RepoModel
142 142 from rhodecode.model.user import UserModel
143 143 from rhodecode.model.scm import ScmModel
144 144 from rhodecode.model.settings import SettingsModel
145 145
146 146 log = get_logger(create_repo)
147 147
148 148 cur_user = UserModel()._get_user(cur_user)
149 149 owner = cur_user
150 150
151 151 repo_name = form_data['repo_name']
152 152 repo_name_full = form_data['repo_name_full']
153 153 repo_type = form_data['repo_type']
154 154 description = form_data['repo_description']
155 155 private = form_data['repo_private']
156 156 clone_uri = form_data.get('clone_uri')
157 157 repo_group = safe_int(form_data['repo_group'])
158 158 copy_fork_permissions = form_data.get('copy_permissions')
159 159 copy_group_permissions = form_data.get('repo_copy_permissions')
160 160 fork_of = form_data.get('fork_parent_id')
161 161 state = form_data.get('repo_state', Repository.STATE_PENDING)
162 162
163 163 # repo creation defaults, private and repo_type are filled in form
164 164 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
165 165 enable_statistics = form_data.get(
166 166 'enable_statistics', defs.get('repo_enable_statistics'))
167 167 enable_locking = form_data.get(
168 168 'enable_locking', defs.get('repo_enable_locking'))
169 169 enable_downloads = form_data.get(
170 170 'enable_downloads', defs.get('repo_enable_downloads'))
171 171
172 172 # set landing rev based on default branches for SCM
173 173 landing_ref, _label = ScmModel.backend_landing_ref(repo_type)
174 174
175 175 try:
176 176 RepoModel()._create_repo(
177 177 repo_name=repo_name_full,
178 178 repo_type=repo_type,
179 179 description=description,
180 180 owner=owner,
181 181 private=private,
182 182 clone_uri=clone_uri,
183 183 repo_group=repo_group,
184 184 landing_rev=landing_ref,
185 185 fork_of=fork_of,
186 186 copy_fork_permissions=copy_fork_permissions,
187 187 copy_group_permissions=copy_group_permissions,
188 188 enable_statistics=enable_statistics,
189 189 enable_locking=enable_locking,
190 190 enable_downloads=enable_downloads,
191 191 state=state
192 192 )
193 193 Session().commit()
194 194
195 195 # now create this repo on Filesystem
196 196 RepoModel()._create_filesystem_repo(
197 197 repo_name=repo_name,
198 198 repo_type=repo_type,
199 199 repo_group=RepoModel()._get_repo_group(repo_group),
200 200 clone_uri=clone_uri,
201 201 )
202 202 repo = Repository.get_by_repo_name(repo_name_full)
203 203 hooks_base.create_repository(created_by=owner.username, **repo.get_dict())
204 204
205 205 # update repo commit caches initially
206 206 repo.update_commit_cache()
207 207
208 208 # set new created state
209 209 repo.set_state(Repository.STATE_CREATED)
210 210 repo_id = repo.repo_id
211 211 repo_data = repo.get_api_data()
212 212
213 213 audit_logger.store(
214 214 'repo.create', action_data={'data': repo_data},
215 215 user=cur_user,
216 216 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
217 217
218 218 Session().commit()
219 219 except Exception as e:
220 220 log.warning('Exception occurred when creating repository, '
221 221 'doing cleanup...', exc_info=True)
222 222 if isinstance(e, IntegrityError):
223 223 Session().rollback()
224 224
225 225 # rollback things manually !
226 226 repo = Repository.get_by_repo_name(repo_name_full)
227 227 if repo:
228 228 Repository.delete(repo.repo_id)
229 229 Session().commit()
230 230 RepoModel()._delete_filesystem_repo(repo)
231 231 log.info('Cleanup of repo %s finished', repo_name_full)
232 232 raise
233 233
234 234 return True
235 235
236 236
237 237 @async_task(ignore_result=True, base=RequestContextTask)
238 238 def create_repo_fork(form_data, cur_user):
239 239 """
240 240 Creates a fork of repository using internal VCS methods
241 241 """
242 242 from rhodecode.model.repo import RepoModel
243 243 from rhodecode.model.user import UserModel
244 244
245 245 log = get_logger(create_repo_fork)
246 246
247 247 cur_user = UserModel()._get_user(cur_user)
248 248 owner = cur_user
249 249
250 250 repo_name = form_data['repo_name'] # fork in this case
251 251 repo_name_full = form_data['repo_name_full']
252 252 repo_type = form_data['repo_type']
253 253 description = form_data['description']
254 254 private = form_data['private']
255 255 clone_uri = form_data.get('clone_uri')
256 256 repo_group = safe_int(form_data['repo_group'])
257 257 landing_ref = form_data['landing_rev']
258 258 copy_fork_permissions = form_data.get('copy_permissions')
259 259 fork_id = safe_int(form_data.get('fork_parent_id'))
260 260
261 261 try:
262 262 fork_of = RepoModel()._get_repo(fork_id)
263 263 RepoModel()._create_repo(
264 264 repo_name=repo_name_full,
265 265 repo_type=repo_type,
266 266 description=description,
267 267 owner=owner,
268 268 private=private,
269 269 clone_uri=clone_uri,
270 270 repo_group=repo_group,
271 271 landing_rev=landing_ref,
272 272 fork_of=fork_of,
273 273 copy_fork_permissions=copy_fork_permissions
274 274 )
275 275
276 276 Session().commit()
277 277
278 278 base_path = Repository.base_path()
279 279 source_repo_path = os.path.join(base_path, fork_of.repo_name)
280 280
281 281 # now create this repo on Filesystem
282 282 RepoModel()._create_filesystem_repo(
283 283 repo_name=repo_name,
284 284 repo_type=repo_type,
285 285 repo_group=RepoModel()._get_repo_group(repo_group),
286 286 clone_uri=source_repo_path,
287 287 )
288 288 repo = Repository.get_by_repo_name(repo_name_full)
289 289 hooks_base.create_repository(created_by=owner.username, **repo.get_dict())
290 290
291 291 # update repo commit caches initially
292 292 config = repo._config
293 293 config.set('extensions', 'largefiles', '')
294 294 repo.update_commit_cache(config=config)
295 295
296 296 # set new created state
297 297 repo.set_state(Repository.STATE_CREATED)
298 298
299 299 repo_id = repo.repo_id
300 300 repo_data = repo.get_api_data()
301 301 audit_logger.store(
302 302 'repo.fork', action_data={'data': repo_data},
303 303 user=cur_user,
304 304 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
305 305
306 306 Session().commit()
307 307 except Exception as e:
308 308 log.warning('Exception occurred when forking repository, '
309 309 'doing cleanup...', exc_info=True)
310 310 if isinstance(e, IntegrityError):
311 311 Session().rollback()
312 312
313 313 # rollback things manually !
314 314 repo = Repository.get_by_repo_name(repo_name_full)
315 315 if repo:
316 316 Repository.delete(repo.repo_id)
317 317 Session().commit()
318 318 RepoModel()._delete_filesystem_repo(repo)
319 319 log.info('Cleanup of repo %s finished', repo_name_full)
320 320 raise
321 321
322 322 return True
323 323
324 324
325 325 @async_task(ignore_result=True)
326 326 def repo_maintenance(repoid):
327 327 from rhodecode.lib import repo_maintenance as repo_maintenance_lib
328 328 log = get_logger(repo_maintenance)
329 329 repo = Repository.get_by_id_or_repo_name(repoid)
330 330 if repo:
331 331 maintenance = repo_maintenance_lib.RepoMaintenance()
332 332 tasks = maintenance.get_tasks_for_repo(repo)
333 333 log.debug('Executing %s tasks on repo `%s`', tasks, repoid)
334 334 executed_types = maintenance.execute(repo)
335 335 log.debug('Got execution results %s', executed_types)
336 336 else:
337 337 log.debug('Repo `%s` not found or without a clone_url', repoid)
338 338
339 339
340 340 @async_task(ignore_result=True)
341 341 def check_for_update():
342 342 from rhodecode.model.update import UpdateModel
343 343 update_url = UpdateModel().get_update_url()
344 344 cur_ver = rhodecode.__version__
345 345
346 346 try:
347 347 data = UpdateModel().get_update_data(update_url)
348 348 latest = data['versions'][0]
349 349 UpdateModel().store_version(latest['version'])
350 350 except Exception:
351 351 pass
352 352
353 353
354 354 @async_task(ignore_result=False)
355 355 def beat_check(*args, **kwargs):
356 356 log = get_logger(beat_check)
357 log.info('Got args: %r and kwargs %r', args, kwargs)
357 log.info('%r: Got args: %r and kwargs %r', beat_check, args, kwargs)
358 358 return time.time()
359 359
360 360
361 361 @async_task(ignore_result=True)
362 362 def sync_last_update(*args, **kwargs):
363 363
364 364 skip_repos = kwargs.get('skip_repos')
365 365 if not skip_repos:
366 366 repos = Repository.query() \
367 367 .order_by(Repository.group_id.asc())
368 368
369 369 for repo in repos:
370 370 repo.update_commit_cache()
371 371
372 372 skip_groups = kwargs.get('skip_groups')
373 373 if not skip_groups:
374 374 repo_groups = RepoGroup.query() \
375 375 .filter(RepoGroup.group_parent_id == None)
376 376
377 377 for root_gr in repo_groups:
378 378 for repo_gr in reversed(root_gr.recursive_groups()):
379 379 repo_gr.update_commit_cache()
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,152 +1,160 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2020 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import os
22 22 import re
23 23 import logging
24 24
25 25
26 26 import ipaddress
27 27 import colander
28 28
29 29 from rhodecode.translation import _
30 30 from rhodecode.lib.utils2 import glob2re, safe_unicode
31 31 from rhodecode.lib.ext_json import json
32 32
33 33 log = logging.getLogger(__name__)
34 34
35 35
36 36 def ip_addr_validator(node, value):
37 37 try:
38 38 # this raises an ValueError if address is not IpV4 or IpV6
39 39 ipaddress.ip_network(safe_unicode(value), strict=False)
40 40 except ValueError:
41 41 msg = _(u'Please enter a valid IPv4 or IpV6 address')
42 42 raise colander.Invalid(node, msg)
43 43
44 44
45 45 class IpAddrValidator(object):
46 46 def __init__(self, strict=True):
47 47 self.strict = strict
48 48
49 49 def __call__(self, node, value):
50 50 try:
51 51 # this raises an ValueError if address is not IpV4 or IpV6
52 52 ipaddress.ip_network(safe_unicode(value), strict=self.strict)
53 53 except ValueError:
54 54 msg = _(u'Please enter a valid IPv4 or IpV6 address')
55 55 raise colander.Invalid(node, msg)
56 56
57 57
58 58 def glob_validator(node, value):
59 59 try:
60 60 re.compile('^' + glob2re(value) + '$')
61 61 except Exception:
62 62 msg = _(u'Invalid glob pattern')
63 63 raise colander.Invalid(node, msg)
64 64
65 65
66 66 def valid_name_validator(node, value):
67 67 from rhodecode.model.validation_schema import types
68 68 if value is types.RootLocation:
69 69 return
70 70
71 71 msg = _('Name must start with a letter or number. Got `{}`').format(value)
72 72 if not re.match(r'^[a-zA-z0-9]{1,}', value):
73 73 raise colander.Invalid(node, msg)
74 74
75 75
76 76 class InvalidCloneUrl(Exception):
77 77 allowed_prefixes = ()
78 78
79 79
80 80 def url_validator(url, repo_type, config):
81 81 from rhodecode.lib.vcs.backends.hg import MercurialRepository
82 82 from rhodecode.lib.vcs.backends.git import GitRepository
83 83 from rhodecode.lib.vcs.backends.svn import SubversionRepository
84 84
85 85 if repo_type == 'hg':
86 86 allowed_prefixes = ('http', 'svn+http', 'git+http')
87 87
88 88 if 'http' in url[:4]:
89 89 # initially check if it's at least the proper URL
90 90 # or does it pass basic auth
91 91
92 92 return MercurialRepository.check_url(url, config)
93 93 elif 'svn+http' in url[:8]: # svn->hg import
94 94 SubversionRepository.check_url(url, config)
95 95 elif 'git+http' in url[:8]: # git->hg import
96 96 raise NotImplementedError()
97 97 else:
98 98 exc = InvalidCloneUrl('Clone from URI %s not allowed. '
99 99 'Allowed url must start with one of %s'
100 100 % (url, ','.join(allowed_prefixes)))
101 101 exc.allowed_prefixes = allowed_prefixes
102 102 raise exc
103 103
104 104 elif repo_type == 'git':
105 105 allowed_prefixes = ('http', 'svn+http', 'hg+http')
106 106 if 'http' in url[:4]:
107 107 # initially check if it's at least the proper URL
108 108 # or does it pass basic auth
109 109 return GitRepository.check_url(url, config)
110 110 elif 'svn+http' in url[:8]: # svn->git import
111 111 raise NotImplementedError()
112 112 elif 'hg+http' in url[:8]: # hg->git import
113 113 raise NotImplementedError()
114 114 else:
115 115 exc = InvalidCloneUrl('Clone from URI %s not allowed. '
116 116 'Allowed url must start with one of %s'
117 117 % (url, ','.join(allowed_prefixes)))
118 118 exc.allowed_prefixes = allowed_prefixes
119 119 raise exc
120 120 elif repo_type == 'svn':
121 121 # no validation for SVN yet
122 122 return
123 123
124 124 raise InvalidCloneUrl('Invalid repo type specified: `{}`'.format(repo_type))
125 125
126 126
127 127 class CloneUriValidator(object):
128 128 def __init__(self, repo_type):
129 129 self.repo_type = repo_type
130 130
131 131 def __call__(self, node, value):
132 132
133 133 from rhodecode.lib.utils import make_db_config
134 134 try:
135 135 config = make_db_config(clear_session=False)
136 136 url_validator(value, self.repo_type, config)
137 137 except InvalidCloneUrl as e:
138 138 log.warning(e)
139 139 raise colander.Invalid(node, e.message)
140 140 except Exception:
141 141 log.exception('Url validation failed')
142 142 msg = _(u'invalid clone url for {repo_type} repository').format(
143 143 repo_type=self.repo_type)
144 144 raise colander.Invalid(node, msg)
145 145
146 146
147 147 def json_validator(node, value):
148 148 try:
149 149 json.loads(value)
150 except (Exception,):
150 except (Exception,) as e:
151 151 msg = _(u'Please enter a valid json object')
152 152 raise colander.Invalid(node, msg)
153
154
155 def json_validator_with_exc(node, value):
156 try:
157 json.loads(value)
158 except (Exception,) as e:
159 msg = _(u'Please enter a valid json object: `{}`'.format(e))
160 raise colander.Invalid(node, msg)
General Comments 0
You need to be logged in to leave comments. Login now