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