##// END OF EJS Templates
use the GET parent_group param to pre-fill the group choice
marcink -
r3233:11b005b2 beta
parent child Browse files
Show More
@@ -1,480 +1,490 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.repos
3 rhodecode.controllers.admin.repos
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Repositories controller for RhodeCode
6 Repositories controller for RhodeCode
7
7
8 :created_on: Apr 7, 2010
8 :created_on: Apr 7, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 from formencode import htmlfill
29 from formencode import htmlfill
30
30
31 from webob.exc import HTTPInternalServerError
31 from webob.exc import HTTPInternalServerError
32 from pylons import request, session, tmpl_context as c, url
32 from pylons import request, session, tmpl_context as c, url
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35 from sqlalchemy.exc import IntegrityError
35 from sqlalchemy.exc import IntegrityError
36
36
37 import rhodecode
37 import rhodecode
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 HasPermissionAnyDecorator, HasRepoPermissionAllDecorator
40 HasPermissionAnyDecorator, HasRepoPermissionAllDecorator
41 from rhodecode.lib.base import BaseController, render
41 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
42 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
43 from rhodecode.lib.helpers import get_token
43 from rhodecode.lib.helpers import get_token
44 from rhodecode.model.meta import Session
44 from rhodecode.model.meta import Session
45 from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup,\
45 from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup,\
46 RhodeCodeSetting
46 RhodeCodeSetting
47 from rhodecode.model.forms import RepoForm
47 from rhodecode.model.forms import RepoForm
48 from rhodecode.model.scm import ScmModel
48 from rhodecode.model.scm import ScmModel
49 from rhodecode.model.repo import RepoModel
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.lib.compat import json
50 from rhodecode.lib.compat import json
51 from sqlalchemy.sql.expression import func
51 from sqlalchemy.sql.expression import func
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 class ReposController(BaseController):
56 class ReposController(BaseController):
57 """
57 """
58 REST Controller styled on the Atom Publishing Protocol"""
58 REST Controller styled on the Atom Publishing Protocol"""
59 # To properly map this controller, ensure your config/routing.py
59 # To properly map this controller, ensure your config/routing.py
60 # file has a resource setup:
60 # file has a resource setup:
61 # map.resource('repo', 'repos')
61 # map.resource('repo', 'repos')
62
62
63 @LoginRequired()
63 @LoginRequired()
64 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
64 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
65 def __before__(self):
65 def __before__(self):
66 c.admin_user = session.get('admin_user')
66 c.admin_user = session.get('admin_user')
67 c.admin_username = session.get('admin_username')
67 c.admin_username = session.get('admin_username')
68 super(ReposController, self).__before__()
68 super(ReposController, self).__before__()
69
69
70 def __load_defaults(self):
70 def __load_defaults(self):
71 c.repo_groups = RepoGroup.groups_choices(check_perms=True)
71 c.repo_groups = RepoGroup.groups_choices(check_perms=True)
72 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
72 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
73
73
74 repo_model = RepoModel()
74 repo_model = RepoModel()
75 c.users_array = repo_model.get_users_js()
75 c.users_array = repo_model.get_users_js()
76 c.users_groups_array = repo_model.get_users_groups_js()
76 c.users_groups_array = repo_model.get_users_groups_js()
77 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
77 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
78 c.landing_revs_choices = choices
78 c.landing_revs_choices = choices
79
79
80 def __load_data(self, repo_name=None):
80 def __load_data(self, repo_name=None):
81 """
81 """
82 Load defaults settings for edit, and update
82 Load defaults settings for edit, and update
83
83
84 :param repo_name:
84 :param repo_name:
85 """
85 """
86 self.__load_defaults()
86 self.__load_defaults()
87
87
88 c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
88 c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
89 repo = db_repo.scm_instance
89 repo = db_repo.scm_instance
90
90
91 if c.repo_info is None:
91 if c.repo_info is None:
92 h.not_mapped_error(repo_name)
92 h.not_mapped_error(repo_name)
93 return redirect(url('repos'))
93 return redirect(url('repos'))
94
94
95 ##override defaults for exact repo info here git/hg etc
95 ##override defaults for exact repo info here git/hg etc
96 choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info)
96 choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info)
97 c.landing_revs_choices = choices
97 c.landing_revs_choices = choices
98
98
99 c.default_user_id = User.get_by_username('default').user_id
99 c.default_user_id = User.get_by_username('default').user_id
100 c.in_public_journal = UserFollowing.query()\
100 c.in_public_journal = UserFollowing.query()\
101 .filter(UserFollowing.user_id == c.default_user_id)\
101 .filter(UserFollowing.user_id == c.default_user_id)\
102 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
102 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
103
103
104 if c.repo_info.stats:
104 if c.repo_info.stats:
105 # this is on what revision we ended up so we add +1 for count
105 # this is on what revision we ended up so we add +1 for count
106 last_rev = c.repo_info.stats.stat_on_revision + 1
106 last_rev = c.repo_info.stats.stat_on_revision + 1
107 else:
107 else:
108 last_rev = 0
108 last_rev = 0
109 c.stats_revision = last_rev
109 c.stats_revision = last_rev
110
110
111 c.repo_last_rev = repo.count() if repo.revisions else 0
111 c.repo_last_rev = repo.count() if repo.revisions else 0
112
112
113 if last_rev == 0 or c.repo_last_rev == 0:
113 if last_rev == 0 or c.repo_last_rev == 0:
114 c.stats_percentage = 0
114 c.stats_percentage = 0
115 else:
115 else:
116 c.stats_percentage = '%.2f' % ((float((last_rev)) /
116 c.stats_percentage = '%.2f' % ((float((last_rev)) /
117 c.repo_last_rev) * 100)
117 c.repo_last_rev) * 100)
118
118
119 defaults = RepoModel()._get_defaults(repo_name)
119 defaults = RepoModel()._get_defaults(repo_name)
120
120
121 c.repos_list = [('', _('--REMOVE FORK--'))]
121 c.repos_list = [('', _('--REMOVE FORK--'))]
122 c.repos_list += [(x.repo_id, x.repo_name) for x in
122 c.repos_list += [(x.repo_id, x.repo_name) for x in
123 Repository.query().order_by(Repository.repo_name).all()
123 Repository.query().order_by(Repository.repo_name).all()
124 if x.repo_id != c.repo_info.repo_id]
124 if x.repo_id != c.repo_info.repo_id]
125
125
126 defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else ''
126 defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else ''
127 return defaults
127 return defaults
128
128
129 @HasPermissionAllDecorator('hg.admin')
129 @HasPermissionAllDecorator('hg.admin')
130 def index(self, format='html'):
130 def index(self, format='html'):
131 """GET /repos: All items in the collection"""
131 """GET /repos: All items in the collection"""
132 # url('repos')
132 # url('repos')
133
133
134 c.repos_list = Repository.query()\
134 c.repos_list = Repository.query()\
135 .order_by(func.lower(Repository.repo_name))\
135 .order_by(func.lower(Repository.repo_name))\
136 .all()
136 .all()
137
137
138 repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
138 repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
139 admin=True)
139 admin=True)
140 #json used to render the grid
140 #json used to render the grid
141 c.data = json.dumps(repos_data)
141 c.data = json.dumps(repos_data)
142
142
143 return render('admin/repos/repos.html')
143 return render('admin/repos/repos.html')
144
144
145 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
145 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
146 def create(self):
146 def create(self):
147 """
147 """
148 POST /repos: Create a new item"""
148 POST /repos: Create a new item"""
149 # url('repos')
149 # url('repos')
150
150
151 self.__load_defaults()
151 self.__load_defaults()
152 form_result = {}
152 form_result = {}
153 try:
153 try:
154 form_result = RepoForm(repo_groups=c.repo_groups_choices,
154 form_result = RepoForm(repo_groups=c.repo_groups_choices,
155 landing_revs=c.landing_revs_choices)()\
155 landing_revs=c.landing_revs_choices)()\
156 .to_python(dict(request.POST))
156 .to_python(dict(request.POST))
157 new_repo = RepoModel().create(form_result,
157 new_repo = RepoModel().create(form_result,
158 self.rhodecode_user.user_id)
158 self.rhodecode_user.user_id)
159 if form_result['clone_uri']:
159 if form_result['clone_uri']:
160 h.flash(_('created repository %s from %s') \
160 h.flash(_('created repository %s from %s') \
161 % (form_result['repo_name'], form_result['clone_uri']),
161 % (form_result['repo_name'], form_result['clone_uri']),
162 category='success')
162 category='success')
163 else:
163 else:
164 h.flash(_('created repository %s') % form_result['repo_name'],
164 h.flash(_('created repository %s') % form_result['repo_name'],
165 category='success')
165 category='success')
166
166
167 if request.POST.get('user_created'):
167 if request.POST.get('user_created'):
168 # created by regular non admin user
168 # created by regular non admin user
169 action_logger(self.rhodecode_user, 'user_created_repo',
169 action_logger(self.rhodecode_user, 'user_created_repo',
170 form_result['repo_name_full'], self.ip_addr,
170 form_result['repo_name_full'], self.ip_addr,
171 self.sa)
171 self.sa)
172 else:
172 else:
173 action_logger(self.rhodecode_user, 'admin_created_repo',
173 action_logger(self.rhodecode_user, 'admin_created_repo',
174 form_result['repo_name_full'], self.ip_addr,
174 form_result['repo_name_full'], self.ip_addr,
175 self.sa)
175 self.sa)
176 Session().commit()
176 Session().commit()
177 except formencode.Invalid, errors:
177 except formencode.Invalid, errors:
178
178
179 c.new_repo = errors.value['repo_name']
179 c.new_repo = errors.value['repo_name']
180
180
181 if request.POST.get('user_created'):
181 if request.POST.get('user_created'):
182 r = render('admin/repos/repo_add_create_repository.html')
182 r = render('admin/repos/repo_add_create_repository.html')
183 else:
183 else:
184 r = render('admin/repos/repo_add.html')
184 r = render('admin/repos/repo_add.html')
185
185
186 return htmlfill.render(
186 return htmlfill.render(
187 r,
187 r,
188 defaults=errors.value,
188 defaults=errors.value,
189 errors=errors.error_dict or {},
189 errors=errors.error_dict or {},
190 prefix_error=False,
190 prefix_error=False,
191 encoding="UTF-8")
191 encoding="UTF-8")
192
192
193 except Exception:
193 except Exception:
194 log.error(traceback.format_exc())
194 log.error(traceback.format_exc())
195 msg = _('error occurred during creation of repository %s') \
195 msg = _('error occurred during creation of repository %s') \
196 % form_result.get('repo_name')
196 % form_result.get('repo_name')
197 h.flash(msg, category='error')
197 h.flash(msg, category='error')
198 return redirect(url('repos'))
198 return redirect(url('repos'))
199 #redirect to our new repo !
199 #redirect to our new repo !
200 return redirect(url('summary_home', repo_name=new_repo.repo_name))
200 return redirect(url('summary_home', repo_name=new_repo.repo_name))
201
201
202 @HasPermissionAllDecorator('hg.admin')
202 @HasPermissionAllDecorator('hg.admin')
203 def new(self, format='html'):
203 def new(self, format='html'):
204 """GET /repos/new: Form to create a new item"""
204 """
205 WARNING: this function is depracated see settings.create_repo !!
206
207 GET /repos/new: Form to create a new item
208 """
209
205 new_repo = request.GET.get('repo', '')
210 new_repo = request.GET.get('repo', '')
211 parent_group = request.GET.get('parent_group')
212
206 c.new_repo = repo_name_slug(new_repo)
213 c.new_repo = repo_name_slug(new_repo)
207 self.__load_defaults()
214 self.__load_defaults()
208 ## apply the defaults from defaults page
215 ## apply the defaults from defaults page
209 defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
216 defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
217 if parent_group:
218 defaults.update({'repo_group': parent_group})
219
210 return htmlfill.render(
220 return htmlfill.render(
211 render('admin/repos/repo_add.html'),
221 render('admin/repos/repo_add.html'),
212 defaults=defaults,
222 defaults=defaults,
213 errors={},
223 errors={},
214 prefix_error=False,
224 prefix_error=False,
215 encoding="UTF-8"
225 encoding="UTF-8"
216 )
226 )
217
227
218 @HasPermissionAllDecorator('hg.admin')
228 @HasPermissionAllDecorator('hg.admin')
219 def update(self, repo_name):
229 def update(self, repo_name):
220 """
230 """
221 PUT /repos/repo_name: Update an existing item"""
231 PUT /repos/repo_name: Update an existing item"""
222 # Forms posted to this method should contain a hidden field:
232 # Forms posted to this method should contain a hidden field:
223 # <input type="hidden" name="_method" value="PUT" />
233 # <input type="hidden" name="_method" value="PUT" />
224 # Or using helpers:
234 # Or using helpers:
225 # h.form(url('repo', repo_name=ID),
235 # h.form(url('repo', repo_name=ID),
226 # method='put')
236 # method='put')
227 # url('repo', repo_name=ID)
237 # url('repo', repo_name=ID)
228 self.__load_defaults()
238 self.__load_defaults()
229 repo_model = RepoModel()
239 repo_model = RepoModel()
230 changed_name = repo_name
240 changed_name = repo_name
231 #override the choices with extracted revisions !
241 #override the choices with extracted revisions !
232 choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name)
242 choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name)
233 c.landing_revs_choices = choices
243 c.landing_revs_choices = choices
234
244
235 _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
245 _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
236 repo_groups=c.repo_groups_choices,
246 repo_groups=c.repo_groups_choices,
237 landing_revs=c.landing_revs_choices)()
247 landing_revs=c.landing_revs_choices)()
238 try:
248 try:
239 form_result = _form.to_python(dict(request.POST))
249 form_result = _form.to_python(dict(request.POST))
240 repo = repo_model.update(repo_name, **form_result)
250 repo = repo_model.update(repo_name, **form_result)
241 invalidate_cache('get_repo_cached_%s' % repo_name)
251 invalidate_cache('get_repo_cached_%s' % repo_name)
242 h.flash(_('Repository %s updated successfully') % repo_name,
252 h.flash(_('Repository %s updated successfully') % repo_name,
243 category='success')
253 category='success')
244 changed_name = repo.repo_name
254 changed_name = repo.repo_name
245 action_logger(self.rhodecode_user, 'admin_updated_repo',
255 action_logger(self.rhodecode_user, 'admin_updated_repo',
246 changed_name, self.ip_addr, self.sa)
256 changed_name, self.ip_addr, self.sa)
247 Session().commit()
257 Session().commit()
248 except formencode.Invalid, errors:
258 except formencode.Invalid, errors:
249 defaults = self.__load_data(repo_name)
259 defaults = self.__load_data(repo_name)
250 defaults.update(errors.value)
260 defaults.update(errors.value)
251 return htmlfill.render(
261 return htmlfill.render(
252 render('admin/repos/repo_edit.html'),
262 render('admin/repos/repo_edit.html'),
253 defaults=defaults,
263 defaults=defaults,
254 errors=errors.error_dict or {},
264 errors=errors.error_dict or {},
255 prefix_error=False,
265 prefix_error=False,
256 encoding="UTF-8")
266 encoding="UTF-8")
257
267
258 except Exception:
268 except Exception:
259 log.error(traceback.format_exc())
269 log.error(traceback.format_exc())
260 h.flash(_('error occurred during update of repository %s') \
270 h.flash(_('error occurred during update of repository %s') \
261 % repo_name, category='error')
271 % repo_name, category='error')
262 return redirect(url('edit_repo', repo_name=changed_name))
272 return redirect(url('edit_repo', repo_name=changed_name))
263
273
264 @HasPermissionAllDecorator('hg.admin')
274 @HasPermissionAllDecorator('hg.admin')
265 def delete(self, repo_name):
275 def delete(self, repo_name):
266 """
276 """
267 DELETE /repos/repo_name: Delete an existing item"""
277 DELETE /repos/repo_name: Delete an existing item"""
268 # Forms posted to this method should contain a hidden field:
278 # Forms posted to this method should contain a hidden field:
269 # <input type="hidden" name="_method" value="DELETE" />
279 # <input type="hidden" name="_method" value="DELETE" />
270 # Or using helpers:
280 # Or using helpers:
271 # h.form(url('repo', repo_name=ID),
281 # h.form(url('repo', repo_name=ID),
272 # method='delete')
282 # method='delete')
273 # url('repo', repo_name=ID)
283 # url('repo', repo_name=ID)
274
284
275 repo_model = RepoModel()
285 repo_model = RepoModel()
276 repo = repo_model.get_by_repo_name(repo_name)
286 repo = repo_model.get_by_repo_name(repo_name)
277 if not repo:
287 if not repo:
278 h.not_mapped_error(repo_name)
288 h.not_mapped_error(repo_name)
279 return redirect(url('repos'))
289 return redirect(url('repos'))
280 try:
290 try:
281 action_logger(self.rhodecode_user, 'admin_deleted_repo',
291 action_logger(self.rhodecode_user, 'admin_deleted_repo',
282 repo_name, self.ip_addr, self.sa)
292 repo_name, self.ip_addr, self.sa)
283 repo_model.delete(repo)
293 repo_model.delete(repo)
284 invalidate_cache('get_repo_cached_%s' % repo_name)
294 invalidate_cache('get_repo_cached_%s' % repo_name)
285 h.flash(_('deleted repository %s') % repo_name, category='success')
295 h.flash(_('deleted repository %s') % repo_name, category='success')
286 Session().commit()
296 Session().commit()
287 except IntegrityError, e:
297 except IntegrityError, e:
288 if e.message.find('repositories_fork_id_fkey') != -1:
298 if e.message.find('repositories_fork_id_fkey') != -1:
289 log.error(traceback.format_exc())
299 log.error(traceback.format_exc())
290 h.flash(_('Cannot delete %s it still contains attached '
300 h.flash(_('Cannot delete %s it still contains attached '
291 'forks') % repo_name,
301 'forks') % repo_name,
292 category='warning')
302 category='warning')
293 else:
303 else:
294 log.error(traceback.format_exc())
304 log.error(traceback.format_exc())
295 h.flash(_('An error occurred during '
305 h.flash(_('An error occurred during '
296 'deletion of %s') % repo_name,
306 'deletion of %s') % repo_name,
297 category='error')
307 category='error')
298
308
299 except Exception, e:
309 except Exception, e:
300 log.error(traceback.format_exc())
310 log.error(traceback.format_exc())
301 h.flash(_('An error occurred during deletion of %s') % repo_name,
311 h.flash(_('An error occurred during deletion of %s') % repo_name,
302 category='error')
312 category='error')
303
313
304 return redirect(url('repos'))
314 return redirect(url('repos'))
305
315
306 @HasRepoPermissionAllDecorator('repository.admin')
316 @HasRepoPermissionAllDecorator('repository.admin')
307 def delete_perm_user(self, repo_name):
317 def delete_perm_user(self, repo_name):
308 """
318 """
309 DELETE an existing repository permission user
319 DELETE an existing repository permission user
310
320
311 :param repo_name:
321 :param repo_name:
312 """
322 """
313 try:
323 try:
314 RepoModel().revoke_user_permission(repo=repo_name,
324 RepoModel().revoke_user_permission(repo=repo_name,
315 user=request.POST['user_id'])
325 user=request.POST['user_id'])
316 Session().commit()
326 Session().commit()
317 except Exception:
327 except Exception:
318 log.error(traceback.format_exc())
328 log.error(traceback.format_exc())
319 h.flash(_('An error occurred during deletion of repository user'),
329 h.flash(_('An error occurred during deletion of repository user'),
320 category='error')
330 category='error')
321 raise HTTPInternalServerError()
331 raise HTTPInternalServerError()
322
332
323 @HasRepoPermissionAllDecorator('repository.admin')
333 @HasRepoPermissionAllDecorator('repository.admin')
324 def delete_perm_users_group(self, repo_name):
334 def delete_perm_users_group(self, repo_name):
325 """
335 """
326 DELETE an existing repository permission users group
336 DELETE an existing repository permission users group
327
337
328 :param repo_name:
338 :param repo_name:
329 """
339 """
330
340
331 try:
341 try:
332 RepoModel().revoke_users_group_permission(
342 RepoModel().revoke_users_group_permission(
333 repo=repo_name, group_name=request.POST['users_group_id']
343 repo=repo_name, group_name=request.POST['users_group_id']
334 )
344 )
335 Session().commit()
345 Session().commit()
336 except Exception:
346 except Exception:
337 log.error(traceback.format_exc())
347 log.error(traceback.format_exc())
338 h.flash(_('An error occurred during deletion of repository'
348 h.flash(_('An error occurred during deletion of repository'
339 ' users groups'),
349 ' users groups'),
340 category='error')
350 category='error')
341 raise HTTPInternalServerError()
351 raise HTTPInternalServerError()
342
352
343 @HasPermissionAllDecorator('hg.admin')
353 @HasPermissionAllDecorator('hg.admin')
344 def repo_stats(self, repo_name):
354 def repo_stats(self, repo_name):
345 """
355 """
346 DELETE an existing repository statistics
356 DELETE an existing repository statistics
347
357
348 :param repo_name:
358 :param repo_name:
349 """
359 """
350
360
351 try:
361 try:
352 RepoModel().delete_stats(repo_name)
362 RepoModel().delete_stats(repo_name)
353 Session().commit()
363 Session().commit()
354 except Exception, e:
364 except Exception, e:
355 log.error(traceback.format_exc())
365 log.error(traceback.format_exc())
356 h.flash(_('An error occurred during deletion of repository stats'),
366 h.flash(_('An error occurred during deletion of repository stats'),
357 category='error')
367 category='error')
358 return redirect(url('edit_repo', repo_name=repo_name))
368 return redirect(url('edit_repo', repo_name=repo_name))
359
369
360 @HasPermissionAllDecorator('hg.admin')
370 @HasPermissionAllDecorator('hg.admin')
361 def repo_cache(self, repo_name):
371 def repo_cache(self, repo_name):
362 """
372 """
363 INVALIDATE existing repository cache
373 INVALIDATE existing repository cache
364
374
365 :param repo_name:
375 :param repo_name:
366 """
376 """
367
377
368 try:
378 try:
369 ScmModel().mark_for_invalidation(repo_name)
379 ScmModel().mark_for_invalidation(repo_name)
370 Session().commit()
380 Session().commit()
371 except Exception, e:
381 except Exception, e:
372 log.error(traceback.format_exc())
382 log.error(traceback.format_exc())
373 h.flash(_('An error occurred during cache invalidation'),
383 h.flash(_('An error occurred during cache invalidation'),
374 category='error')
384 category='error')
375 return redirect(url('edit_repo', repo_name=repo_name))
385 return redirect(url('edit_repo', repo_name=repo_name))
376
386
377 @HasPermissionAllDecorator('hg.admin')
387 @HasPermissionAllDecorator('hg.admin')
378 def repo_locking(self, repo_name):
388 def repo_locking(self, repo_name):
379 """
389 """
380 Unlock repository when it is locked !
390 Unlock repository when it is locked !
381
391
382 :param repo_name:
392 :param repo_name:
383 """
393 """
384
394
385 try:
395 try:
386 repo = Repository.get_by_repo_name(repo_name)
396 repo = Repository.get_by_repo_name(repo_name)
387 if request.POST.get('set_lock'):
397 if request.POST.get('set_lock'):
388 Repository.lock(repo, c.rhodecode_user.user_id)
398 Repository.lock(repo, c.rhodecode_user.user_id)
389 elif request.POST.get('set_unlock'):
399 elif request.POST.get('set_unlock'):
390 Repository.unlock(repo)
400 Repository.unlock(repo)
391 except Exception, e:
401 except Exception, e:
392 log.error(traceback.format_exc())
402 log.error(traceback.format_exc())
393 h.flash(_('An error occurred during unlocking'),
403 h.flash(_('An error occurred during unlocking'),
394 category='error')
404 category='error')
395 return redirect(url('edit_repo', repo_name=repo_name))
405 return redirect(url('edit_repo', repo_name=repo_name))
396
406
397 @HasPermissionAllDecorator('hg.admin')
407 @HasPermissionAllDecorator('hg.admin')
398 def repo_public_journal(self, repo_name):
408 def repo_public_journal(self, repo_name):
399 """
409 """
400 Set's this repository to be visible in public journal,
410 Set's this repository to be visible in public journal,
401 in other words assing default user to follow this repo
411 in other words assing default user to follow this repo
402
412
403 :param repo_name:
413 :param repo_name:
404 """
414 """
405
415
406 cur_token = request.POST.get('auth_token')
416 cur_token = request.POST.get('auth_token')
407 token = get_token()
417 token = get_token()
408 if cur_token == token:
418 if cur_token == token:
409 try:
419 try:
410 repo_id = Repository.get_by_repo_name(repo_name).repo_id
420 repo_id = Repository.get_by_repo_name(repo_name).repo_id
411 user_id = User.get_by_username('default').user_id
421 user_id = User.get_by_username('default').user_id
412 self.scm_model.toggle_following_repo(repo_id, user_id)
422 self.scm_model.toggle_following_repo(repo_id, user_id)
413 h.flash(_('Updated repository visibility in public journal'),
423 h.flash(_('Updated repository visibility in public journal'),
414 category='success')
424 category='success')
415 Session().commit()
425 Session().commit()
416 except:
426 except:
417 h.flash(_('An error occurred during setting this'
427 h.flash(_('An error occurred during setting this'
418 ' repository in public journal'),
428 ' repository in public journal'),
419 category='error')
429 category='error')
420
430
421 else:
431 else:
422 h.flash(_('Token mismatch'), category='error')
432 h.flash(_('Token mismatch'), category='error')
423 return redirect(url('edit_repo', repo_name=repo_name))
433 return redirect(url('edit_repo', repo_name=repo_name))
424
434
425 @HasPermissionAllDecorator('hg.admin')
435 @HasPermissionAllDecorator('hg.admin')
426 def repo_pull(self, repo_name):
436 def repo_pull(self, repo_name):
427 """
437 """
428 Runs task to update given repository with remote changes,
438 Runs task to update given repository with remote changes,
429 ie. make pull on remote location
439 ie. make pull on remote location
430
440
431 :param repo_name:
441 :param repo_name:
432 """
442 """
433 try:
443 try:
434 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
444 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
435 h.flash(_('Pulled from remote location'), category='success')
445 h.flash(_('Pulled from remote location'), category='success')
436 except Exception, e:
446 except Exception, e:
437 h.flash(_('An error occurred during pull from remote location'),
447 h.flash(_('An error occurred during pull from remote location'),
438 category='error')
448 category='error')
439
449
440 return redirect(url('edit_repo', repo_name=repo_name))
450 return redirect(url('edit_repo', repo_name=repo_name))
441
451
442 @HasPermissionAllDecorator('hg.admin')
452 @HasPermissionAllDecorator('hg.admin')
443 def repo_as_fork(self, repo_name):
453 def repo_as_fork(self, repo_name):
444 """
454 """
445 Mark given repository as a fork of another
455 Mark given repository as a fork of another
446
456
447 :param repo_name:
457 :param repo_name:
448 """
458 """
449 try:
459 try:
450 fork_id = request.POST.get('id_fork_of')
460 fork_id = request.POST.get('id_fork_of')
451 repo = ScmModel().mark_as_fork(repo_name, fork_id,
461 repo = ScmModel().mark_as_fork(repo_name, fork_id,
452 self.rhodecode_user.username)
462 self.rhodecode_user.username)
453 fork = repo.fork.repo_name if repo.fork else _('Nothing')
463 fork = repo.fork.repo_name if repo.fork else _('Nothing')
454 Session().commit()
464 Session().commit()
455 h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork),
465 h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork),
456 category='success')
466 category='success')
457 except Exception, e:
467 except Exception, e:
458 log.error(traceback.format_exc())
468 log.error(traceback.format_exc())
459 h.flash(_('An error occurred during this operation'),
469 h.flash(_('An error occurred during this operation'),
460 category='error')
470 category='error')
461
471
462 return redirect(url('edit_repo', repo_name=repo_name))
472 return redirect(url('edit_repo', repo_name=repo_name))
463
473
464 @HasPermissionAllDecorator('hg.admin')
474 @HasPermissionAllDecorator('hg.admin')
465 def show(self, repo_name, format='html'):
475 def show(self, repo_name, format='html'):
466 """GET /repos/repo_name: Show a specific item"""
476 """GET /repos/repo_name: Show a specific item"""
467 # url('repo', repo_name=ID)
477 # url('repo', repo_name=ID)
468
478
469 @HasPermissionAllDecorator('hg.admin')
479 @HasPermissionAllDecorator('hg.admin')
470 def edit(self, repo_name, format='html'):
480 def edit(self, repo_name, format='html'):
471 """GET /repos/repo_name/edit: Form to edit an existing item"""
481 """GET /repos/repo_name/edit: Form to edit an existing item"""
472 # url('edit_repo', repo_name=ID)
482 # url('edit_repo', repo_name=ID)
473 defaults = self.__load_data(repo_name)
483 defaults = self.__load_data(repo_name)
474
484
475 return htmlfill.render(
485 return htmlfill.render(
476 render('admin/repos/repo_edit.html'),
486 render('admin/repos/repo_edit.html'),
477 defaults=defaults,
487 defaults=defaults,
478 encoding="UTF-8",
488 encoding="UTF-8",
479 force_defaults=False
489 force_defaults=False
480 )
490 )
@@ -1,525 +1,529 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.settings
3 rhodecode.controllers.admin.settings
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 settings controller for rhodecode admin
6 settings controller for rhodecode admin
7
7
8 :created_on: Jul 14, 2010
8 :created_on: Jul 14, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 import pkg_resources
29 import pkg_resources
30 import platform
30 import platform
31
31
32 from sqlalchemy import func
32 from sqlalchemy import func
33 from formencode import htmlfill
33 from formencode import htmlfill
34 from pylons import request, session, tmpl_context as c, url, config
34 from pylons import request, session, tmpl_context as c, url, config
35 from pylons.controllers.util import abort, redirect
35 from pylons.controllers.util import abort, redirect
36 from pylons.i18n.translation import _
36 from pylons.i18n.translation import _
37
37
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 HasPermissionAnyDecorator, NotAnonymous
40 HasPermissionAnyDecorator, NotAnonymous
41 from rhodecode.lib.base import BaseController, render
41 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.celerylib import tasks, run_task
42 from rhodecode.lib.celerylib import tasks, run_task
43 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
43 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
44 set_rhodecode_config, repo_name_slug, check_git_version
44 set_rhodecode_config, repo_name_slug, check_git_version
45 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
45 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
46 RhodeCodeSetting, PullRequest, PullRequestReviewers
46 RhodeCodeSetting, PullRequest, PullRequestReviewers
47 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
47 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
48 ApplicationUiSettingsForm, ApplicationVisualisationForm
48 ApplicationUiSettingsForm, ApplicationVisualisationForm
49 from rhodecode.model.scm import ScmModel
49 from rhodecode.model.scm import ScmModel
50 from rhodecode.model.user import UserModel
50 from rhodecode.model.user import UserModel
51 from rhodecode.model.repo import RepoModel
51 from rhodecode.model.repo import RepoModel
52 from rhodecode.model.db import User
52 from rhodecode.model.db import User
53 from rhodecode.model.notification import EmailNotificationModel
53 from rhodecode.model.notification import EmailNotificationModel
54 from rhodecode.model.meta import Session
54 from rhodecode.model.meta import Session
55 from rhodecode.lib.utils2 import str2bool, safe_unicode
55 from rhodecode.lib.utils2 import str2bool, safe_unicode
56 from rhodecode.lib.compat import json
56 from rhodecode.lib.compat import json
57 log = logging.getLogger(__name__)
57 log = logging.getLogger(__name__)
58
58
59
59
60 class SettingsController(BaseController):
60 class SettingsController(BaseController):
61 """REST Controller styled on the Atom Publishing Protocol"""
61 """REST Controller styled on the Atom Publishing Protocol"""
62 # To properly map this controller, ensure your config/routing.py
62 # To properly map this controller, ensure your config/routing.py
63 # file has a resource setup:
63 # file has a resource setup:
64 # map.resource('setting', 'settings', controller='admin/settings',
64 # map.resource('setting', 'settings', controller='admin/settings',
65 # path_prefix='/admin', name_prefix='admin_')
65 # path_prefix='/admin', name_prefix='admin_')
66
66
67 @LoginRequired()
67 @LoginRequired()
68 def __before__(self):
68 def __before__(self):
69 c.admin_user = session.get('admin_user')
69 c.admin_user = session.get('admin_user')
70 c.admin_username = session.get('admin_username')
70 c.admin_username = session.get('admin_username')
71 c.modules = sorted([(p.project_name, p.version)
71 c.modules = sorted([(p.project_name, p.version)
72 for p in pkg_resources.working_set]
72 for p in pkg_resources.working_set]
73 + [('git', check_git_version())],
73 + [('git', check_git_version())],
74 key=lambda k: k[0].lower())
74 key=lambda k: k[0].lower())
75 c.py_version = platform.python_version()
75 c.py_version = platform.python_version()
76 c.platform = platform.platform()
76 c.platform = platform.platform()
77 super(SettingsController, self).__before__()
77 super(SettingsController, self).__before__()
78
78
79 @HasPermissionAllDecorator('hg.admin')
79 @HasPermissionAllDecorator('hg.admin')
80 def index(self, format='html'):
80 def index(self, format='html'):
81 """GET /admin/settings: All items in the collection"""
81 """GET /admin/settings: All items in the collection"""
82 # url('admin_settings')
82 # url('admin_settings')
83
83
84 defaults = RhodeCodeSetting.get_app_settings()
84 defaults = RhodeCodeSetting.get_app_settings()
85 defaults.update(self._get_hg_ui_settings())
85 defaults.update(self._get_hg_ui_settings())
86
86
87 return htmlfill.render(
87 return htmlfill.render(
88 render('admin/settings/settings.html'),
88 render('admin/settings/settings.html'),
89 defaults=defaults,
89 defaults=defaults,
90 encoding="UTF-8",
90 encoding="UTF-8",
91 force_defaults=False
91 force_defaults=False
92 )
92 )
93
93
94 @HasPermissionAllDecorator('hg.admin')
94 @HasPermissionAllDecorator('hg.admin')
95 def create(self):
95 def create(self):
96 """POST /admin/settings: Create a new item"""
96 """POST /admin/settings: Create a new item"""
97 # url('admin_settings')
97 # url('admin_settings')
98
98
99 @HasPermissionAllDecorator('hg.admin')
99 @HasPermissionAllDecorator('hg.admin')
100 def new(self, format='html'):
100 def new(self, format='html'):
101 """GET /admin/settings/new: Form to create a new item"""
101 """GET /admin/settings/new: Form to create a new item"""
102 # url('admin_new_setting')
102 # url('admin_new_setting')
103
103
104 @HasPermissionAllDecorator('hg.admin')
104 @HasPermissionAllDecorator('hg.admin')
105 def update(self, setting_id):
105 def update(self, setting_id):
106 """PUT /admin/settings/setting_id: Update an existing item"""
106 """PUT /admin/settings/setting_id: Update an existing item"""
107 # Forms posted to this method should contain a hidden field:
107 # Forms posted to this method should contain a hidden field:
108 # <input type="hidden" name="_method" value="PUT" />
108 # <input type="hidden" name="_method" value="PUT" />
109 # Or using helpers:
109 # Or using helpers:
110 # h.form(url('admin_setting', setting_id=ID),
110 # h.form(url('admin_setting', setting_id=ID),
111 # method='put')
111 # method='put')
112 # url('admin_setting', setting_id=ID)
112 # url('admin_setting', setting_id=ID)
113
113
114 if setting_id == 'mapping':
114 if setting_id == 'mapping':
115 rm_obsolete = request.POST.get('destroy', False)
115 rm_obsolete = request.POST.get('destroy', False)
116 log.debug('Rescanning directories with destroy=%s' % rm_obsolete)
116 log.debug('Rescanning directories with destroy=%s' % rm_obsolete)
117 initial = ScmModel().repo_scan()
117 initial = ScmModel().repo_scan()
118 log.debug('invalidating all repositories')
118 log.debug('invalidating all repositories')
119 for repo_name in initial.keys():
119 for repo_name in initial.keys():
120 invalidate_cache('get_repo_cached_%s' % repo_name)
120 invalidate_cache('get_repo_cached_%s' % repo_name)
121
121
122 added, removed = repo2db_mapper(initial, rm_obsolete)
122 added, removed = repo2db_mapper(initial, rm_obsolete)
123 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
123 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
124 h.flash(_('Repositories successfully '
124 h.flash(_('Repositories successfully '
125 'rescanned added: %s ; removed: %s') %
125 'rescanned added: %s ; removed: %s') %
126 (_repr(added), _repr(removed)),
126 (_repr(added), _repr(removed)),
127 category='success')
127 category='success')
128
128
129 if setting_id == 'whoosh':
129 if setting_id == 'whoosh':
130 repo_location = self._get_hg_ui_settings()['paths_root_path']
130 repo_location = self._get_hg_ui_settings()['paths_root_path']
131 full_index = request.POST.get('full_index', False)
131 full_index = request.POST.get('full_index', False)
132 run_task(tasks.whoosh_index, repo_location, full_index)
132 run_task(tasks.whoosh_index, repo_location, full_index)
133 h.flash(_('Whoosh reindex task scheduled'), category='success')
133 h.flash(_('Whoosh reindex task scheduled'), category='success')
134
134
135 if setting_id == 'global':
135 if setting_id == 'global':
136
136
137 application_form = ApplicationSettingsForm()()
137 application_form = ApplicationSettingsForm()()
138 try:
138 try:
139 form_result = application_form.to_python(dict(request.POST))
139 form_result = application_form.to_python(dict(request.POST))
140 except formencode.Invalid, errors:
140 except formencode.Invalid, errors:
141 return htmlfill.render(
141 return htmlfill.render(
142 render('admin/settings/settings.html'),
142 render('admin/settings/settings.html'),
143 defaults=errors.value,
143 defaults=errors.value,
144 errors=errors.error_dict or {},
144 errors=errors.error_dict or {},
145 prefix_error=False,
145 prefix_error=False,
146 encoding="UTF-8"
146 encoding="UTF-8"
147 )
147 )
148
148
149 try:
149 try:
150 sett1 = RhodeCodeSetting.get_by_name_or_create('title')
150 sett1 = RhodeCodeSetting.get_by_name_or_create('title')
151 sett1.app_settings_value = form_result['rhodecode_title']
151 sett1.app_settings_value = form_result['rhodecode_title']
152 Session().add(sett1)
152 Session().add(sett1)
153
153
154 sett2 = RhodeCodeSetting.get_by_name_or_create('realm')
154 sett2 = RhodeCodeSetting.get_by_name_or_create('realm')
155 sett2.app_settings_value = form_result['rhodecode_realm']
155 sett2.app_settings_value = form_result['rhodecode_realm']
156 Session().add(sett2)
156 Session().add(sett2)
157
157
158 sett3 = RhodeCodeSetting.get_by_name_or_create('ga_code')
158 sett3 = RhodeCodeSetting.get_by_name_or_create('ga_code')
159 sett3.app_settings_value = form_result['rhodecode_ga_code']
159 sett3.app_settings_value = form_result['rhodecode_ga_code']
160 Session().add(sett3)
160 Session().add(sett3)
161
161
162 Session().commit()
162 Session().commit()
163 set_rhodecode_config(config)
163 set_rhodecode_config(config)
164 h.flash(_('Updated application settings'), category='success')
164 h.flash(_('Updated application settings'), category='success')
165
165
166 except Exception:
166 except Exception:
167 log.error(traceback.format_exc())
167 log.error(traceback.format_exc())
168 h.flash(_('error occurred during updating '
168 h.flash(_('error occurred during updating '
169 'application settings'),
169 'application settings'),
170 category='error')
170 category='error')
171
171
172 if setting_id == 'visual':
172 if setting_id == 'visual':
173
173
174 application_form = ApplicationVisualisationForm()()
174 application_form = ApplicationVisualisationForm()()
175 try:
175 try:
176 form_result = application_form.to_python(dict(request.POST))
176 form_result = application_form.to_python(dict(request.POST))
177 except formencode.Invalid, errors:
177 except formencode.Invalid, errors:
178 return htmlfill.render(
178 return htmlfill.render(
179 render('admin/settings/settings.html'),
179 render('admin/settings/settings.html'),
180 defaults=errors.value,
180 defaults=errors.value,
181 errors=errors.error_dict or {},
181 errors=errors.error_dict or {},
182 prefix_error=False,
182 prefix_error=False,
183 encoding="UTF-8"
183 encoding="UTF-8"
184 )
184 )
185
185
186 try:
186 try:
187 sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon')
187 sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon')
188 sett1.app_settings_value = \
188 sett1.app_settings_value = \
189 form_result['rhodecode_show_public_icon']
189 form_result['rhodecode_show_public_icon']
190 Session().add(sett1)
190 Session().add(sett1)
191
191
192 sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon')
192 sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon')
193 sett2.app_settings_value = \
193 sett2.app_settings_value = \
194 form_result['rhodecode_show_private_icon']
194 form_result['rhodecode_show_private_icon']
195 Session().add(sett2)
195 Session().add(sett2)
196
196
197 sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags')
197 sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags')
198 sett3.app_settings_value = \
198 sett3.app_settings_value = \
199 form_result['rhodecode_stylify_metatags']
199 form_result['rhodecode_stylify_metatags']
200 Session().add(sett3)
200 Session().add(sett3)
201
201
202 sett4 = RhodeCodeSetting.get_by_name_or_create('lightweight_dashboard')
202 sett4 = RhodeCodeSetting.get_by_name_or_create('lightweight_dashboard')
203 sett4.app_settings_value = \
203 sett4.app_settings_value = \
204 form_result['rhodecode_lightweight_dashboard']
204 form_result['rhodecode_lightweight_dashboard']
205 Session().add(sett4)
205 Session().add(sett4)
206
206
207 Session().commit()
207 Session().commit()
208 set_rhodecode_config(config)
208 set_rhodecode_config(config)
209 h.flash(_('Updated visualisation settings'),
209 h.flash(_('Updated visualisation settings'),
210 category='success')
210 category='success')
211
211
212 except Exception:
212 except Exception:
213 log.error(traceback.format_exc())
213 log.error(traceback.format_exc())
214 h.flash(_('error occurred during updating '
214 h.flash(_('error occurred during updating '
215 'visualisation settings'),
215 'visualisation settings'),
216 category='error')
216 category='error')
217
217
218 if setting_id == 'vcs':
218 if setting_id == 'vcs':
219 application_form = ApplicationUiSettingsForm()()
219 application_form = ApplicationUiSettingsForm()()
220 try:
220 try:
221 form_result = application_form.to_python(dict(request.POST))
221 form_result = application_form.to_python(dict(request.POST))
222 except formencode.Invalid, errors:
222 except formencode.Invalid, errors:
223 return htmlfill.render(
223 return htmlfill.render(
224 render('admin/settings/settings.html'),
224 render('admin/settings/settings.html'),
225 defaults=errors.value,
225 defaults=errors.value,
226 errors=errors.error_dict or {},
226 errors=errors.error_dict or {},
227 prefix_error=False,
227 prefix_error=False,
228 encoding="UTF-8"
228 encoding="UTF-8"
229 )
229 )
230
230
231 try:
231 try:
232 # fix namespaces for hooks and extensions
232 # fix namespaces for hooks and extensions
233 _f = lambda s: s.replace('.', '_')
233 _f = lambda s: s.replace('.', '_')
234
234
235 sett = RhodeCodeUi.get_by_key('push_ssl')
235 sett = RhodeCodeUi.get_by_key('push_ssl')
236 sett.ui_value = form_result['web_push_ssl']
236 sett.ui_value = form_result['web_push_ssl']
237 Session().add(sett)
237 Session().add(sett)
238
238
239 sett = RhodeCodeUi.get_by_key('/')
239 sett = RhodeCodeUi.get_by_key('/')
240 sett.ui_value = form_result['paths_root_path']
240 sett.ui_value = form_result['paths_root_path']
241 Session().add(sett)
241 Session().add(sett)
242
242
243 #HOOKS
243 #HOOKS
244 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE)
244 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE)
245 sett.ui_active = form_result[_f('hooks_%s' %
245 sett.ui_active = form_result[_f('hooks_%s' %
246 RhodeCodeUi.HOOK_UPDATE)]
246 RhodeCodeUi.HOOK_UPDATE)]
247 Session().add(sett)
247 Session().add(sett)
248
248
249 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_REPO_SIZE)
249 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_REPO_SIZE)
250 sett.ui_active = form_result[_f('hooks_%s' %
250 sett.ui_active = form_result[_f('hooks_%s' %
251 RhodeCodeUi.HOOK_REPO_SIZE)]
251 RhodeCodeUi.HOOK_REPO_SIZE)]
252 Session().add(sett)
252 Session().add(sett)
253
253
254 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PUSH)
254 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PUSH)
255 sett.ui_active = form_result[_f('hooks_%s' %
255 sett.ui_active = form_result[_f('hooks_%s' %
256 RhodeCodeUi.HOOK_PUSH)]
256 RhodeCodeUi.HOOK_PUSH)]
257 Session().add(sett)
257 Session().add(sett)
258
258
259 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PULL)
259 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PULL)
260 sett.ui_active = form_result[_f('hooks_%s' %
260 sett.ui_active = form_result[_f('hooks_%s' %
261 RhodeCodeUi.HOOK_PULL)]
261 RhodeCodeUi.HOOK_PULL)]
262
262
263 Session().add(sett)
263 Session().add(sett)
264
264
265 ## EXTENSIONS
265 ## EXTENSIONS
266 sett = RhodeCodeUi.get_by_key('largefiles')
266 sett = RhodeCodeUi.get_by_key('largefiles')
267 if not sett:
267 if not sett:
268 #make one if it's not there !
268 #make one if it's not there !
269 sett = RhodeCodeUi()
269 sett = RhodeCodeUi()
270 sett.ui_key = 'largefiles'
270 sett.ui_key = 'largefiles'
271 sett.ui_section = 'extensions'
271 sett.ui_section = 'extensions'
272 sett.ui_active = form_result[_f('extensions_largefiles')]
272 sett.ui_active = form_result[_f('extensions_largefiles')]
273 Session().add(sett)
273 Session().add(sett)
274
274
275 sett = RhodeCodeUi.get_by_key('hgsubversion')
275 sett = RhodeCodeUi.get_by_key('hgsubversion')
276 if not sett:
276 if not sett:
277 #make one if it's not there !
277 #make one if it's not there !
278 sett = RhodeCodeUi()
278 sett = RhodeCodeUi()
279 sett.ui_key = 'hgsubversion'
279 sett.ui_key = 'hgsubversion'
280 sett.ui_section = 'extensions'
280 sett.ui_section = 'extensions'
281
281
282 sett.ui_active = form_result[_f('extensions_hgsubversion')]
282 sett.ui_active = form_result[_f('extensions_hgsubversion')]
283 Session().add(sett)
283 Session().add(sett)
284
284
285 # sett = RhodeCodeUi.get_by_key('hggit')
285 # sett = RhodeCodeUi.get_by_key('hggit')
286 # if not sett:
286 # if not sett:
287 # #make one if it's not there !
287 # #make one if it's not there !
288 # sett = RhodeCodeUi()
288 # sett = RhodeCodeUi()
289 # sett.ui_key = 'hggit'
289 # sett.ui_key = 'hggit'
290 # sett.ui_section = 'extensions'
290 # sett.ui_section = 'extensions'
291 #
291 #
292 # sett.ui_active = form_result[_f('extensions_hggit')]
292 # sett.ui_active = form_result[_f('extensions_hggit')]
293 # Session().add(sett)
293 # Session().add(sett)
294
294
295 Session().commit()
295 Session().commit()
296
296
297 h.flash(_('Updated VCS settings'), category='success')
297 h.flash(_('Updated VCS settings'), category='success')
298
298
299 except Exception:
299 except Exception:
300 log.error(traceback.format_exc())
300 log.error(traceback.format_exc())
301 h.flash(_('error occurred during updating '
301 h.flash(_('error occurred during updating '
302 'application settings'), category='error')
302 'application settings'), category='error')
303
303
304 if setting_id == 'hooks':
304 if setting_id == 'hooks':
305 ui_key = request.POST.get('new_hook_ui_key')
305 ui_key = request.POST.get('new_hook_ui_key')
306 ui_value = request.POST.get('new_hook_ui_value')
306 ui_value = request.POST.get('new_hook_ui_value')
307 try:
307 try:
308
308
309 if ui_value and ui_key:
309 if ui_value and ui_key:
310 RhodeCodeUi.create_or_update_hook(ui_key, ui_value)
310 RhodeCodeUi.create_or_update_hook(ui_key, ui_value)
311 h.flash(_('Added new hook'),
311 h.flash(_('Added new hook'),
312 category='success')
312 category='success')
313
313
314 # check for edits
314 # check for edits
315 update = False
315 update = False
316 _d = request.POST.dict_of_lists()
316 _d = request.POST.dict_of_lists()
317 for k, v in zip(_d.get('hook_ui_key', []),
317 for k, v in zip(_d.get('hook_ui_key', []),
318 _d.get('hook_ui_value_new', [])):
318 _d.get('hook_ui_value_new', [])):
319 RhodeCodeUi.create_or_update_hook(k, v)
319 RhodeCodeUi.create_or_update_hook(k, v)
320 update = True
320 update = True
321
321
322 if update:
322 if update:
323 h.flash(_('Updated hooks'), category='success')
323 h.flash(_('Updated hooks'), category='success')
324 Session().commit()
324 Session().commit()
325 except Exception:
325 except Exception:
326 log.error(traceback.format_exc())
326 log.error(traceback.format_exc())
327 h.flash(_('error occurred during hook creation'),
327 h.flash(_('error occurred during hook creation'),
328 category='error')
328 category='error')
329
329
330 return redirect(url('admin_edit_setting', setting_id='hooks'))
330 return redirect(url('admin_edit_setting', setting_id='hooks'))
331
331
332 if setting_id == 'email':
332 if setting_id == 'email':
333 test_email = request.POST.get('test_email')
333 test_email = request.POST.get('test_email')
334 test_email_subj = 'RhodeCode TestEmail'
334 test_email_subj = 'RhodeCode TestEmail'
335 test_email_body = 'RhodeCode Email test'
335 test_email_body = 'RhodeCode Email test'
336
336
337 test_email_html_body = EmailNotificationModel()\
337 test_email_html_body = EmailNotificationModel()\
338 .get_email_tmpl(EmailNotificationModel.TYPE_DEFAULT,
338 .get_email_tmpl(EmailNotificationModel.TYPE_DEFAULT,
339 body=test_email_body)
339 body=test_email_body)
340
340
341 recipients = [test_email] if test_email else None
341 recipients = [test_email] if test_email else None
342
342
343 run_task(tasks.send_email, recipients, test_email_subj,
343 run_task(tasks.send_email, recipients, test_email_subj,
344 test_email_body, test_email_html_body)
344 test_email_body, test_email_html_body)
345
345
346 h.flash(_('Email task created'), category='success')
346 h.flash(_('Email task created'), category='success')
347 return redirect(url('admin_settings'))
347 return redirect(url('admin_settings'))
348
348
349 @HasPermissionAllDecorator('hg.admin')
349 @HasPermissionAllDecorator('hg.admin')
350 def delete(self, setting_id):
350 def delete(self, setting_id):
351 """DELETE /admin/settings/setting_id: Delete an existing item"""
351 """DELETE /admin/settings/setting_id: Delete an existing item"""
352 # Forms posted to this method should contain a hidden field:
352 # Forms posted to this method should contain a hidden field:
353 # <input type="hidden" name="_method" value="DELETE" />
353 # <input type="hidden" name="_method" value="DELETE" />
354 # Or using helpers:
354 # Or using helpers:
355 # h.form(url('admin_setting', setting_id=ID),
355 # h.form(url('admin_setting', setting_id=ID),
356 # method='delete')
356 # method='delete')
357 # url('admin_setting', setting_id=ID)
357 # url('admin_setting', setting_id=ID)
358 if setting_id == 'hooks':
358 if setting_id == 'hooks':
359 hook_id = request.POST.get('hook_id')
359 hook_id = request.POST.get('hook_id')
360 RhodeCodeUi.delete(hook_id)
360 RhodeCodeUi.delete(hook_id)
361 Session().commit()
361 Session().commit()
362
362
363 @HasPermissionAllDecorator('hg.admin')
363 @HasPermissionAllDecorator('hg.admin')
364 def show(self, setting_id, format='html'):
364 def show(self, setting_id, format='html'):
365 """
365 """
366 GET /admin/settings/setting_id: Show a specific item"""
366 GET /admin/settings/setting_id: Show a specific item"""
367 # url('admin_setting', setting_id=ID)
367 # url('admin_setting', setting_id=ID)
368
368
369 @HasPermissionAllDecorator('hg.admin')
369 @HasPermissionAllDecorator('hg.admin')
370 def edit(self, setting_id, format='html'):
370 def edit(self, setting_id, format='html'):
371 """
371 """
372 GET /admin/settings/setting_id/edit: Form to
372 GET /admin/settings/setting_id/edit: Form to
373 edit an existing item"""
373 edit an existing item"""
374 # url('admin_edit_setting', setting_id=ID)
374 # url('admin_edit_setting', setting_id=ID)
375
375
376 c.hooks = RhodeCodeUi.get_builtin_hooks()
376 c.hooks = RhodeCodeUi.get_builtin_hooks()
377 c.custom_hooks = RhodeCodeUi.get_custom_hooks()
377 c.custom_hooks = RhodeCodeUi.get_custom_hooks()
378
378
379 return htmlfill.render(
379 return htmlfill.render(
380 render('admin/settings/hooks.html'),
380 render('admin/settings/hooks.html'),
381 defaults={},
381 defaults={},
382 encoding="UTF-8",
382 encoding="UTF-8",
383 force_defaults=False
383 force_defaults=False
384 )
384 )
385
385
386 def _load_my_repos_data(self):
386 def _load_my_repos_data(self):
387 repos_list = Session().query(Repository)\
387 repos_list = Session().query(Repository)\
388 .filter(Repository.user_id ==
388 .filter(Repository.user_id ==
389 self.rhodecode_user.user_id)\
389 self.rhodecode_user.user_id)\
390 .order_by(func.lower(Repository.repo_name)).all()
390 .order_by(func.lower(Repository.repo_name)).all()
391
391
392 repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list,
392 repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list,
393 admin=True)
393 admin=True)
394 #json used to render the grid
394 #json used to render the grid
395 return json.dumps(repos_data)
395 return json.dumps(repos_data)
396
396
397 @NotAnonymous()
397 @NotAnonymous()
398 def my_account(self):
398 def my_account(self):
399 """
399 """
400 GET /_admin/my_account Displays info about my account
400 GET /_admin/my_account Displays info about my account
401 """
401 """
402 # url('admin_settings_my_account')
402 # url('admin_settings_my_account')
403
403
404 c.user = User.get(self.rhodecode_user.user_id)
404 c.user = User.get(self.rhodecode_user.user_id)
405 c.ldap_dn = c.user.ldap_dn
405 c.ldap_dn = c.user.ldap_dn
406
406
407 if c.user.username == 'default':
407 if c.user.username == 'default':
408 h.flash(_("You can't edit this user since it's"
408 h.flash(_("You can't edit this user since it's"
409 " crucial for entire application"), category='warning')
409 " crucial for entire application"), category='warning')
410 return redirect(url('users'))
410 return redirect(url('users'))
411
411
412 #json used to render the grid
412 #json used to render the grid
413 c.data = self._load_my_repos_data()
413 c.data = self._load_my_repos_data()
414
414
415 defaults = c.user.get_dict()
415 defaults = c.user.get_dict()
416
416
417 c.form = htmlfill.render(
417 c.form = htmlfill.render(
418 render('admin/users/user_edit_my_account_form.html'),
418 render('admin/users/user_edit_my_account_form.html'),
419 defaults=defaults,
419 defaults=defaults,
420 encoding="UTF-8",
420 encoding="UTF-8",
421 force_defaults=False
421 force_defaults=False
422 )
422 )
423 return render('admin/users/user_edit_my_account.html')
423 return render('admin/users/user_edit_my_account.html')
424
424
425 @NotAnonymous()
425 @NotAnonymous()
426 def my_account_update(self):
426 def my_account_update(self):
427 """PUT /_admin/my_account_update: Update an existing item"""
427 """PUT /_admin/my_account_update: Update an existing item"""
428 # Forms posted to this method should contain a hidden field:
428 # Forms posted to this method should contain a hidden field:
429 # <input type="hidden" name="_method" value="PUT" />
429 # <input type="hidden" name="_method" value="PUT" />
430 # Or using helpers:
430 # Or using helpers:
431 # h.form(url('admin_settings_my_account_update'),
431 # h.form(url('admin_settings_my_account_update'),
432 # method='put')
432 # method='put')
433 # url('admin_settings_my_account_update', id=ID)
433 # url('admin_settings_my_account_update', id=ID)
434 uid = self.rhodecode_user.user_id
434 uid = self.rhodecode_user.user_id
435 c.user = User.get(self.rhodecode_user.user_id)
435 c.user = User.get(self.rhodecode_user.user_id)
436 c.ldap_dn = c.user.ldap_dn
436 c.ldap_dn = c.user.ldap_dn
437 email = self.rhodecode_user.email
437 email = self.rhodecode_user.email
438 _form = UserForm(edit=True,
438 _form = UserForm(edit=True,
439 old_data={'user_id': uid, 'email': email})()
439 old_data={'user_id': uid, 'email': email})()
440 form_result = {}
440 form_result = {}
441 try:
441 try:
442 form_result = _form.to_python(dict(request.POST))
442 form_result = _form.to_python(dict(request.POST))
443 skip_attrs = ['admin', 'active'] # skip attr for my account
443 skip_attrs = ['admin', 'active'] # skip attr for my account
444 if c.ldap_dn:
444 if c.ldap_dn:
445 #forbid updating username for ldap accounts
445 #forbid updating username for ldap accounts
446 skip_attrs.append('username')
446 skip_attrs.append('username')
447 UserModel().update(uid, form_result, skip_attrs=skip_attrs)
447 UserModel().update(uid, form_result, skip_attrs=skip_attrs)
448 h.flash(_('Your account was updated successfully'),
448 h.flash(_('Your account was updated successfully'),
449 category='success')
449 category='success')
450 Session().commit()
450 Session().commit()
451 except formencode.Invalid, errors:
451 except formencode.Invalid, errors:
452 #json used to render the grid
452 #json used to render the grid
453 c.data = self._load_my_repos_data()
453 c.data = self._load_my_repos_data()
454 c.form = htmlfill.render(
454 c.form = htmlfill.render(
455 render('admin/users/user_edit_my_account_form.html'),
455 render('admin/users/user_edit_my_account_form.html'),
456 defaults=errors.value,
456 defaults=errors.value,
457 errors=errors.error_dict or {},
457 errors=errors.error_dict or {},
458 prefix_error=False,
458 prefix_error=False,
459 encoding="UTF-8")
459 encoding="UTF-8")
460 return render('admin/users/user_edit_my_account.html')
460 return render('admin/users/user_edit_my_account.html')
461 except Exception:
461 except Exception:
462 log.error(traceback.format_exc())
462 log.error(traceback.format_exc())
463 h.flash(_('error occurred during update of user %s') \
463 h.flash(_('error occurred during update of user %s') \
464 % form_result.get('username'), category='error')
464 % form_result.get('username'), category='error')
465
465
466 return redirect(url('my_account'))
466 return redirect(url('my_account'))
467
467
468 @NotAnonymous()
468 @NotAnonymous()
469 def my_account_my_pullrequests(self):
469 def my_account_my_pullrequests(self):
470 c.my_pull_requests = PullRequest.query()\
470 c.my_pull_requests = PullRequest.query()\
471 .filter(PullRequest.user_id ==
471 .filter(PullRequest.user_id ==
472 self.rhodecode_user.user_id)\
472 self.rhodecode_user.user_id)\
473 .all()
473 .all()
474 c.participate_in_pull_requests = \
474 c.participate_in_pull_requests = \
475 [x.pull_request for x in PullRequestReviewers.query()\
475 [x.pull_request for x in PullRequestReviewers.query()\
476 .filter(PullRequestReviewers.user_id ==
476 .filter(PullRequestReviewers.user_id ==
477 self.rhodecode_user.user_id)\
477 self.rhodecode_user.user_id)\
478 .all()]
478 .all()]
479 return render('admin/users/user_edit_my_account_pullrequests.html')
479 return render('admin/users/user_edit_my_account_pullrequests.html')
480
480
481 @NotAnonymous()
481 @NotAnonymous()
482 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
482 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
483 def create_repository(self):
483 def create_repository(self):
484 """GET /_admin/create_repository: Form to create a new item"""
484 """GET /_admin/create_repository: Form to create a new item"""
485
485
486 c.repo_groups = RepoGroup.groups_choices(check_perms=True)
486 c.repo_groups = RepoGroup.groups_choices(check_perms=True)
487 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
487 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
488 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
488 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
489
489
490 new_repo = request.GET.get('repo', '')
490 new_repo = request.GET.get('repo', '')
491 parent_group = request.GET.get('parent_group')
491 c.new_repo = repo_name_slug(new_repo)
492 c.new_repo = repo_name_slug(new_repo)
492
493
493 ## apply the defaults from defaults page
494 ## apply the defaults from defaults page
494 defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
495 defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
496 if parent_group:
497 defaults.update({'repo_group': parent_group})
498
495 return htmlfill.render(
499 return htmlfill.render(
496 render('admin/repos/repo_add_create_repository.html'),
500 render('admin/repos/repo_add_create_repository.html'),
497 defaults=defaults,
501 defaults=defaults,
498 errors={},
502 errors={},
499 prefix_error=False,
503 prefix_error=False,
500 encoding="UTF-8"
504 encoding="UTF-8"
501 )
505 )
502
506
503 def _get_hg_ui_settings(self):
507 def _get_hg_ui_settings(self):
504 ret = RhodeCodeUi.query().all()
508 ret = RhodeCodeUi.query().all()
505
509
506 if not ret:
510 if not ret:
507 raise Exception('Could not get application ui settings !')
511 raise Exception('Could not get application ui settings !')
508 settings = {}
512 settings = {}
509 for each in ret:
513 for each in ret:
510 k = each.ui_key
514 k = each.ui_key
511 v = each.ui_value
515 v = each.ui_value
512 if k == '/':
516 if k == '/':
513 k = 'root_path'
517 k = 'root_path'
514
518
515 if k == 'push_ssl':
519 if k == 'push_ssl':
516 v = str2bool(v)
520 v = str2bool(v)
517
521
518 if k.find('.') != -1:
522 if k.find('.') != -1:
519 k = k.replace('.', '_')
523 k = k.replace('.', '_')
520
524
521 if each.ui_section in ['hooks', 'extensions']:
525 if each.ui_section in ['hooks', 'extensions']:
522 v = each.ui_active
526 v = each.ui_active
523
527
524 settings[each.ui_section + '_' + k] = v
528 settings[each.ui_section + '_' + k] = v
525 return settings
529 return settings
General Comments 0
You need to be logged in to leave comments. Login now