##// END OF EJS Templates
Added new style error display,...
marcink -
r356:b0715a78 default
parent child Browse files
Show More
@@ -1,197 +1,212 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # repos controller for pylons
3 # repos controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
7 # as published by the Free Software Foundation; version 2
8 # of the License or (at your opinion) any later version of the license.
8 # of the License or (at your opinion) any later version of the license.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
18 # MA 02110-1301, USA.
19 """
20 Created on April 7, 2010
21 admin controller for pylons
22 @author: marcink
23 """
24 from formencode import htmlfill
19 from formencode import htmlfill
25 from operator import itemgetter
20 from operator import itemgetter
26 from pylons import request, response, session, tmpl_context as c, url
21 from pylons import request, response, session, tmpl_context as c, url
27 from pylons.controllers.util import abort, redirect
22 from pylons.controllers.util import abort, redirect
28 from pylons.i18n.translation import _
23 from pylons.i18n.translation import _
29 from pylons_app.lib import helpers as h
24 from pylons_app.lib import helpers as h
30 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
25 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
31 from pylons_app.lib.base import BaseController, render
26 from pylons_app.lib.base import BaseController, render
32 from pylons_app.lib.utils import invalidate_cache
27 from pylons_app.lib.utils import invalidate_cache
33 from pylons_app.model.forms import RepoForm
28 from pylons_app.model.forms import RepoForm
34 from pylons_app.model.hg_model import HgModel
29 from pylons_app.model.hg_model import HgModel
35 from pylons_app.model.repo_model import RepoModel
30 from pylons_app.model.repo_model import RepoModel
36 import formencode
31 import formencode
37 import logging
32 import logging
33 import traceback
34 """
35 Created on April 7, 2010
36 admin controller for pylons
37 @author: marcink
38 """
38 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
39
40
40 class ReposController(BaseController):
41 class ReposController(BaseController):
41 """REST Controller styled on the Atom Publishing Protocol"""
42 """REST Controller styled on the Atom Publishing Protocol"""
42 # To properly map this controller, ensure your config/routing.py
43 # To properly map this controller, ensure your config/routing.py
43 # file has a resource setup:
44 # file has a resource setup:
44 # map.resource('repo', 'repos')
45 # map.resource('repo', 'repos')
45
46
46 @LoginRequired()
47 @LoginRequired()
47 @HasPermissionAllDecorator('hg.admin')
48 @HasPermissionAllDecorator('hg.admin')
48 def __before__(self):
49 def __before__(self):
49 c.admin_user = session.get('admin_user')
50 c.admin_user = session.get('admin_user')
50 c.admin_username = session.get('admin_username')
51 c.admin_username = session.get('admin_username')
51 super(ReposController, self).__before__()
52 super(ReposController, self).__before__()
52
53
53 def index(self, format='html'):
54 def index(self, format='html'):
54 """GET /repos: All items in the collection"""
55 """GET /repos: All items in the collection"""
55 # url('repos')
56 # url('repos')
56 cached_repo_list = HgModel().get_repos()
57 cached_repo_list = HgModel().get_repos()
57 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
58 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
58 return render('admin/repos/repos.html')
59 return render('admin/repos/repos.html')
59
60
60 def create(self):
61 def create(self):
61 """POST /repos: Create a new item"""
62 """POST /repos: Create a new item"""
62 # url('repos')
63 # url('repos')
63 repo_model = RepoModel()
64 repo_model = RepoModel()
64 _form = RepoForm()()
65 _form = RepoForm()()
66 form_result = None
65 try:
67 try:
66 form_result = _form.to_python(dict(request.POST))
68 form_result = _form.to_python(dict(request.POST))
67 repo_model.create(form_result, c.hg_app_user)
69 repo_model.create(form_result, c.hg_app_user)
68 invalidate_cache('cached_repo_list')
70 invalidate_cache('cached_repo_list')
69 h.flash(_('created repository %s') % form_result['repo_name'],
71 h.flash(_('created repository %s') % form_result['repo_name'],
70 category='success')
72 category='success')
71
73
72 except formencode.Invalid as errors:
74 except formencode.Invalid as errors:
73 c.form_errors = errors.error_dict
74 c.new_repo = errors.value['repo_name']
75 c.new_repo = errors.value['repo_name']
75 return htmlfill.render(
76 return htmlfill.render(
76 render('admin/repos/repo_add.html'),
77 render('admin/repos/repo_add.html'),
77 defaults=errors.value,
78 defaults=errors.value,
78 encoding="UTF-8")
79 errors=errors.error_dict or {},
80 prefix_error=False,
81 encoding="UTF-8")
79
82
80 except Exception:
83 except Exception:
81 h.flash(_('error occured during creation of repository %s') \
84 log.error(traceback.format_exc())
82 % form_result['repo_name'], category='error')
85 if form_result:
86 msg = _('error occured during creation of repository %s') \
87 % form_result['repo_name']
88 else:
89 msg = _('error occured during creation of repository')
90 h.flash(msg, category='error')
83
91
84 return redirect('repos')
92 return redirect('repos')
85
93
86 def new(self, format='html'):
94 def new(self, format='html'):
87 """GET /repos/new: Form to create a new item"""
95 """GET /repos/new: Form to create a new item"""
88 new_repo = request.GET.get('repo', '')
96 new_repo = request.GET.get('repo', '')
89 c.new_repo = h.repo_name_slug(new_repo)
97 c.new_repo = h.repo_name_slug(new_repo)
90
98
91 return render('admin/repos/repo_add.html')
99 return render('admin/repos/repo_add.html')
92
100
93 def update(self, repo_name):
101 def update(self, repo_name):
94 """PUT /repos/repo_name: Update an existing item"""
102 """PUT /repos/repo_name: Update an existing item"""
95 # Forms posted to this method should contain a hidden field:
103 # Forms posted to this method should contain a hidden field:
96 # <input type="hidden" name="_method" value="PUT" />
104 # <input type="hidden" name="_method" value="PUT" />
97 # Or using helpers:
105 # Or using helpers:
98 # h.form(url('repo', repo_name=ID),
106 # h.form(url('repo', repo_name=ID),
99 # method='put')
107 # method='put')
100 # url('repo', repo_name=ID)
108 # url('repo', repo_name=ID)
101 repo_model = RepoModel()
109 repo_model = RepoModel()
102 _form = RepoForm(edit=True)()
110 changed_name = repo_name
111 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
112
103 try:
113 try:
104 form_result = _form.to_python(dict(request.POST))
114 form_result = _form.to_python(dict(request.POST))
105 repo_model.update(repo_name, form_result)
115 repo_model.update(repo_name, form_result)
106 invalidate_cache('cached_repo_list')
116 invalidate_cache('cached_repo_list')
107 h.flash(_('Repository %s updated succesfully' % repo_name),
117 h.flash(_('Repository %s updated succesfully' % repo_name),
108 category='success')
118 category='success')
109
119 changed_name = form_result['repo_name']
110 except formencode.Invalid as errors:
120 except formencode.Invalid as errors:
111 c.repo_info = repo_model.get(repo_name)
121 c.repo_info = repo_model.get(repo_name)
112 c.users_array = repo_model.get_users_js()
122 c.users_array = repo_model.get_users_js()
113 errors.value.update({'user':c.repo_info.user.username})
123 errors.value.update({'user':c.repo_info.user.username})
114 c.form_errors = errors.error_dict
115 return htmlfill.render(
124 return htmlfill.render(
116 render('admin/repos/repo_edit.html'),
125 render('admin/repos/repo_edit.html'),
117 defaults=errors.value,
126 defaults=errors.value,
127 errors=errors.error_dict or {},
128 prefix_error=False,
118 encoding="UTF-8")
129 encoding="UTF-8")
130
119 except Exception:
131 except Exception:
132 log.error(traceback.format_exc())
120 h.flash(_('error occured during update of repository %s') \
133 h.flash(_('error occured during update of repository %s') \
121 % form_result['repo_name'], category='error')
134 % repo_name, category='error')
122 return redirect(url('repos'))
135
136
137 return redirect(url('edit_repo', repo_name=changed_name))
123
138
124 def delete(self, repo_name):
139 def delete(self, repo_name):
125 """DELETE /repos/repo_name: Delete an existing item"""
140 """DELETE /repos/repo_name: Delete an existing item"""
126 # Forms posted to this method should contain a hidden field:
141 # Forms posted to this method should contain a hidden field:
127 # <input type="hidden" name="_method" value="DELETE" />
142 # <input type="hidden" name="_method" value="DELETE" />
128 # Or using helpers:
143 # Or using helpers:
129 # h.form(url('repo', repo_name=ID),
144 # h.form(url('repo', repo_name=ID),
130 # method='delete')
145 # method='delete')
131 # url('repo', repo_name=ID)
146 # url('repo', repo_name=ID)
132
147
133 repo_model = RepoModel()
148 repo_model = RepoModel()
134 repo = repo_model.get(repo_name)
149 repo = repo_model.get(repo_name)
135 if not repo:
150 if not repo:
136 h.flash(_('%s repository is not mapped to db perhaps'
151 h.flash(_('%s repository is not mapped to db perhaps'
137 ' it was moved or renamed from the filesystem'
152 ' it was moved or renamed from the filesystem'
138 ' please run the application again'
153 ' please run the application again'
139 ' in order to rescan repositories') % repo_name,
154 ' in order to rescan repositories') % repo_name,
140 category='error')
155 category='error')
141
156
142 return redirect(url('repos'))
157 return redirect(url('repos'))
143 try:
158 try:
144 repo_model.delete(repo)
159 repo_model.delete(repo)
145 invalidate_cache('cached_repo_list')
160 invalidate_cache('cached_repo_list')
146 h.flash(_('deleted repository %s') % repo_name, category='success')
161 h.flash(_('deleted repository %s') % repo_name, category='success')
147 except Exception:
162 except Exception:
148 h.flash(_('An error occured during deletion of %s') % repo_name,
163 h.flash(_('An error occured during deletion of %s') % repo_name,
149 category='error')
164 category='error')
150
165
151 return redirect(url('repos'))
166 return redirect(url('repos'))
152
167
153 def delete_perm_user(self, repo_name):
168 def delete_perm_user(self, repo_name):
154 """
169 """
155 DELETE an existing repository permission user
170 DELETE an existing repository permission user
156 @param repo_name:
171 @param repo_name:
157 """
172 """
158
173
159 try:
174 try:
160 repo_model = RepoModel()
175 repo_model = RepoModel()
161 repo_model.delete_perm_user(request.POST, repo_name)
176 repo_model.delete_perm_user(request.POST, repo_name)
162 except Exception as e:
177 except Exception as e:
163 h.flash(_('An error occured during deletion of repository user'),
178 h.flash(_('An error occured during deletion of repository user'),
164 category='error')
179 category='error')
165
180
166
181
167 def show(self, repo_name, format='html'):
182 def show(self, repo_name, format='html'):
168 """GET /repos/repo_name: Show a specific item"""
183 """GET /repos/repo_name: Show a specific item"""
169 # url('repo', repo_name=ID)
184 # url('repo', repo_name=ID)
170
185
171 def edit(self, repo_name, format='html'):
186 def edit(self, repo_name, format='html'):
172 """GET /repos/repo_name/edit: Form to edit an existing item"""
187 """GET /repos/repo_name/edit: Form to edit an existing item"""
173 # url('edit_repo', repo_name=ID)
188 # url('edit_repo', repo_name=ID)
174 repo_model = RepoModel()
189 repo_model = RepoModel()
175 c.repo_info = repo = repo_model.get(repo_name)
190 c.repo_info = repo = repo_model.get(repo_name)
176 if not repo:
191 if not repo:
177 h.flash(_('%s repository is not mapped to db perhaps'
192 h.flash(_('%s repository is not mapped to db perhaps'
178 ' it was created or renamed from the filesystem'
193 ' it was created or renamed from the filesystem'
179 ' please run the application again'
194 ' please run the application again'
180 ' in order to rescan repositories') % repo_name,
195 ' in order to rescan repositories') % repo_name,
181 category='error')
196 category='error')
182
197
183 return redirect(url('repos'))
198 return redirect(url('repos'))
184 defaults = c.repo_info.__dict__
199 defaults = c.repo_info.__dict__
185 defaults.update({'user':c.repo_info.user.username})
200 defaults.update({'user':c.repo_info.user.username})
186 c.users_array = repo_model.get_users_js()
201 c.users_array = repo_model.get_users_js()
187
202
188 for p in c.repo_info.repo2perm:
203 for p in c.repo_info.repo2perm:
189 defaults.update({'perm_%s' % p.user.username:
204 defaults.update({'perm_%s' % p.user.username:
190 p.permission.permission_name})
205 p.permission.permission_name})
191
206
192 return htmlfill.render(
207 return htmlfill.render(
193 render('admin/repos/repo_edit.html'),
208 render('admin/repos/repo_edit.html'),
194 defaults=defaults,
209 defaults=defaults,
195 encoding="UTF-8",
210 encoding="UTF-8",
196 force_defaults=False
211 force_defaults=False
197 )
212 )
@@ -1,95 +1,98 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # settings controller for pylons
3 # settings controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
21 Created on June 30, 2010
22 settings controller for pylons
23 @author: marcink
24 """
25 from formencode import htmlfill
20 from formencode import htmlfill
26 from pylons import tmpl_context as c, request, url
21 from pylons import tmpl_context as c, request, url
27 from pylons.controllers.util import redirect
22 from pylons.controllers.util import redirect
28 from pylons.i18n.translation import _
23 from pylons.i18n.translation import _
29 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
24 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
30 from pylons_app.lib.base import BaseController, render
25 from pylons_app.lib.base import BaseController, render
31 from pylons_app.lib.utils import invalidate_cache
26 from pylons_app.lib.utils import invalidate_cache
32 from pylons_app.model.forms import RepoSettingsForm
27 from pylons_app.model.forms import RepoSettingsForm
33 from pylons_app.model.repo_model import RepoModel
28 from pylons_app.model.repo_model import RepoModel
34 import formencode
29 import formencode
35 import logging
30 import logging
36 import pylons_app.lib.helpers as h
31 import pylons_app.lib.helpers as h
32 import traceback
33 """
34 Created on June 30, 2010
35 settings controller for pylons
36 @author: marcink
37 """
37 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
38
39
39 class SettingsController(BaseController):
40 class SettingsController(BaseController):
40
41
41 @LoginRequired()
42 @LoginRequired()
42 @HasRepoPermissionAllDecorator('repository.admin')
43 @HasRepoPermissionAllDecorator('repository.admin')
43 def __before__(self):
44 def __before__(self):
44 super(SettingsController, self).__before__()
45 super(SettingsController, self).__before__()
45
46
46 def index(self, repo_name):
47 def index(self, repo_name):
47 repo_model = RepoModel()
48 repo_model = RepoModel()
48 c.repo_info = repo = repo_model.get(repo_name)
49 c.repo_info = repo = repo_model.get(repo_name)
49 if not repo:
50 if not repo:
50 h.flash(_('%s repository is not mapped to db perhaps'
51 h.flash(_('%s repository is not mapped to db perhaps'
51 ' it was created or renamed from the filesystem'
52 ' it was created or renamed from the filesystem'
52 ' please run the application again'
53 ' please run the application again'
53 ' in order to rescan repositories') % repo_name,
54 ' in order to rescan repositories') % repo_name,
54 category='error')
55 category='error')
55
56
56 return redirect(url('repos'))
57 return redirect(url('repos'))
57 defaults = c.repo_info.__dict__
58 defaults = c.repo_info.__dict__
58 defaults.update({'user':c.repo_info.user.username})
59 defaults.update({'user':c.repo_info.user.username})
59 c.users_array = repo_model.get_users_js()
60 c.users_array = repo_model.get_users_js()
60
61
61 for p in c.repo_info.repo2perm:
62 for p in c.repo_info.repo2perm:
62 defaults.update({'perm_%s' % p.user.username:
63 defaults.update({'perm_%s' % p.user.username:
63 p.permission.permission_name})
64 p.permission.permission_name})
64
65
65 return htmlfill.render(
66 return htmlfill.render(
66 render('settings/repo_settings.html'),
67 render('settings/repo_settings.html'),
67 defaults=defaults,
68 defaults=defaults,
68 encoding="UTF-8",
69 encoding="UTF-8",
69 force_defaults=False
70 force_defaults=False
70 )
71 )
71
72
72 def update(self, repo_name):
73 def update(self, repo_name):
73 repo_model = RepoModel()
74 repo_model = RepoModel()
74 _form = RepoSettingsForm(edit=True)()
75 _form = RepoSettingsForm(edit=True, old_data={'repo_name':repo_name})()
75 try:
76 try:
76 form_result = _form.to_python(dict(request.POST))
77 form_result = _form.to_python(dict(request.POST))
77 repo_model.update(repo_name, form_result)
78 repo_model.update(repo_name, form_result)
78 invalidate_cache('cached_repo_list')
79 invalidate_cache('cached_repo_list')
79 h.flash(_('Repository %s updated succesfully' % repo_name),
80 h.flash(_('Repository %s updated succesfully' % repo_name),
80 category='success')
81 category='success')
81
82
82 except formencode.Invalid as errors:
83 except formencode.Invalid as errors:
83 c.repo_info = repo_model.get(repo_name)
84 c.repo_info = repo_model.get(repo_name)
84 c.users_array = repo_model.get_users_js()
85 c.users_array = repo_model.get_users_js()
85 errors.value.update({'user':c.repo_info.user.username})
86 errors.value.update({'user':c.repo_info.user.username})
86 c.form_errors = errors.error_dict
87 return htmlfill.render(
87 return htmlfill.render(
88 render('admin/repos/repo_edit.html'),
88 render('settings/repo_settings.html'),
89 defaults=errors.value,
89 defaults=errors.value,
90 encoding="UTF-8")
90 errors=errors.error_dict or {},
91 prefix_error=False,
92 encoding="UTF-8")
91 except Exception:
93 except Exception:
94 log.error(traceback.format_exc())
92 h.flash(_('error occured during update of repository %s') \
95 h.flash(_('error occured during update of repository %s') \
93 % form_result['repo_name'], category='error')
96 % form_result['repo_name'], category='error')
94
97
95 return redirect(url('repo_settings_home', repo_name=repo_name))
98 return redirect(url('repo_settings_home', repo_name=form_result['repo_name']))
@@ -1,282 +1,289 b''
1 """ this is forms validation classes
1 """ this is forms validation classes
2 http://formencode.org/module-formencode.validators.html
2 http://formencode.org/module-formencode.validators.html
3 for list off all availible validators
3 for list off all availible validators
4
4
5 we can create our own validators
5 we can create our own validators
6
6
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 pre_validators [] These validators will be applied before the schema
8 pre_validators [] These validators will be applied before the schema
9 chained_validators [] These validators will be applied after the schema
9 chained_validators [] These validators will be applied after the schema
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14
14
15
15
16 <name> = formencode.validators.<name of validator>
16 <name> = formencode.validators.<name of validator>
17 <name> must equal form name
17 <name> must equal form name
18 list=[1,2,3,4,5]
18 list=[1,2,3,4,5]
19 for SELECT use formencode.All(OneOf(list), Int())
19 for SELECT use formencode.All(OneOf(list), Int())
20
20
21 """
21 """
22 from formencode import All
22 from formencode import All
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 Email, Bool, StringBoolean
24 Email, Bool, StringBoolean
25 from pylons import session
25 from pylons import session
26 from pylons.i18n.translation import _
26 from pylons.i18n.translation import _
27 from pylons_app.lib.auth import get_crypt_password
27 from pylons_app.lib.auth import get_crypt_password
28 import pylons_app.lib.helpers as h
28 import pylons_app.lib.helpers as h
29 from pylons_app.model import meta
29 from pylons_app.model import meta
30 from pylons_app.model.db import User, Repository
30 from pylons_app.model.db import User, Repository
31 from sqlalchemy.exc import OperationalError
31 from sqlalchemy.exc import OperationalError
32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
33 from webhelpers.pylonslib.secure_form import authentication_token
33 from webhelpers.pylonslib.secure_form import authentication_token
34 import datetime
34 import datetime
35 import formencode
35 import formencode
36 import logging
36 import logging
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39
39
40 #this is needed to translate the messages using _() in validators
40 #this is needed to translate the messages using _() in validators
41 class State_obj(object):
41 class State_obj(object):
42 _ = staticmethod(_)
42 _ = staticmethod(_)
43
43
44 #===============================================================================
44 #===============================================================================
45 # VALIDATORS
45 # VALIDATORS
46 #===============================================================================
46 #===============================================================================
47 class ValidAuthToken(formencode.validators.FancyValidator):
47 class ValidAuthToken(formencode.validators.FancyValidator):
48 messages = {'invalid_token':_('Token mismatch')}
48 messages = {'invalid_token':_('Token mismatch')}
49
49
50 def validate_python(self, value, state):
50 def validate_python(self, value, state):
51
51
52 if value != authentication_token():
52 if value != authentication_token():
53 raise formencode.Invalid(self.message('invalid_token', state,
53 raise formencode.Invalid(self.message('invalid_token', state,
54 search_number=value), value, state)
54 search_number=value), value, state)
55 class ValidUsername(formencode.validators.FancyValidator):
55 class ValidUsername(formencode.validators.FancyValidator):
56
56
57 def validate_python(self, value, state):
57 def validate_python(self, value, state):
58 if value in ['default', 'new_user']:
58 if value in ['default', 'new_user']:
59 raise formencode.Invalid(_('Invalid username'), value, state)
59 raise formencode.Invalid(_('Invalid username'), value, state)
60
60
61 class ValidPassword(formencode.validators.FancyValidator):
61 class ValidPassword(formencode.validators.FancyValidator):
62
62
63 def to_python(self, value, state):
63 def to_python(self, value, state):
64 if value:
64 if value:
65 return get_crypt_password(value)
65 return get_crypt_password(value)
66
66
67 class ValidAuth(formencode.validators.FancyValidator):
67 class ValidAuth(formencode.validators.FancyValidator):
68 messages = {
68 messages = {
69 'invalid_password':_('invalid password'),
69 'invalid_password':_('invalid password'),
70 'invalid_login':_('invalid user name'),
70 'invalid_login':_('invalid user name'),
71 'disabled_account':_('Your acccount is disabled')
71 'disabled_account':_('Your acccount is disabled')
72
72
73 }
73 }
74 #error mapping
74 #error mapping
75 e_dict = {'username':messages['invalid_login'],
75 e_dict = {'username':messages['invalid_login'],
76 'password':messages['invalid_password']}
76 'password':messages['invalid_password']}
77 e_dict_disable = {'username':messages['disabled_account']}
77 e_dict_disable = {'username':messages['disabled_account']}
78
78
79 def validate_python(self, value, state):
79 def validate_python(self, value, state):
80 sa = meta.Session
80 sa = meta.Session
81 crypted_passwd = get_crypt_password(value['password'])
81 crypted_passwd = get_crypt_password(value['password'])
82 username = value['username']
82 username = value['username']
83 try:
83 try:
84 user = sa.query(User).filter(User.username == username).one()
84 user = sa.query(User).filter(User.username == username).one()
85 except (NoResultFound, MultipleResultsFound, OperationalError) as e:
85 except (NoResultFound, MultipleResultsFound, OperationalError) as e:
86 log.error(e)
86 log.error(e)
87 user = None
87 user = None
88 raise formencode.Invalid(self.message('invalid_password',
88 raise formencode.Invalid(self.message('invalid_password',
89 state=State_obj), value, state,
89 state=State_obj), value, state,
90 error_dict=self.e_dict)
90 error_dict=self.e_dict)
91 if user:
91 if user:
92 if user.active:
92 if user.active:
93 if user.username == username and user.password == crypted_passwd:
93 if user.username == username and user.password == crypted_passwd:
94 from pylons_app.lib.auth import AuthUser
94 from pylons_app.lib.auth import AuthUser
95 auth_user = AuthUser()
95 auth_user = AuthUser()
96 auth_user.username = username
96 auth_user.username = username
97 auth_user.is_authenticated = True
97 auth_user.is_authenticated = True
98 auth_user.is_admin = user.admin
98 auth_user.is_admin = user.admin
99 auth_user.user_id = user.user_id
99 auth_user.user_id = user.user_id
100 auth_user.name = user.name
100 auth_user.name = user.name
101 auth_user.lastname = user.lastname
101 auth_user.lastname = user.lastname
102 session['hg_app_user'] = auth_user
102 session['hg_app_user'] = auth_user
103 session.save()
103 session.save()
104 log.info('user %s is now authenticated', username)
104 log.info('user %s is now authenticated', username)
105
105
106 try:
106 try:
107 user.last_login = datetime.datetime.now()
107 user.last_login = datetime.datetime.now()
108 sa.add(user)
108 sa.add(user)
109 sa.commit()
109 sa.commit()
110 except (OperationalError) as e:
110 except (OperationalError) as e:
111 log.error(e)
111 log.error(e)
112 sa.rollback()
112 sa.rollback()
113
113
114 return value
114 return value
115 else:
115 else:
116 log.warning('user %s not authenticated', username)
116 log.warning('user %s not authenticated', username)
117 raise formencode.Invalid(self.message('invalid_password',
117 raise formencode.Invalid(self.message('invalid_password',
118 state=State_obj), value, state,
118 state=State_obj), value, state,
119 error_dict=self.e_dict)
119 error_dict=self.e_dict)
120 else:
120 else:
121 log.warning('user %s is disabled', username)
121 log.warning('user %s is disabled', username)
122 raise formencode.Invalid(self.message('disabled_account',
122 raise formencode.Invalid(self.message('disabled_account',
123 state=State_obj),
123 state=State_obj),
124 value, state,
124 value, state,
125 error_dict=self.e_dict_disable)
125 error_dict=self.e_dict_disable)
126
126
127 meta.Session.remove()
127 meta.Session.remove()
128
129
128 class ValidRepoUser(formencode.validators.FancyValidator):
130 class ValidRepoUser(formencode.validators.FancyValidator):
129
131
130 def to_python(self, value, state):
132 def to_python(self, value, state):
131 sa = meta.Session
133 sa = meta.Session
132 try:
134 try:
133 self.user_db = sa.query(User)\
135 self.user_db = sa.query(User)\
134 .filter(User.active == True)\
136 .filter(User.active == True)\
135 .filter(User.username == value).one()
137 .filter(User.username == value).one()
136 except Exception:
138 except Exception:
137 raise formencode.Invalid(_('This username is not valid'),
139 raise formencode.Invalid(_('This username is not valid'),
138 value, state)
140 value, state)
141 meta.Session.remove()
139 return self.user_db.user_id
142 return self.user_db.user_id
140
143
141 def ValidRepoName(edit=False):
144 def ValidRepoName(edit, old_data):
142 class _ValidRepoName(formencode.validators.FancyValidator):
145 class _ValidRepoName(formencode.validators.FancyValidator):
143
146
144 def to_python(self, value, state):
147 def to_python(self, value, state):
145 slug = h.repo_name_slug(value)
148 slug = h.repo_name_slug(value)
146 if slug in ['_admin']:
149 if slug in ['_admin']:
147 raise formencode.Invalid(_('This repository name is disallowed'),
150 raise formencode.Invalid(_('This repository name is disallowed'),
148 value, state)
151 value, state)
149 sa = meta.Session
152
150 if sa.query(Repository).get(slug) and not edit:
153 if old_data.get('repo_name') != value or not edit:
151 raise formencode.Invalid(_('This repository already exists'),
154 sa = meta.Session
152 value, state)
155 if sa.query(Repository).get(slug):
153
156 raise formencode.Invalid(_('This repository already exists') ,
157 value, state)
158 meta.Session.remove()
154 return slug
159 return slug
160
161
155 return _ValidRepoName
162 return _ValidRepoName
156
163
157 class ValidPerms(formencode.validators.FancyValidator):
164 class ValidPerms(formencode.validators.FancyValidator):
158 messages = {'perm_new_user_name':_('This username is not valid')}
165 messages = {'perm_new_user_name':_('This username is not valid')}
159
166
160 def to_python(self, value, state):
167 def to_python(self, value, state):
161 perms_update = []
168 perms_update = []
162 perms_new = []
169 perms_new = []
163 #build a list of permission to update and new permission to create
170 #build a list of permission to update and new permission to create
164 for k, v in value.items():
171 for k, v in value.items():
165 if k.startswith('perm_'):
172 if k.startswith('perm_'):
166 if k.startswith('perm_new_user'):
173 if k.startswith('perm_new_user'):
167 new_perm = value.get('perm_new_user', False)
174 new_perm = value.get('perm_new_user', False)
168 new_user = value.get('perm_new_user_name', False)
175 new_user = value.get('perm_new_user_name', False)
169 if new_user and new_perm:
176 if new_user and new_perm:
170 if (new_user, new_perm) not in perms_new:
177 if (new_user, new_perm) not in perms_new:
171 perms_new.append((new_user, new_perm))
178 perms_new.append((new_user, new_perm))
172 else:
179 else:
173 usr = k[5:]
180 usr = k[5:]
174 if usr == 'default':
181 if usr == 'default':
175 if value['private']:
182 if value['private']:
176 #set none for default when updating to private repo
183 #set none for default when updating to private repo
177 v = 'repository.none'
184 v = 'repository.none'
178 perms_update.append((usr, v))
185 perms_update.append((usr, v))
179 value['perms_updates'] = perms_update
186 value['perms_updates'] = perms_update
180 value['perms_new'] = perms_new
187 value['perms_new'] = perms_new
181 sa = meta.Session
188 sa = meta.Session
182 for k, v in perms_new:
189 for k, v in perms_new:
183 try:
190 try:
184 self.user_db = sa.query(User)\
191 self.user_db = sa.query(User)\
185 .filter(User.active == True)\
192 .filter(User.active == True)\
186 .filter(User.username == k).one()
193 .filter(User.username == k).one()
187 except Exception:
194 except Exception:
188 msg = self.message('perm_new_user_name',
195 msg = self.message('perm_new_user_name',
189 state=State_obj)
196 state=State_obj)
190 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
197 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
191 return value
198 return value
192
199
193 class ValidSettings(formencode.validators.FancyValidator):
200 class ValidSettings(formencode.validators.FancyValidator):
194
201
195 def to_python(self, value, state):
202 def to_python(self, value, state):
196 #settings form can't edit user
203 #settings form can't edit user
197 if value.has_key('user'):
204 if value.has_key('user'):
198 del['value']['user']
205 del['value']['user']
199
206
200 return value
207 return value
201 #===============================================================================
208 #===============================================================================
202 # FORMS
209 # FORMS
203 #===============================================================================
210 #===============================================================================
204 class LoginForm(formencode.Schema):
211 class LoginForm(formencode.Schema):
205 allow_extra_fields = True
212 allow_extra_fields = True
206 filter_extra_fields = True
213 filter_extra_fields = True
207 username = UnicodeString(
214 username = UnicodeString(
208 strip=True,
215 strip=True,
209 min=3,
216 min=3,
210 not_empty=True,
217 not_empty=True,
211 messages={
218 messages={
212 'empty':_('Please enter a login'),
219 'empty':_('Please enter a login'),
213 'tooShort':_('Enter a value %(min)i characters long or more')}
220 'tooShort':_('Enter a value %(min)i characters long or more')}
214 )
221 )
215
222
216 password = UnicodeString(
223 password = UnicodeString(
217 strip=True,
224 strip=True,
218 min=3,
225 min=3,
219 not_empty=True,
226 not_empty=True,
220 messages={
227 messages={
221 'empty':_('Please enter a password'),
228 'empty':_('Please enter a password'),
222 'tooShort':_('Enter a value %(min)i characters long or more')}
229 'tooShort':_('Enter a value %(min)i characters long or more')}
223 )
230 )
224
231
225
232
226 #chained validators have access to all data
233 #chained validators have access to all data
227 chained_validators = [ValidAuth]
234 chained_validators = [ValidAuth]
228
235
229 def UserForm(edit=False):
236 def UserForm(edit=False):
230 class _UserForm(formencode.Schema):
237 class _UserForm(formencode.Schema):
231 allow_extra_fields = True
238 allow_extra_fields = True
232 filter_extra_fields = True
239 filter_extra_fields = True
233 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername)
240 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername)
234 if edit:
241 if edit:
235 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
242 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
236 admin = StringBoolean(if_missing=False)
243 admin = StringBoolean(if_missing=False)
237 else:
244 else:
238 password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
245 password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
239 active = StringBoolean(if_missing=False)
246 active = StringBoolean(if_missing=False)
240 name = UnicodeString(strip=True, min=3, not_empty=True)
247 name = UnicodeString(strip=True, min=3, not_empty=True)
241 lastname = UnicodeString(strip=True, min=3, not_empty=True)
248 lastname = UnicodeString(strip=True, min=3, not_empty=True)
242 email = Email(not_empty=True)
249 email = Email(not_empty=True)
243
250
244 return _UserForm
251 return _UserForm
245
252
246 def RepoForm(edit=False):
253 def RepoForm(edit=False, old_data={}):
247 class _RepoForm(formencode.Schema):
254 class _RepoForm(formencode.Schema):
248 allow_extra_fields = True
255 allow_extra_fields = True
249 filter_extra_fields = False
256 filter_extra_fields = False
250 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit))
257 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
251 description = UnicodeString(strip=True, min=3, not_empty=True)
258 description = UnicodeString(strip=True, min=3, not_empty=True)
252 private = StringBoolean(if_missing=False)
259 private = StringBoolean(if_missing=False)
253
260
254 if edit:
261 if edit:
255 user = All(Int(not_empty=True), ValidRepoUser)
262 user = All(Int(not_empty=True), ValidRepoUser)
256
263
257 chained_validators = [ValidPerms]
264 chained_validators = [ValidPerms]
258 return _RepoForm
265 return _RepoForm
259
266
260 def RepoSettingsForm(edit=False):
267 def RepoSettingsForm(edit=False, old_data={}):
261 class _RepoForm(formencode.Schema):
268 class _RepoForm(formencode.Schema):
262 allow_extra_fields = True
269 allow_extra_fields = True
263 filter_extra_fields = False
270 filter_extra_fields = False
264 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit))
271 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
265 description = UnicodeString(strip=True, min=3, not_empty=True)
272 description = UnicodeString(strip=True, min=3, not_empty=True)
266 private = StringBoolean(if_missing=False)
273 private = StringBoolean(if_missing=False)
267
274
268 chained_validators = [ValidPerms, ValidSettings]
275 chained_validators = [ValidPerms, ValidSettings]
269 return _RepoForm
276 return _RepoForm
270
277
271
278
272 def ApplicationSettingsForm():
279 def ApplicationSettingsForm():
273 class _ApplicationSettingsForm(formencode.Schema):
280 class _ApplicationSettingsForm(formencode.Schema):
274 allow_extra_fields = True
281 allow_extra_fields = True
275 filter_extra_fields = False
282 filter_extra_fields = False
276 app_title = UnicodeString(strip=True, min=3, not_empty=True)
283 app_title = UnicodeString(strip=True, min=3, not_empty=True)
277 app_auth_realm = UnicodeString(strip=True, min=3, not_empty=True)
284 app_auth_realm = UnicodeString(strip=True, min=3, not_empty=True)
278
285
279 return _ApplicationSettingsForm
286 return _ApplicationSettingsForm
280
287
281
288
282
289
@@ -1,165 +1,170 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # model for handling repositories actions
3 # model for handling repositories actions
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 # This program is free software; you can redistribute it and/or
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
7 # as published by the Free Software Foundation; version 2
8 # of the License or (at your opinion) any later version of the license.
8 # of the License or (at your opinion) any later version of the license.
9 #
9 #
10 # This program is distributed in the hope that it will be useful,
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
13 # GNU General Public License for more details.
14 #
14 #
15 # You should have received a copy of the GNU General Public License
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
18 # MA 02110-1301, USA.
19
19
20 """
20 """
21 Created on Jun 5, 2010
21 Created on Jun 5, 2010
22 model for handling repositories actions
22 model for handling repositories actions
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from pylons_app.model.meta import Session
25 from pylons_app.model.meta import Session
26 from pylons_app.model.db import Repository, Repo2Perm, User, Permission
26 from pylons_app.model.db import Repository, Repo2Perm, User, Permission
27 import shutil
27 import shutil
28 import os
28 import os
29 from datetime import datetime
29 from datetime import datetime
30 from pylons_app.lib.utils import check_repo
30 from pylons_app.lib.utils import check_repo
31 from pylons import app_globals as g
31 from pylons import app_globals as g
32 import traceback
32 import traceback
33 import logging
33 import logging
34 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
35
35
36 class RepoModel(object):
36 class RepoModel(object):
37
37
38 def __init__(self):
38 def __init__(self):
39 self.sa = Session()
39 self.sa = Session()
40
40
41 def get(self, id):
41 def get(self, id):
42 return self.sa.query(Repository).get(id)
42 return self.sa.query(Repository).get(id)
43
43
44 def get_users_js(self):
44 def get_users_js(self):
45
45
46 users = self.sa.query(User).filter(User.active == True).all()
46 users = self.sa.query(User).filter(User.active == True).all()
47 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
47 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
48 users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
48 users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
49 u.lastname, u.username)
49 u.lastname, u.username)
50 for u in users])
50 for u in users])
51 return users_array
51 return users_array
52
52
53
53
54 def update(self, repo_id, form_data):
54 def update(self, repo_id, form_data):
55 try:
55 try:
56 if repo_id != form_data['repo_name']:
56 if repo_id != form_data['repo_name']:
57 #rename our data
57 self.__rename_repo(repo_id, form_data['repo_name'])
58 self.__rename_repo(repo_id, form_data['repo_name'])
58 cur_repo = self.sa.query(Repository).get(repo_id)
59 cur_repo = self.sa.query(Repository).get(repo_id)
59 for k, v in form_data.items():
60 for k, v in form_data.items():
60 if k == 'user':
61 if k == 'user':
61 cur_repo.user_id = v
62 cur_repo.user_id = v
62 else:
63 else:
63 setattr(cur_repo, k, v)
64 setattr(cur_repo, k, v)
64
65
65 #update permissions
66 #update permissions
66 for username, perm in form_data['perms_updates']:
67 for username, perm in form_data['perms_updates']:
67 r2p = self.sa.query(Repo2Perm)\
68 r2p = self.sa.query(Repo2Perm)\
68 .filter(Repo2Perm.user == self.sa.query(User)\
69 .filter(Repo2Perm.user == self.sa.query(User)\
69 .filter(User.username == username).one())\
70 .filter(User.username == username).one())\
70 .filter(Repo2Perm.repository == repo_id).one()
71 .filter(Repo2Perm.repository == repo_id).one()
71
72
72 r2p.permission_id = self.sa.query(Permission).filter(
73 r2p.permission_id = self.sa.query(Permission).filter(
73 Permission.permission_name ==
74 Permission.permission_name ==
74 perm).one().permission_id
75 perm).one().permission_id
75 self.sa.add(r2p)
76 self.sa.add(r2p)
76
77
77 for username, perm in form_data['perms_new']:
78 for username, perm in form_data['perms_new']:
78 r2p = Repo2Perm()
79 r2p = Repo2Perm()
79 r2p.repository = repo_id
80 r2p.repository = repo_id
80 r2p.user = self.sa.query(User)\
81 r2p.user = self.sa.query(User)\
81 .filter(User.username == username).one()
82 .filter(User.username == username).one()
82
83
83 r2p.permission_id = self.sa.query(Permission).filter(
84 r2p.permission_id = self.sa.query(Permission).filter(
84 Permission.permission_name ==
85 Permission.permission_name ==
85 perm).one().permission_id
86 perm).one().permission_id
86 self.sa.add(r2p)
87 self.sa.add(r2p)
87
88
88 self.sa.add(cur_repo)
89 self.sa.add(cur_repo)
89 self.sa.commit()
90 self.sa.commit()
90 except:
91 except:
91 log.error(traceback.format_exc())
92 log.error(traceback.format_exc())
92 self.sa.rollback()
93 self.sa.rollback()
93 raise
94 raise
94
95
95 def create(self, form_data, cur_user, just_db=False):
96 def create(self, form_data, cur_user, just_db=False):
96 try:
97 try:
97 repo_name = form_data['repo_name']
98 repo_name = form_data['repo_name']
98 new_repo = Repository()
99 new_repo = Repository()
99 for k, v in form_data.items():
100 for k, v in form_data.items():
100 setattr(new_repo, k, v)
101 setattr(new_repo, k, v)
101
102
102 new_repo.user_id = cur_user.user_id
103 new_repo.user_id = cur_user.user_id
103 self.sa.add(new_repo)
104 self.sa.add(new_repo)
104
105
105 #create default permission
106 #create default permission
106 repo2perm = Repo2Perm()
107 repo2perm = Repo2Perm()
107 default_perm = 'repository.none' if form_data['private'] \
108 default_perm = 'repository.none' if form_data['private'] \
108 else 'repository.read'
109 else 'repository.read'
109 repo2perm.permission_id = self.sa.query(Permission)\
110 repo2perm.permission_id = self.sa.query(Permission)\
110 .filter(Permission.permission_name == default_perm)\
111 .filter(Permission.permission_name == default_perm)\
111 .one().permission_id
112 .one().permission_id
112
113
113 repo2perm.repository = repo_name
114 repo2perm.repository = repo_name
114 repo2perm.user_id = self.sa.query(User)\
115 repo2perm.user_id = self.sa.query(User)\
115 .filter(User.username == 'default').one().user_id
116 .filter(User.username == 'default').one().user_id
116
117
117 self.sa.add(repo2perm)
118 self.sa.add(repo2perm)
118 self.sa.commit()
119 self.sa.commit()
119 if not just_db:
120 if not just_db:
120 self.__create_repo(repo_name)
121 self.__create_repo(repo_name)
121 except:
122 except:
122 log.error(traceback.format_exc())
123 log.error(traceback.format_exc())
123 self.sa.rollback()
124 self.sa.rollback()
124 raise
125 raise
125
126
126 def delete(self, repo):
127 def delete(self, repo):
127 try:
128 try:
128 self.sa.delete(repo)
129 self.sa.delete(repo)
129 self.sa.commit()
130 self.sa.commit()
130 self.__delete_repo(repo.repo_name)
131 self.__delete_repo(repo.repo_name)
131 except:
132 except:
132 log.error(traceback.format_exc())
133 log.error(traceback.format_exc())
133 self.sa.rollback()
134 self.sa.rollback()
134 raise
135 raise
135 def delete_perm_user(self, form_data, repo_name):
136 def delete_perm_user(self, form_data, repo_name):
136 try:
137 try:
137 r2p = self.sa.query(Repo2Perm).filter(Repo2Perm.repository == repo_name)\
138 r2p = self.sa.query(Repo2Perm).filter(Repo2Perm.repository == repo_name)\
138 .filter(Repo2Perm.user_id == form_data['user_id']).delete()
139 .filter(Repo2Perm.user_id == form_data['user_id']).delete()
139 self.sa.commit()
140 self.sa.commit()
140 except:
141 except:
141 log.error(traceback.format_exc())
142 log.error(traceback.format_exc())
142 self.sa.rollback()
143 self.sa.rollback()
143 raise
144 raise
144
145
145 def __create_repo(self, repo_name):
146 def __create_repo(self, repo_name):
146 repo_path = os.path.join(g.base_path, repo_name)
147 repo_path = os.path.join(g.base_path, repo_name)
147 if check_repo(repo_name, g.base_path):
148 if check_repo(repo_name, g.base_path):
148 log.info('creating repo %s in %s', repo_name, repo_path)
149 log.info('creating repo %s in %s', repo_name, repo_path)
149 from vcs.backends.hg import MercurialRepository
150 from vcs.backends.hg import MercurialRepository
150 MercurialRepository(repo_path, create=True)
151 MercurialRepository(repo_path, create=True)
151
152
152 def __rename_repo(self, old, new):
153 def __rename_repo(self, old, new):
153 log.info('renaming repoo from %s to %s', old, new)
154 log.info('renaming repo from %s to %s', old, new)
155
154 old_path = os.path.join(g.base_path, old)
156 old_path = os.path.join(g.base_path, old)
155 new_path = os.path.join(g.base_path, new)
157 new_path = os.path.join(g.base_path, new)
158 if os.path.isdir(new_path):
159 raise Exception('Was trying to rename to already existing dir %s',
160 new_path)
156 shutil.move(old_path, new_path)
161 shutil.move(old_path, new_path)
157
162
158 def __delete_repo(self, name):
163 def __delete_repo(self, name):
159 rm_path = os.path.join(g.base_path, name)
164 rm_path = os.path.join(g.base_path, name)
160 log.info("Removing %s", rm_path)
165 log.info("Removing %s", rm_path)
161 #disable hg
166 #disable hg
162 shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
167 shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
163 #disable repo
168 #disable repo
164 shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
169 shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
165 % (datetime.today(), name)))
170 % (datetime.today(), name)))
General Comments 0
You need to be logged in to leave comments. Login now