##// END OF EJS Templates
mail: use faster detection of email misconfiguration. This should be done at earliest...
marcink -
r3077:6903e671 default
parent child Browse files
Show More
@@ -1,307 +1,308 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2018 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 RhodeCode task modules, containing all task that suppose to be run
22 RhodeCode task modules, containing all task that suppose to be run
23 by celery daemon
23 by celery daemon
24 """
24 """
25
25
26 import os
26 import os
27 import time
27 import time
28
28
29 import rhodecode
29 import rhodecode
30 from rhodecode.lib import audit_logger
30 from rhodecode.lib import audit_logger
31 from rhodecode.lib.celerylib import get_logger, async_task, RequestContextTask
31 from rhodecode.lib.celerylib import get_logger, async_task, RequestContextTask
32 from rhodecode.lib.hooks_base import log_create_repository
32 from rhodecode.lib.hooks_base import log_create_repository
33 from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer
33 from rhodecode.lib.rcmail.smtp_mailer import SmtpMailer
34 from rhodecode.lib.utils2 import safe_int, str2bool
34 from rhodecode.lib.utils2 import safe_int, str2bool
35 from rhodecode.model.db import Session, IntegrityError, Repository, User, true
35 from rhodecode.model.db import Session, IntegrityError, Repository, User, true
36
36
37
37
38 @async_task(ignore_result=True, base=RequestContextTask)
38 @async_task(ignore_result=True, base=RequestContextTask)
39 def send_email(recipients, subject, body='', html_body='', email_config=None):
39 def send_email(recipients, subject, body='', html_body='', email_config=None):
40 """
40 """
41 Sends an email with defined parameters from the .ini files.
41 Sends an email with defined parameters from the .ini files.
42
42
43 :param recipients: list of recipients, it this is empty the defined email
43 :param recipients: list of recipients, it this is empty the defined email
44 address from field 'email_to' is used instead
44 address from field 'email_to' is used instead
45 :param subject: subject of the mail
45 :param subject: subject of the mail
46 :param body: body of the mail
46 :param body: body of the mail
47 :param html_body: html version of body
47 :param html_body: html version of body
48 """
48 """
49 log = get_logger(send_email)
49 log = get_logger(send_email)
50
50
51 email_config = email_config or rhodecode.CONFIG
51 email_config = email_config or rhodecode.CONFIG
52
53 mail_server = email_config.get('smtp_server') or None
54 if mail_server is None:
55 log.error("SMTP server information missing. Sending email failed. "
56 "Make sure that `smtp_server` variable is configured "
57 "inside the .ini file")
58 return False
59
52 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
60 subject = "%s %s" % (email_config.get('email_prefix', ''), subject)
53 if not recipients:
61 if not recipients:
54 # if recipients are not defined we send to email_config + all admins
62 # if recipients are not defined we send to email_config + all admins
55 admins = []
63 admins = []
56 for u in User.query().filter(User.admin == true()).all():
64 for u in User.query().filter(User.admin == true()).all():
57 if u.email:
65 if u.email:
58 admins.append(u.email)
66 admins.append(u.email)
59 recipients = []
67 recipients = []
60 config_email = email_config.get('email_to')
68 config_email = email_config.get('email_to')
61 if config_email:
69 if config_email:
62 recipients += [config_email]
70 recipients += [config_email]
63 recipients += admins
71 recipients += admins
64
72
65 mail_server = email_config.get('smtp_server') or None
66 if mail_server is None:
67 log.error("SMTP server information missing. Sending email failed. "
68 "Make sure that `smtp_server` variable is configured "
69 "inside the .ini file")
70 return False
71
72 mail_from = email_config.get('app_email_from', 'RhodeCode')
73 mail_from = email_config.get('app_email_from', 'RhodeCode')
73 user = email_config.get('smtp_username')
74 user = email_config.get('smtp_username')
74 passwd = email_config.get('smtp_password')
75 passwd = email_config.get('smtp_password')
75 mail_port = email_config.get('smtp_port')
76 mail_port = email_config.get('smtp_port')
76 tls = str2bool(email_config.get('smtp_use_tls'))
77 tls = str2bool(email_config.get('smtp_use_tls'))
77 ssl = str2bool(email_config.get('smtp_use_ssl'))
78 ssl = str2bool(email_config.get('smtp_use_ssl'))
78 debug = str2bool(email_config.get('debug'))
79 debug = str2bool(email_config.get('debug'))
79 smtp_auth = email_config.get('smtp_auth')
80 smtp_auth = email_config.get('smtp_auth')
80
81
81 try:
82 try:
82 m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
83 m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
83 mail_port, ssl, tls, debug=debug)
84 mail_port, ssl, tls, debug=debug)
84 m.send(recipients, subject, body, html_body)
85 m.send(recipients, subject, body, html_body)
85 except Exception:
86 except Exception:
86 log.exception('Mail sending failed')
87 log.exception('Mail sending failed')
87 return False
88 return False
88 return True
89 return True
89
90
90
91
91 @async_task(ignore_result=True, base=RequestContextTask)
92 @async_task(ignore_result=True, base=RequestContextTask)
92 def create_repo(form_data, cur_user):
93 def create_repo(form_data, cur_user):
93 from rhodecode.model.repo import RepoModel
94 from rhodecode.model.repo import RepoModel
94 from rhodecode.model.user import UserModel
95 from rhodecode.model.user import UserModel
95 from rhodecode.model.settings import SettingsModel
96 from rhodecode.model.settings import SettingsModel
96
97
97 log = get_logger(create_repo)
98 log = get_logger(create_repo)
98
99
99 cur_user = UserModel()._get_user(cur_user)
100 cur_user = UserModel()._get_user(cur_user)
100 owner = cur_user
101 owner = cur_user
101
102
102 repo_name = form_data['repo_name']
103 repo_name = form_data['repo_name']
103 repo_name_full = form_data['repo_name_full']
104 repo_name_full = form_data['repo_name_full']
104 repo_type = form_data['repo_type']
105 repo_type = form_data['repo_type']
105 description = form_data['repo_description']
106 description = form_data['repo_description']
106 private = form_data['repo_private']
107 private = form_data['repo_private']
107 clone_uri = form_data.get('clone_uri')
108 clone_uri = form_data.get('clone_uri')
108 repo_group = safe_int(form_data['repo_group'])
109 repo_group = safe_int(form_data['repo_group'])
109 landing_rev = form_data['repo_landing_rev']
110 landing_rev = form_data['repo_landing_rev']
110 copy_fork_permissions = form_data.get('copy_permissions')
111 copy_fork_permissions = form_data.get('copy_permissions')
111 copy_group_permissions = form_data.get('repo_copy_permissions')
112 copy_group_permissions = form_data.get('repo_copy_permissions')
112 fork_of = form_data.get('fork_parent_id')
113 fork_of = form_data.get('fork_parent_id')
113 state = form_data.get('repo_state', Repository.STATE_PENDING)
114 state = form_data.get('repo_state', Repository.STATE_PENDING)
114
115
115 # repo creation defaults, private and repo_type are filled in form
116 # repo creation defaults, private and repo_type are filled in form
116 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
117 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
117 enable_statistics = form_data.get(
118 enable_statistics = form_data.get(
118 'enable_statistics', defs.get('repo_enable_statistics'))
119 'enable_statistics', defs.get('repo_enable_statistics'))
119 enable_locking = form_data.get(
120 enable_locking = form_data.get(
120 'enable_locking', defs.get('repo_enable_locking'))
121 'enable_locking', defs.get('repo_enable_locking'))
121 enable_downloads = form_data.get(
122 enable_downloads = form_data.get(
122 'enable_downloads', defs.get('repo_enable_downloads'))
123 'enable_downloads', defs.get('repo_enable_downloads'))
123
124
124 try:
125 try:
125 repo = RepoModel()._create_repo(
126 repo = RepoModel()._create_repo(
126 repo_name=repo_name_full,
127 repo_name=repo_name_full,
127 repo_type=repo_type,
128 repo_type=repo_type,
128 description=description,
129 description=description,
129 owner=owner,
130 owner=owner,
130 private=private,
131 private=private,
131 clone_uri=clone_uri,
132 clone_uri=clone_uri,
132 repo_group=repo_group,
133 repo_group=repo_group,
133 landing_rev=landing_rev,
134 landing_rev=landing_rev,
134 fork_of=fork_of,
135 fork_of=fork_of,
135 copy_fork_permissions=copy_fork_permissions,
136 copy_fork_permissions=copy_fork_permissions,
136 copy_group_permissions=copy_group_permissions,
137 copy_group_permissions=copy_group_permissions,
137 enable_statistics=enable_statistics,
138 enable_statistics=enable_statistics,
138 enable_locking=enable_locking,
139 enable_locking=enable_locking,
139 enable_downloads=enable_downloads,
140 enable_downloads=enable_downloads,
140 state=state
141 state=state
141 )
142 )
142 Session().commit()
143 Session().commit()
143
144
144 # now create this repo on Filesystem
145 # now create this repo on Filesystem
145 RepoModel()._create_filesystem_repo(
146 RepoModel()._create_filesystem_repo(
146 repo_name=repo_name,
147 repo_name=repo_name,
147 repo_type=repo_type,
148 repo_type=repo_type,
148 repo_group=RepoModel()._get_repo_group(repo_group),
149 repo_group=RepoModel()._get_repo_group(repo_group),
149 clone_uri=clone_uri,
150 clone_uri=clone_uri,
150 )
151 )
151 repo = Repository.get_by_repo_name(repo_name_full)
152 repo = Repository.get_by_repo_name(repo_name_full)
152 log_create_repository(created_by=owner.username, **repo.get_dict())
153 log_create_repository(created_by=owner.username, **repo.get_dict())
153
154
154 # update repo commit caches initially
155 # update repo commit caches initially
155 repo.update_commit_cache()
156 repo.update_commit_cache()
156
157
157 # set new created state
158 # set new created state
158 repo.set_state(Repository.STATE_CREATED)
159 repo.set_state(Repository.STATE_CREATED)
159 repo_id = repo.repo_id
160 repo_id = repo.repo_id
160 repo_data = repo.get_api_data()
161 repo_data = repo.get_api_data()
161
162
162 audit_logger.store(
163 audit_logger.store(
163 'repo.create', action_data={'data': repo_data},
164 'repo.create', action_data={'data': repo_data},
164 user=cur_user,
165 user=cur_user,
165 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
166 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
166
167
167 Session().commit()
168 Session().commit()
168 except Exception as e:
169 except Exception as e:
169 log.warning('Exception occurred when creating repository, '
170 log.warning('Exception occurred when creating repository, '
170 'doing cleanup...', exc_info=True)
171 'doing cleanup...', exc_info=True)
171 if isinstance(e, IntegrityError):
172 if isinstance(e, IntegrityError):
172 Session().rollback()
173 Session().rollback()
173
174
174 # rollback things manually !
175 # rollback things manually !
175 repo = Repository.get_by_repo_name(repo_name_full)
176 repo = Repository.get_by_repo_name(repo_name_full)
176 if repo:
177 if repo:
177 Repository.delete(repo.repo_id)
178 Repository.delete(repo.repo_id)
178 Session().commit()
179 Session().commit()
179 RepoModel()._delete_filesystem_repo(repo)
180 RepoModel()._delete_filesystem_repo(repo)
180 log.info('Cleanup of repo %s finished', repo_name_full)
181 log.info('Cleanup of repo %s finished', repo_name_full)
181 raise
182 raise
182
183
183 return True
184 return True
184
185
185
186
186 @async_task(ignore_result=True, base=RequestContextTask)
187 @async_task(ignore_result=True, base=RequestContextTask)
187 def create_repo_fork(form_data, cur_user):
188 def create_repo_fork(form_data, cur_user):
188 """
189 """
189 Creates a fork of repository using internal VCS methods
190 Creates a fork of repository using internal VCS methods
190 """
191 """
191 from rhodecode.model.repo import RepoModel
192 from rhodecode.model.repo import RepoModel
192 from rhodecode.model.user import UserModel
193 from rhodecode.model.user import UserModel
193
194
194 log = get_logger(create_repo_fork)
195 log = get_logger(create_repo_fork)
195
196
196 cur_user = UserModel()._get_user(cur_user)
197 cur_user = UserModel()._get_user(cur_user)
197 owner = cur_user
198 owner = cur_user
198
199
199 repo_name = form_data['repo_name'] # fork in this case
200 repo_name = form_data['repo_name'] # fork in this case
200 repo_name_full = form_data['repo_name_full']
201 repo_name_full = form_data['repo_name_full']
201 repo_type = form_data['repo_type']
202 repo_type = form_data['repo_type']
202 description = form_data['description']
203 description = form_data['description']
203 private = form_data['private']
204 private = form_data['private']
204 clone_uri = form_data.get('clone_uri')
205 clone_uri = form_data.get('clone_uri')
205 repo_group = safe_int(form_data['repo_group'])
206 repo_group = safe_int(form_data['repo_group'])
206 landing_rev = form_data['landing_rev']
207 landing_rev = form_data['landing_rev']
207 copy_fork_permissions = form_data.get('copy_permissions')
208 copy_fork_permissions = form_data.get('copy_permissions')
208 fork_id = safe_int(form_data.get('fork_parent_id'))
209 fork_id = safe_int(form_data.get('fork_parent_id'))
209
210
210 try:
211 try:
211 fork_of = RepoModel()._get_repo(fork_id)
212 fork_of = RepoModel()._get_repo(fork_id)
212 RepoModel()._create_repo(
213 RepoModel()._create_repo(
213 repo_name=repo_name_full,
214 repo_name=repo_name_full,
214 repo_type=repo_type,
215 repo_type=repo_type,
215 description=description,
216 description=description,
216 owner=owner,
217 owner=owner,
217 private=private,
218 private=private,
218 clone_uri=clone_uri,
219 clone_uri=clone_uri,
219 repo_group=repo_group,
220 repo_group=repo_group,
220 landing_rev=landing_rev,
221 landing_rev=landing_rev,
221 fork_of=fork_of,
222 fork_of=fork_of,
222 copy_fork_permissions=copy_fork_permissions
223 copy_fork_permissions=copy_fork_permissions
223 )
224 )
224
225
225 Session().commit()
226 Session().commit()
226
227
227 base_path = Repository.base_path()
228 base_path = Repository.base_path()
228 source_repo_path = os.path.join(base_path, fork_of.repo_name)
229 source_repo_path = os.path.join(base_path, fork_of.repo_name)
229
230
230 # now create this repo on Filesystem
231 # now create this repo on Filesystem
231 RepoModel()._create_filesystem_repo(
232 RepoModel()._create_filesystem_repo(
232 repo_name=repo_name,
233 repo_name=repo_name,
233 repo_type=repo_type,
234 repo_type=repo_type,
234 repo_group=RepoModel()._get_repo_group(repo_group),
235 repo_group=RepoModel()._get_repo_group(repo_group),
235 clone_uri=source_repo_path,
236 clone_uri=source_repo_path,
236 )
237 )
237 repo = Repository.get_by_repo_name(repo_name_full)
238 repo = Repository.get_by_repo_name(repo_name_full)
238 log_create_repository(created_by=owner.username, **repo.get_dict())
239 log_create_repository(created_by=owner.username, **repo.get_dict())
239
240
240 # update repo commit caches initially
241 # update repo commit caches initially
241 config = repo._config
242 config = repo._config
242 config.set('extensions', 'largefiles', '')
243 config.set('extensions', 'largefiles', '')
243 repo.update_commit_cache(config=config)
244 repo.update_commit_cache(config=config)
244
245
245 # set new created state
246 # set new created state
246 repo.set_state(Repository.STATE_CREATED)
247 repo.set_state(Repository.STATE_CREATED)
247
248
248 repo_id = repo.repo_id
249 repo_id = repo.repo_id
249 repo_data = repo.get_api_data()
250 repo_data = repo.get_api_data()
250 audit_logger.store(
251 audit_logger.store(
251 'repo.fork', action_data={'data': repo_data},
252 'repo.fork', action_data={'data': repo_data},
252 user=cur_user,
253 user=cur_user,
253 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
254 repo=audit_logger.RepoWrap(repo_name=repo_name, repo_id=repo_id))
254
255
255 Session().commit()
256 Session().commit()
256 except Exception as e:
257 except Exception as e:
257 log.warning('Exception occurred when forking repository, '
258 log.warning('Exception occurred when forking repository, '
258 'doing cleanup...', exc_info=True)
259 'doing cleanup...', exc_info=True)
259 if isinstance(e, IntegrityError):
260 if isinstance(e, IntegrityError):
260 Session().rollback()
261 Session().rollback()
261
262
262 # rollback things manually !
263 # rollback things manually !
263 repo = Repository.get_by_repo_name(repo_name_full)
264 repo = Repository.get_by_repo_name(repo_name_full)
264 if repo:
265 if repo:
265 Repository.delete(repo.repo_id)
266 Repository.delete(repo.repo_id)
266 Session().commit()
267 Session().commit()
267 RepoModel()._delete_filesystem_repo(repo)
268 RepoModel()._delete_filesystem_repo(repo)
268 log.info('Cleanup of repo %s finished', repo_name_full)
269 log.info('Cleanup of repo %s finished', repo_name_full)
269 raise
270 raise
270
271
271 return True
272 return True
272
273
273
274
274 @async_task(ignore_result=True)
275 @async_task(ignore_result=True)
275 def repo_maintenance(repoid):
276 def repo_maintenance(repoid):
276 from rhodecode.lib import repo_maintenance as repo_maintenance_lib
277 from rhodecode.lib import repo_maintenance as repo_maintenance_lib
277 log = get_logger(repo_maintenance)
278 log = get_logger(repo_maintenance)
278 repo = Repository.get_by_id_or_repo_name(repoid)
279 repo = Repository.get_by_id_or_repo_name(repoid)
279 if repo:
280 if repo:
280 maintenance = repo_maintenance_lib.RepoMaintenance()
281 maintenance = repo_maintenance_lib.RepoMaintenance()
281 tasks = maintenance.get_tasks_for_repo(repo)
282 tasks = maintenance.get_tasks_for_repo(repo)
282 log.debug('Executing %s tasks on repo `%s`', tasks, repoid)
283 log.debug('Executing %s tasks on repo `%s`', tasks, repoid)
283 executed_types = maintenance.execute(repo)
284 executed_types = maintenance.execute(repo)
284 log.debug('Got execution results %s', executed_types)
285 log.debug('Got execution results %s', executed_types)
285 else:
286 else:
286 log.debug('Repo `%s` not found or without a clone_url', repoid)
287 log.debug('Repo `%s` not found or without a clone_url', repoid)
287
288
288
289
289 @async_task(ignore_result=True)
290 @async_task(ignore_result=True)
290 def check_for_update():
291 def check_for_update():
291 from rhodecode.model.update import UpdateModel
292 from rhodecode.model.update import UpdateModel
292 update_url = UpdateModel().get_update_url()
293 update_url = UpdateModel().get_update_url()
293 cur_ver = rhodecode.__version__
294 cur_ver = rhodecode.__version__
294
295
295 try:
296 try:
296 data = UpdateModel().get_update_data(update_url)
297 data = UpdateModel().get_update_data(update_url)
297 latest = data['versions'][0]
298 latest = data['versions'][0]
298 UpdateModel().store_version(latest['version'])
299 UpdateModel().store_version(latest['version'])
299 except Exception:
300 except Exception:
300 pass
301 pass
301
302
302
303
303 @async_task(ignore_result=False)
304 @async_task(ignore_result=False)
304 def beat_check(*args, **kwargs):
305 def beat_check(*args, **kwargs):
305 log = get_logger(beat_check)
306 log = get_logger(beat_check)
306 log.info('Got args: %r and kwargs %r', args, kwargs)
307 log.info('Got args: %r and kwargs %r', args, kwargs)
307 return time.time()
308 return time.time()
General Comments 0
You need to be logged in to leave comments. Login now