##// END OF EJS Templates
#56 implemented users groups editing,...
marcink -
r972:2c8fd849 beta
parent child Browse files
Show More
@@ -1,124 +1,178 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.users_groups
3 rhodecode.controllers.admin.users_groups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Users Groups crud controller for pylons
6 Users Groups crud controller for pylons
7
7
8 :created_on: Jan 25, 2011
8 :created_on: Jan 25, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 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
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 import logging
28 import logging
29 import traceback
29 import traceback
30 import formencode
30 import formencode
31
31
32 from formencode import htmlfill
32 from formencode import htmlfill
33 from pylons import request, session, tmpl_context as c, url, config
33 from pylons import request, session, tmpl_context as c, url, config
34 from pylons.controllers.util import abort, redirect
34 from pylons.controllers.util import abort, redirect
35 from pylons.i18n.translation import _
35 from pylons.i18n.translation import _
36
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
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 fill_perms
40 fill_perms
41 from rhodecode.lib.base import BaseController, render
41 from rhodecode.lib.base import BaseController, render
42
42
43 from rhodecode.model.db import User, UsersGroup
43 from rhodecode.model.db import User, UsersGroup
44 from rhodecode.model.forms import UserForm, UsersGroupForm
44 from rhodecode.model.forms import UserForm, UsersGroupForm
45 from rhodecode.model.user import UserModel
45 from rhodecode.model.user import UserModel
46 from rhodecode.model.users_group import UsersGroupModel
46 from rhodecode.model.users_group import UsersGroupModel
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50 class UsersGroupsController(BaseController):
50 class UsersGroupsController(BaseController):
51 """REST Controller styled on the Atom Publishing Protocol"""
51 """REST Controller styled on the Atom Publishing Protocol"""
52 # To properly map this controller, ensure your config/routing.py
52 # To properly map this controller, ensure your config/routing.py
53 # file has a resource setup:
53 # file has a resource setup:
54 # map.resource('users_group', 'users_groups')
54 # map.resource('users_group', 'users_groups')
55
55
56 @LoginRequired()
56 @LoginRequired()
57 @HasPermissionAllDecorator('hg.admin')
57 @HasPermissionAllDecorator('hg.admin')
58 def __before__(self):
58 def __before__(self):
59 c.admin_user = session.get('admin_user')
59 c.admin_user = session.get('admin_user')
60 c.admin_username = session.get('admin_username')
60 c.admin_username = session.get('admin_username')
61 super(UsersGroupsController, self).__before__()
61 super(UsersGroupsController, self).__before__()
62 c.available_permissions = config['available_permissions']
62 c.available_permissions = config['available_permissions']
63
63
64 def index(self, format='html'):
64 def index(self, format='html'):
65 """GET /users_groups: All items in the collection"""
65 """GET /users_groups: All items in the collection"""
66 # url('users_groups')
66 # url('users_groups')
67 c.users_groups_list = self.sa.query(UsersGroup).all()
67 c.users_groups_list = self.sa.query(UsersGroup).all()
68 return render('admin/users_groups/users_groups.html')
68 return render('admin/users_groups/users_groups.html')
69
69
70 def create(self):
70 def create(self):
71 """POST /users_groups: Create a new item"""
71 """POST /users_groups: Create a new item"""
72 # url('users_groups')
72 # url('users_groups')
73 users_group_model = UsersGroupModel()
73 users_group_model = UsersGroupModel()
74 users_group_form = UsersGroupForm()()
74 users_group_form = UsersGroupForm()()
75 try:
75 try:
76 form_result = users_group_form.to_python(dict(request.POST))
76 form_result = users_group_form.to_python(dict(request.POST))
77 users_group_model.create(form_result)
77 users_group_model.create(form_result)
78 h.flash(_('created users group %s') % form_result['users_group_name'],
78 h.flash(_('created users group %s') % form_result['users_group_name'],
79 category='success')
79 category='success')
80 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
80 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
81 except formencode.Invalid, errors:
81 except formencode.Invalid, errors:
82 return htmlfill.render(
82 return htmlfill.render(
83 render('admin/users_groups/users_group_add.html'),
83 render('admin/users_groups/users_group_add.html'),
84 defaults=errors.value,
84 defaults=errors.value,
85 errors=errors.error_dict or {},
85 errors=errors.error_dict or {},
86 prefix_error=False,
86 prefix_error=False,
87 encoding="UTF-8")
87 encoding="UTF-8")
88 except Exception:
88 except Exception:
89 log.error(traceback.format_exc())
89 log.error(traceback.format_exc())
90 h.flash(_('error occurred during creation of users group %s') \
90 h.flash(_('error occurred during creation of users group %s') \
91 % request.POST.get('users_group_name'), category='error')
91 % request.POST.get('users_group_name'), category='error')
92
92
93 return redirect(url('users_groups'))
93 return redirect(url('users_groups'))
94
94
95 def new(self, format='html'):
95 def new(self, format='html'):
96 """GET /users_groups/new: Form to create a new item"""
96 """GET /users_groups/new: Form to create a new item"""
97 # url('new_users_group')
97 # url('new_users_group')
98 return render('admin/users_groups/users_group_add.html')
98 return render('admin/users_groups/users_group_add.html')
99
99
100 def update(self, id):
100 def update(self, id):
101 """PUT /users_groups/id: Update an existing item"""
101 """PUT /users_groups/id: Update an existing item"""
102 # Forms posted to this method should contain a hidden field:
102 # Forms posted to this method should contain a hidden field:
103 # <input type="hidden" name="_method" value="PUT" />
103 # <input type="hidden" name="_method" value="PUT" />
104 # Or using helpers:
104 # Or using helpers:
105 # h.form(url('users_group', id=ID),
105 # h.form(url('users_group', id=ID),
106 # method='put')
106 # method='put')
107 # url('users_group', id=ID)
107 # url('users_group', id=ID)
108
108
109
110 users_group_model = UsersGroupModel()
111 c.users_group = users_group_model.get(id)
112 c.group_members = [(x.user_id, x.user.username) for x in
113 c.users_group.members]
114
115 c.available_members = [(x.user_id, x.username) for x in
116 self.sa.query(User).all()]
117 users_group_form = UsersGroupForm(edit=True,
118 old_data=c.users_group.get_dict(),
119 available_members=[str(x[0]) for x
120 in c.available_members])()
121
122 try:
123 form_result = users_group_form.to_python(request.POST)
124 users_group_model.update(id, form_result)
125 h.flash(_('updated users group %s') % form_result['users_group_name'],
126 category='success')
127 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
128 except formencode.Invalid, errors:
129 return htmlfill.render(
130 render('admin/users_groups/users_group_edit.html'),
131 defaults=errors.value,
132 errors=errors.error_dict or {},
133 prefix_error=False,
134 encoding="UTF-8")
135 except Exception:
136 log.error(traceback.format_exc())
137 h.flash(_('error occurred during update of users group %s') \
138 % request.POST.get('users_group_name'), category='error')
139
140 return redirect(url('users_groups'))
141
142
143
109 def delete(self, id):
144 def delete(self, id):
110 """DELETE /users_groups/id: Delete an existing item"""
145 """DELETE /users_groups/id: Delete an existing item"""
111 # Forms posted to this method should contain a hidden field:
146 # Forms posted to this method should contain a hidden field:
112 # <input type="hidden" name="_method" value="DELETE" />
147 # <input type="hidden" name="_method" value="DELETE" />
113 # Or using helpers:
148 # Or using helpers:
114 # h.form(url('users_group', id=ID),
149 # h.form(url('users_group', id=ID),
115 # method='delete')
150 # method='delete')
116 # url('users_group', id=ID)
151 # url('users_group', id=ID)
117
152
118 def show(self, id, format='html'):
153 def show(self, id, format='html'):
119 """GET /users_groups/id: Show a specific item"""
154 """GET /users_groups/id: Show a specific item"""
120 # url('users_group', id=ID)
155 # url('users_group', id=ID)
121
156
122 def edit(self, id, format='html'):
157 def edit(self, id, format='html'):
123 """GET /users_groups/id/edit: Form to edit an existing item"""
158 """GET /users_groups/id/edit: Form to edit an existing item"""
124 # url('edit_users_group', id=ID)
159 # url('edit_users_group', id=ID)
160
161 c.users_group = self.sa.query(UsersGroup).get(id)
162 if not c.users_group:
163 return redirect(url('users_groups'))
164
165 c.users_group.permissions = {}
166 c.group_members = [(x.user_id, x.user.username) for x in
167 c.users_group.members]
168 print c.group_members, 'x' * 100
169 c.available_members = [(x.user_id, x.username) for x in
170 self.sa.query(User).all()]
171 defaults = c.users_group.get_dict()
172
173 return htmlfill.render(
174 render('admin/users_groups/users_group_edit.html'),
175 defaults=defaults,
176 encoding="UTF-8",
177 force_defaults=False
178 )
@@ -1,331 +1,335 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.db
3 rhodecode.model.db
4 ~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~
5
5
6 Database Models for RhodeCode
6 Database Models for RhodeCode
7
7
8 :created_on: Apr 08, 2010
8 :created_on: Apr 08, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 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
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27 import logging
27 import logging
28 import datetime
28 import datetime
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.exc import DatabaseError
31 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.orm import relation, backref, class_mapper
32 from sqlalchemy.orm import relationship, backref, class_mapper
33 from sqlalchemy.orm.session import Session
33 from sqlalchemy.orm.session import Session
34
34
35 from rhodecode.model.meta import Base
35 from rhodecode.model.meta import Base
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39 class BaseModel(object):
39 class BaseModel(object):
40
40
41 @classmethod
41 @classmethod
42 def _get_keys(cls):
42 def _get_keys(cls):
43 """return column names for this model """
43 """return column names for this model """
44 return class_mapper(cls).c.keys()
44 return class_mapper(cls).c.keys()
45
45
46 def get_dict(self):
46 def get_dict(self):
47 """return dict with keys and values corresponding
47 """return dict with keys and values corresponding
48 to this model data """
48 to this model data """
49
49
50 d = {}
50 d = {}
51 for k in self._get_keys():
51 for k in self._get_keys():
52 d[k] = getattr(self, k)
52 d[k] = getattr(self, k)
53 return d
53 return d
54
54
55 def get_appstruct(self):
55 def get_appstruct(self):
56 """return list with keys and values tupples corresponding
56 """return list with keys and values tupples corresponding
57 to this model data """
57 to this model data """
58
58
59 l = []
59 l = []
60 for k in self._get_keys():
60 for k in self._get_keys():
61 l.append((k, getattr(self, k),))
61 l.append((k, getattr(self, k),))
62 return l
62 return l
63
63
64 def populate_obj(self, populate_dict):
64 def populate_obj(self, populate_dict):
65 """populate model with data from given populate_dict"""
65 """populate model with data from given populate_dict"""
66
66
67 for k in self._get_keys():
67 for k in self._get_keys():
68 if k in populate_dict:
68 if k in populate_dict:
69 setattr(self, k, populate_dict[k])
69 setattr(self, k, populate_dict[k])
70
70
71 class RhodeCodeSettings(Base, BaseModel):
71 class RhodeCodeSettings(Base, BaseModel):
72 __tablename__ = 'rhodecode_settings'
72 __tablename__ = 'rhodecode_settings'
73 __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
73 __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
74 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
74 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
75 app_settings_name = Column("app_settings_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
75 app_settings_name = Column("app_settings_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
76 app_settings_value = Column("app_settings_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
76 app_settings_value = Column("app_settings_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
77
77
78 def __init__(self, k='', v=''):
78 def __init__(self, k='', v=''):
79 self.app_settings_name = k
79 self.app_settings_name = k
80 self.app_settings_value = v
80 self.app_settings_value = v
81
81
82 def __repr__(self):
82 def __repr__(self):
83 return "<%s('%s:%s')>" % (self.__class__.__name__,
83 return "<%s('%s:%s')>" % (self.__class__.__name__,
84 self.app_settings_name, self.app_settings_value)
84 self.app_settings_name, self.app_settings_value)
85
85
86 class RhodeCodeUi(Base, BaseModel):
86 class RhodeCodeUi(Base, BaseModel):
87 __tablename__ = 'rhodecode_ui'
87 __tablename__ = 'rhodecode_ui'
88 __table_args__ = {'useexisting':True}
88 __table_args__ = {'useexisting':True}
89 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
89 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
90 ui_section = Column("ui_section", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
90 ui_section = Column("ui_section", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
91 ui_key = Column("ui_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
91 ui_key = Column("ui_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
92 ui_value = Column("ui_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
92 ui_value = Column("ui_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
93 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
93 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
94
94
95
95
96 class User(Base, BaseModel):
96 class User(Base, BaseModel):
97 __tablename__ = 'users'
97 __tablename__ = 'users'
98 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
98 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
99 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
99 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
100 username = Column("username", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
100 username = Column("username", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
101 password = Column("password", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
101 password = Column("password", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
102 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
102 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
103 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
103 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
104 name = Column("name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
104 name = Column("name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
105 lastname = Column("lastname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
105 lastname = Column("lastname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
106 email = Column("email", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
106 email = Column("email", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
107 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
107 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
108 is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
108 is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
109
109
110 user_log = relation('UserLog', cascade='all')
110 user_log = relationship('UserLog', cascade='all')
111 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
111 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
112
112
113 repositories = relation('Repository')
113 repositories = relationship('Repository')
114 user_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
114 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
115
115
116 @property
116 @property
117 def full_contact(self):
117 def full_contact(self):
118 return '%s %s <%s>' % (self.name, self.lastname, self.email)
118 return '%s %s <%s>' % (self.name, self.lastname, self.email)
119
119
120
120
121 @property
121 @property
122 def is_admin(self):
122 def is_admin(self):
123 return self.admin
123 return self.admin
124
124
125 def __repr__(self):
125 def __repr__(self):
126 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
126 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
127 self.user_id, self.username)
127 self.user_id, self.username)
128
128
129 def update_lastlogin(self):
129 def update_lastlogin(self):
130 """Update user lastlogin"""
130 """Update user lastlogin"""
131
131
132 try:
132 try:
133 session = Session.object_session(self)
133 session = Session.object_session(self)
134 self.last_login = datetime.datetime.now()
134 self.last_login = datetime.datetime.now()
135 session.add(self)
135 session.add(self)
136 session.commit()
136 session.commit()
137 log.debug('updated user %s lastlogin', self.username)
137 log.debug('updated user %s lastlogin', self.username)
138 except (DatabaseError,):
138 except (DatabaseError,):
139 session.rollback()
139 session.rollback()
140
140
141
141
142 class UserLog(Base, BaseModel):
142 class UserLog(Base, BaseModel):
143 __tablename__ = 'user_logs'
143 __tablename__ = 'user_logs'
144 __table_args__ = {'useexisting':True}
144 __table_args__ = {'useexisting':True}
145 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
145 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
146 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
146 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
147 repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
147 repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
148 repository_name = Column("repository_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
148 repository_name = Column("repository_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
149 user_ip = Column("user_ip", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
149 user_ip = Column("user_ip", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
150 action = Column("action", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
150 action = Column("action", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
151 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
151 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
152
152
153 user = relation('User')
153 user = relationship('User')
154 repository = relation('Repository')
154 repository = relationship('Repository')
155
155
156
156
157 class UsersGroup(Base, BaseModel):
157 class UsersGroup(Base, BaseModel):
158 __tablename__ = 'users_groups'
158 __tablename__ = 'users_groups'
159 __table_args__ = {'useexisting':True}
159 __table_args__ = {'useexisting':True}
160
160
161 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
161 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
162 users_group_name = Column("users_group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
162 users_group_name = Column("users_group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
163 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
163 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
164
164
165 members = relation('UsersGroupMember')
165 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan")
166
166
167 class UsersGroupMember(Base, BaseModel):
167 class UsersGroupMember(Base, BaseModel):
168 __tablename__ = 'users_groups_members'
168 __tablename__ = 'users_groups_members'
169 __table_args__ = {'useexisting':True}
169 __table_args__ = {'useexisting':True}
170
170
171 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
171 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
172 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
172 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
173 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
173 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
174
174
175 user = relation('User')
175 user = relationship('User')
176 users_group = relation('UsersGroup')
176 users_group = relationship('UsersGroup')
177
178 def __init__(self, gr_id, u_id):
179 self.users_group_id = gr_id
180 self.user_id = u_id
177
181
178 class Repository(Base, BaseModel):
182 class Repository(Base, BaseModel):
179 __tablename__ = 'repositories'
183 __tablename__ = 'repositories'
180 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
184 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
181 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
185 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
182 repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
186 repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
183 repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
187 repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
184 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
188 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
185 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
189 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
186 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
190 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
187 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
191 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
188 description = Column("description", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
192 description = Column("description", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
189 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
193 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
190 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
194 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
191
195
192 user = relation('User')
196 user = relationship('User')
193 fork = relation('Repository', remote_side=repo_id)
197 fork = relationship('Repository', remote_side=repo_id)
194 group = relation('Group')
198 group = relationship('Group')
195 repo_to_perm = relation('RepoToPerm', cascade='all')
199 repo_to_perm = relationship('RepoToPerm', cascade='all')
196 stats = relation('Statistics', cascade='all', uselist=False)
200 stats = relationship('Statistics', cascade='all', uselist=False)
197
201
198 repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
202 repo_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
199
203
200 def __repr__(self):
204 def __repr__(self):
201 return "<%s('%s:%s')>" % (self.__class__.__name__,
205 return "<%s('%s:%s')>" % (self.__class__.__name__,
202 self.repo_id, self.repo_name)
206 self.repo_id, self.repo_name)
203
207
204 class Group(Base, BaseModel):
208 class Group(Base, BaseModel):
205 __tablename__ = 'groups'
209 __tablename__ = 'groups'
206 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
210 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
207
211
208 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
212 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
209 group_name = Column("group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
213 group_name = Column("group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
210 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
214 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
211
215
212 parent_group = relation('Group', remote_side=group_id)
216 parent_group = relationship('Group', remote_side=group_id)
213
217
214
218
215 def __init__(self, group_name='', parent_group=None):
219 def __init__(self, group_name='', parent_group=None):
216 self.group_name = group_name
220 self.group_name = group_name
217 self.parent_group = parent_group
221 self.parent_group = parent_group
218
222
219 def __repr__(self):
223 def __repr__(self):
220 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
224 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
221 self.group_name)
225 self.group_name)
222
226
223 class Permission(Base, BaseModel):
227 class Permission(Base, BaseModel):
224 __tablename__ = 'permissions'
228 __tablename__ = 'permissions'
225 __table_args__ = {'useexisting':True}
229 __table_args__ = {'useexisting':True}
226 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
230 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
227 permission_name = Column("permission_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
231 permission_name = Column("permission_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
228 permission_longname = Column("permission_longname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
232 permission_longname = Column("permission_longname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
229
233
230 def __repr__(self):
234 def __repr__(self):
231 return "<%s('%s:%s')>" % (self.__class__.__name__,
235 return "<%s('%s:%s')>" % (self.__class__.__name__,
232 self.permission_id, self.permission_name)
236 self.permission_id, self.permission_name)
233
237
234 class RepoToPerm(Base, BaseModel):
238 class RepoToPerm(Base, BaseModel):
235 __tablename__ = 'repo_to_perm'
239 __tablename__ = 'repo_to_perm'
236 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
240 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
237 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
241 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
238 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
242 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
239 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
243 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
240 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
244 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
241
245
242 user = relation('User')
246 user = relationship('User')
243 permission = relation('Permission')
247 permission = relationship('Permission')
244 repository = relation('Repository')
248 repository = relationship('Repository')
245
249
246 class UserToPerm(Base, BaseModel):
250 class UserToPerm(Base, BaseModel):
247 __tablename__ = 'user_to_perm'
251 __tablename__ = 'user_to_perm'
248 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
252 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
249 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
253 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
250 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
254 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
251 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
255 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
252
256
253 user = relation('User')
257 user = relationship('User')
254 permission = relation('Permission')
258 permission = relationship('Permission')
255
259
256 class UsersGroupToPerm(Base, BaseModel):
260 class UsersGroupToPerm(Base, BaseModel):
257 __tablename__ = 'users_group_to_perm'
261 __tablename__ = 'users_group_to_perm'
258 __table_args__ = (UniqueConstraint('users_group_id', 'permission_id'), {'useexisting':True})
262 __table_args__ = (UniqueConstraint('users_group_id', 'permission_id'), {'useexisting':True})
259 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
263 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
260 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
264 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
261 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
265 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
262
266
263 users_group = relation('UsersGroup')
267 users_group = relationship('UsersGroup')
264 permission = relation('Permission')
268 permission = relationship('Permission')
265
269
266 class GroupToPerm(Base, BaseModel):
270 class GroupToPerm(Base, BaseModel):
267 __tablename__ = 'group_to_perm'
271 __tablename__ = 'group_to_perm'
268 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
272 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
269
273
270 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
274 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
271 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
275 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
272 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
276 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
273 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
277 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
274
278
275 user = relation('User')
279 user = relationship('User')
276 permission = relation('Permission')
280 permission = relationship('Permission')
277 group = relation('Group')
281 group = relationship('Group')
278
282
279 class Statistics(Base, BaseModel):
283 class Statistics(Base, BaseModel):
280 __tablename__ = 'statistics'
284 __tablename__ = 'statistics'
281 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
285 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
282 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
286 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
283 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
287 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
284 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
288 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
285 commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
289 commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
286 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
290 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
287 languages = Column("languages", LargeBinary(), nullable=False)#JSON data
291 languages = Column("languages", LargeBinary(), nullable=False)#JSON data
288
292
289 repository = relation('Repository', single_parent=True)
293 repository = relationship('Repository', single_parent=True)
290
294
291 class UserFollowing(Base, BaseModel):
295 class UserFollowing(Base, BaseModel):
292 __tablename__ = 'user_followings'
296 __tablename__ = 'user_followings'
293 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
297 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
294 UniqueConstraint('user_id', 'follows_user_id')
298 UniqueConstraint('user_id', 'follows_user_id')
295 , {'useexisting':True})
299 , {'useexisting':True})
296
300
297 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
301 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
298 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
302 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
299 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
303 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
300 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
304 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
301
305
302 user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
306 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
303
307
304 follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
308 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
305 follows_repository = relation('Repository')
309 follows_repository = relationship('Repository')
306
310
307 class CacheInvalidation(Base, BaseModel):
311 class CacheInvalidation(Base, BaseModel):
308 __tablename__ = 'cache_invalidation'
312 __tablename__ = 'cache_invalidation'
309 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
313 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
310 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
314 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
311 cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
315 cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
312 cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
316 cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
313 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
317 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
314
318
315
319
316 def __init__(self, cache_key, cache_args=''):
320 def __init__(self, cache_key, cache_args=''):
317 self.cache_key = cache_key
321 self.cache_key = cache_key
318 self.cache_args = cache_args
322 self.cache_args = cache_args
319 self.cache_active = False
323 self.cache_active = False
320
324
321 def __repr__(self):
325 def __repr__(self):
322 return "<%s('%s:%s')>" % (self.__class__.__name__,
326 return "<%s('%s:%s')>" % (self.__class__.__name__,
323 self.cache_id, self.cache_key)
327 self.cache_id, self.cache_key)
324
328
325 class DbMigrateVersion(Base, BaseModel):
329 class DbMigrateVersion(Base, BaseModel):
326 __tablename__ = 'db_migrate_version'
330 __tablename__ = 'db_migrate_version'
327 __table_args__ = {'useexisting':True}
331 __table_args__ = {'useexisting':True}
328 repository_id = Column('repository_id', String(250), primary_key=True)
332 repository_id = Column('repository_id', String(250), primary_key=True)
329 repository_path = Column('repository_path', Text)
333 repository_path = Column('repository_path', Text)
330 version = Column('version', Integer)
334 version = Column('version', Integer)
331
335
@@ -1,531 +1,537 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 import os
22 import os
23 import re
23 import re
24 import logging
24 import logging
25
25
26 import formencode
26 import formencode
27 from formencode import All
27 from formencode import All
28 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
28 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
29 Email, Bool, StringBoolean
29 Email, Bool, StringBoolean, Set
30
30
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 import rhodecode.lib.helpers as h
33 import rhodecode.lib.helpers as h
34 from rhodecode.lib.auth import authenticate, get_crypt_password
34 from rhodecode.lib.auth import authenticate, get_crypt_password
35 from rhodecode.lib.exceptions import LdapImportError
35 from rhodecode.lib.exceptions import LdapImportError
36 from rhodecode.model import meta
36 from rhodecode.model import meta
37 from rhodecode.model.user import UserModel
37 from rhodecode.model.user import UserModel
38 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.users_group import UsersGroupModel
39 from rhodecode.model.users_group import UsersGroupModel
40 from rhodecode.model.db import User
40 from rhodecode.model.db import User
41 from rhodecode import BACKENDS
41 from rhodecode import BACKENDS
42
42
43 from webhelpers.pylonslib.secure_form import authentication_token
43 from webhelpers.pylonslib.secure_form import authentication_token
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47 #this is needed to translate the messages using _() in validators
47 #this is needed to translate the messages using _() in validators
48 class State_obj(object):
48 class State_obj(object):
49 _ = staticmethod(_)
49 _ = staticmethod(_)
50
50
51 #===============================================================================
51 #===============================================================================
52 # VALIDATORS
52 # VALIDATORS
53 #===============================================================================
53 #===============================================================================
54 class ValidAuthToken(formencode.validators.FancyValidator):
54 class ValidAuthToken(formencode.validators.FancyValidator):
55 messages = {'invalid_token':_('Token mismatch')}
55 messages = {'invalid_token':_('Token mismatch')}
56
56
57 def validate_python(self, value, state):
57 def validate_python(self, value, state):
58
58
59 if value != authentication_token():
59 if value != authentication_token():
60 raise formencode.Invalid(self.message('invalid_token', state,
60 raise formencode.Invalid(self.message('invalid_token', state,
61 search_number=value), value, state)
61 search_number=value), value, state)
62
62
63 def ValidUsername(edit, old_data):
63 def ValidUsername(edit, old_data):
64 class _ValidUsername(formencode.validators.FancyValidator):
64 class _ValidUsername(formencode.validators.FancyValidator):
65
65
66 def validate_python(self, value, state):
66 def validate_python(self, value, state):
67 if value in ['default', 'new_user']:
67 if value in ['default', 'new_user']:
68 raise formencode.Invalid(_('Invalid username'), value, state)
68 raise formencode.Invalid(_('Invalid username'), value, state)
69 #check if user is unique
69 #check if user is unique
70 old_un = None
70 old_un = None
71 if edit:
71 if edit:
72 old_un = UserModel().get(old_data.get('user_id')).username
72 old_un = UserModel().get(old_data.get('user_id')).username
73
73
74 if old_un != value or not edit:
74 if old_un != value or not edit:
75 if UserModel().get_by_username(value, cache=False,
75 if UserModel().get_by_username(value, cache=False,
76 case_insensitive=True):
76 case_insensitive=True):
77 raise formencode.Invalid(_('This username already exists') ,
77 raise formencode.Invalid(_('This username already exists') ,
78 value, state)
78 value, state)
79
79
80
80
81 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
81 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
82 raise formencode.Invalid(_('Username may only contain '
82 raise formencode.Invalid(_('Username may only contain '
83 'alphanumeric characters underscores, '
83 'alphanumeric characters underscores, '
84 'periods or dashes and must begin with '
84 'periods or dashes and must begin with '
85 'alphanumeric character'),
85 'alphanumeric character'),
86 value, state)
86 value, state)
87
87
88
88
89
89
90 return _ValidUsername
90 return _ValidUsername
91
91
92
92
93
93
94 def ValidUsersGroup(edit, old_data):
94 def ValidUsersGroup(edit, old_data):
95
95
96 class _ValidUsersGroup(formencode.validators.FancyValidator):
96 class _ValidUsersGroup(formencode.validators.FancyValidator):
97
97
98 def validate_python(self, value, state):
98 def validate_python(self, value, state):
99 if value in ['default']:
99 if value in ['default']:
100 raise formencode.Invalid(_('Invalid group name'), value, state)
100 raise formencode.Invalid(_('Invalid group name'), value, state)
101 #check if group is unique
101 #check if group is unique
102 old_un = None
102 old_ugname = None
103 if edit:
103 if edit:
104 old_un = UserModel().get(old_data.get('users_group_id')).username
104 old_ugname = UsersGroupModel()\
105 .get(old_data.get('users_group_id')).users_group_name
105
106
106 if old_un != value or not edit:
107 if old_ugname != value or not edit:
107 if UsersGroupModel().get_by_groupname(value, cache=False,
108 if UsersGroupModel().get_by_groupname(value, cache=False,
108 case_insensitive=True):
109 case_insensitive=True):
109 raise formencode.Invalid(_('This users group already exists') ,
110 raise formencode.Invalid(_('This users group already exists') ,
110 value, state)
111 value, state)
111
112
112
113
113 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
114 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
114 raise formencode.Invalid(_('Group name may only contain '
115 raise formencode.Invalid(_('Group name may only contain '
115 'alphanumeric characters underscores, '
116 'alphanumeric characters underscores, '
116 'periods or dashes and must begin with '
117 'periods or dashes and must begin with '
117 'alphanumeric character'),
118 'alphanumeric character'),
118 value, state)
119 value, state)
119
120
120 return _ValidUsersGroup
121 return _ValidUsersGroup
121
122
122
123
123
124
124 class ValidPassword(formencode.validators.FancyValidator):
125 class ValidPassword(formencode.validators.FancyValidator):
125
126
126 def to_python(self, value, state):
127 def to_python(self, value, state):
127
128
128 if value:
129 if value:
129
130
130 if value.get('password'):
131 if value.get('password'):
131 try:
132 try:
132 value['password'] = get_crypt_password(value['password'])
133 value['password'] = get_crypt_password(value['password'])
133 except UnicodeEncodeError:
134 except UnicodeEncodeError:
134 e_dict = {'password':_('Invalid characters in password')}
135 e_dict = {'password':_('Invalid characters in password')}
135 raise formencode.Invalid('', value, state, error_dict=e_dict)
136 raise formencode.Invalid('', value, state, error_dict=e_dict)
136
137
137 if value.get('password_confirmation'):
138 if value.get('password_confirmation'):
138 try:
139 try:
139 value['password_confirmation'] = \
140 value['password_confirmation'] = \
140 get_crypt_password(value['password_confirmation'])
141 get_crypt_password(value['password_confirmation'])
141 except UnicodeEncodeError:
142 except UnicodeEncodeError:
142 e_dict = {'password_confirmation':_('Invalid characters in password')}
143 e_dict = {'password_confirmation':_('Invalid characters in password')}
143 raise formencode.Invalid('', value, state, error_dict=e_dict)
144 raise formencode.Invalid('', value, state, error_dict=e_dict)
144
145
145 if value.get('new_password'):
146 if value.get('new_password'):
146 try:
147 try:
147 value['new_password'] = \
148 value['new_password'] = \
148 get_crypt_password(value['new_password'])
149 get_crypt_password(value['new_password'])
149 except UnicodeEncodeError:
150 except UnicodeEncodeError:
150 e_dict = {'new_password':_('Invalid characters in password')}
151 e_dict = {'new_password':_('Invalid characters in password')}
151 raise formencode.Invalid('', value, state, error_dict=e_dict)
152 raise formencode.Invalid('', value, state, error_dict=e_dict)
152
153
153 return value
154 return value
154
155
155 class ValidPasswordsMatch(formencode.validators.FancyValidator):
156 class ValidPasswordsMatch(formencode.validators.FancyValidator):
156
157
157 def validate_python(self, value, state):
158 def validate_python(self, value, state):
158
159
159 if value['password'] != value['password_confirmation']:
160 if value['password'] != value['password_confirmation']:
160 e_dict = {'password_confirmation':
161 e_dict = {'password_confirmation':
161 _('Password do not match')}
162 _('Password do not match')}
162 raise formencode.Invalid('', value, state, error_dict=e_dict)
163 raise formencode.Invalid('', value, state, error_dict=e_dict)
163
164
164 class ValidAuth(formencode.validators.FancyValidator):
165 class ValidAuth(formencode.validators.FancyValidator):
165 messages = {
166 messages = {
166 'invalid_password':_('invalid password'),
167 'invalid_password':_('invalid password'),
167 'invalid_login':_('invalid user name'),
168 'invalid_login':_('invalid user name'),
168 'disabled_account':_('Your account is disabled')
169 'disabled_account':_('Your account is disabled')
169
170
170 }
171 }
171 #error mapping
172 #error mapping
172 e_dict = {'username':messages['invalid_login'],
173 e_dict = {'username':messages['invalid_login'],
173 'password':messages['invalid_password']}
174 'password':messages['invalid_password']}
174 e_dict_disable = {'username':messages['disabled_account']}
175 e_dict_disable = {'username':messages['disabled_account']}
175
176
176 def validate_python(self, value, state):
177 def validate_python(self, value, state):
177 password = value['password']
178 password = value['password']
178 username = value['username']
179 username = value['username']
179 user = UserModel().get_by_username(username)
180 user = UserModel().get_by_username(username)
180
181
181 if authenticate(username, password):
182 if authenticate(username, password):
182 return value
183 return value
183 else:
184 else:
184 if user and user.active is False:
185 if user and user.active is False:
185 log.warning('user %s is disabled', username)
186 log.warning('user %s is disabled', username)
186 raise formencode.Invalid(self.message('disabled_account',
187 raise formencode.Invalid(self.message('disabled_account',
187 state=State_obj),
188 state=State_obj),
188 value, state,
189 value, state,
189 error_dict=self.e_dict_disable)
190 error_dict=self.e_dict_disable)
190 else:
191 else:
191 log.warning('user %s not authenticated', username)
192 log.warning('user %s not authenticated', username)
192 raise formencode.Invalid(self.message('invalid_password',
193 raise formencode.Invalid(self.message('invalid_password',
193 state=State_obj), value, state,
194 state=State_obj), value, state,
194 error_dict=self.e_dict)
195 error_dict=self.e_dict)
195
196
196 class ValidRepoUser(formencode.validators.FancyValidator):
197 class ValidRepoUser(formencode.validators.FancyValidator):
197
198
198 def to_python(self, value, state):
199 def to_python(self, value, state):
199 sa = meta.Session()
200 sa = meta.Session()
200 try:
201 try:
201 self.user_db = sa.query(User)\
202 self.user_db = sa.query(User)\
202 .filter(User.active == True)\
203 .filter(User.active == True)\
203 .filter(User.username == value).one()
204 .filter(User.username == value).one()
204 except Exception:
205 except Exception:
205 raise formencode.Invalid(_('This username is not valid'),
206 raise formencode.Invalid(_('This username is not valid'),
206 value, state)
207 value, state)
207 finally:
208 finally:
208 meta.Session.remove()
209 meta.Session.remove()
209
210
210 return self.user_db.user_id
211 return self.user_db.user_id
211
212
212 def ValidRepoName(edit, old_data):
213 def ValidRepoName(edit, old_data):
213 class _ValidRepoName(formencode.validators.FancyValidator):
214 class _ValidRepoName(formencode.validators.FancyValidator):
214
215
215 def to_python(self, value, state):
216 def to_python(self, value, state):
216 slug = h.repo_name_slug(value)
217 slug = h.repo_name_slug(value)
217 if slug in ['_admin']:
218 if slug in ['_admin']:
218 raise formencode.Invalid(_('This repository name is disallowed'),
219 raise formencode.Invalid(_('This repository name is disallowed'),
219 value, state)
220 value, state)
220 if old_data.get('repo_name') != value or not edit:
221 if old_data.get('repo_name') != value or not edit:
221 if RepoModel().get_by_repo_name(slug, cache=False):
222 if RepoModel().get_by_repo_name(slug, cache=False):
222 raise formencode.Invalid(_('This repository already exists') ,
223 raise formencode.Invalid(_('This repository already exists') ,
223 value, state)
224 value, state)
224 return slug
225 return slug
225
226
226
227
227 return _ValidRepoName
228 return _ValidRepoName
228
229
229 def ValidForkType(old_data):
230 def ValidForkType(old_data):
230 class _ValidForkType(formencode.validators.FancyValidator):
231 class _ValidForkType(formencode.validators.FancyValidator):
231
232
232 def to_python(self, value, state):
233 def to_python(self, value, state):
233 if old_data['repo_type'] != value:
234 if old_data['repo_type'] != value:
234 raise formencode.Invalid(_('Fork have to be the same type as original'),
235 raise formencode.Invalid(_('Fork have to be the same type as original'),
235 value, state)
236 value, state)
236 return value
237 return value
237 return _ValidForkType
238 return _ValidForkType
238
239
239 class ValidPerms(formencode.validators.FancyValidator):
240 class ValidPerms(formencode.validators.FancyValidator):
240 messages = {'perm_new_user_name':_('This username is not valid')}
241 messages = {'perm_new_user_name':_('This username is not valid')}
241
242
242 def to_python(self, value, state):
243 def to_python(self, value, state):
243 perms_update = []
244 perms_update = []
244 perms_new = []
245 perms_new = []
245 #build a list of permission to update and new permission to create
246 #build a list of permission to update and new permission to create
246 for k, v in value.items():
247 for k, v in value.items():
247 if k.startswith('perm_'):
248 if k.startswith('perm_'):
248 if k.startswith('perm_new_user'):
249 if k.startswith('perm_new_user'):
249 new_perm = value.get('perm_new_user', False)
250 new_perm = value.get('perm_new_user', False)
250 new_user = value.get('perm_new_user_name', False)
251 new_user = value.get('perm_new_user_name', False)
251 if new_user and new_perm:
252 if new_user and new_perm:
252 if (new_user, new_perm) not in perms_new:
253 if (new_user, new_perm) not in perms_new:
253 perms_new.append((new_user, new_perm))
254 perms_new.append((new_user, new_perm))
254 else:
255 else:
255 usr = k[5:]
256 usr = k[5:]
256 if usr == 'default':
257 if usr == 'default':
257 if value['private']:
258 if value['private']:
258 #set none for default when updating to private repo
259 #set none for default when updating to private repo
259 v = 'repository.none'
260 v = 'repository.none'
260 perms_update.append((usr, v))
261 perms_update.append((usr, v))
261 value['perms_updates'] = perms_update
262 value['perms_updates'] = perms_update
262 value['perms_new'] = perms_new
263 value['perms_new'] = perms_new
263 sa = meta.Session
264 sa = meta.Session
264 for k, v in perms_new:
265 for k, v in perms_new:
265 try:
266 try:
266 self.user_db = sa.query(User)\
267 self.user_db = sa.query(User)\
267 .filter(User.active == True)\
268 .filter(User.active == True)\
268 .filter(User.username == k).one()
269 .filter(User.username == k).one()
269 except Exception:
270 except Exception:
270 msg = self.message('perm_new_user_name',
271 msg = self.message('perm_new_user_name',
271 state=State_obj)
272 state=State_obj)
272 raise formencode.Invalid(msg, value, state,
273 raise formencode.Invalid(msg, value, state,
273 error_dict={'perm_new_user_name':msg})
274 error_dict={'perm_new_user_name':msg})
274 return value
275 return value
275
276
276 class ValidSettings(formencode.validators.FancyValidator):
277 class ValidSettings(formencode.validators.FancyValidator):
277
278
278 def to_python(self, value, state):
279 def to_python(self, value, state):
279 #settings form can't edit user
280 #settings form can't edit user
280 if value.has_key('user'):
281 if value.has_key('user'):
281 del['value']['user']
282 del['value']['user']
282
283
283 return value
284 return value
284
285
285 class ValidPath(formencode.validators.FancyValidator):
286 class ValidPath(formencode.validators.FancyValidator):
286 def to_python(self, value, state):
287 def to_python(self, value, state):
287
288
288 if not os.path.isdir(value):
289 if not os.path.isdir(value):
289 msg = _('This is not a valid path')
290 msg = _('This is not a valid path')
290 raise formencode.Invalid(msg, value, state,
291 raise formencode.Invalid(msg, value, state,
291 error_dict={'paths_root_path':msg})
292 error_dict={'paths_root_path':msg})
292 return value
293 return value
293
294
294 def UniqSystemEmail(old_data):
295 def UniqSystemEmail(old_data):
295 class _UniqSystemEmail(formencode.validators.FancyValidator):
296 class _UniqSystemEmail(formencode.validators.FancyValidator):
296 def to_python(self, value, state):
297 def to_python(self, value, state):
297 value = value.lower()
298 value = value.lower()
298 if old_data.get('email') != value:
299 if old_data.get('email') != value:
299 sa = meta.Session()
300 sa = meta.Session()
300 try:
301 try:
301 user = sa.query(User).filter(User.email == value).scalar()
302 user = sa.query(User).filter(User.email == value).scalar()
302 if user:
303 if user:
303 raise formencode.Invalid(_("This e-mail address is already taken") ,
304 raise formencode.Invalid(_("This e-mail address is already taken") ,
304 value, state)
305 value, state)
305 finally:
306 finally:
306 meta.Session.remove()
307 meta.Session.remove()
307
308
308 return value
309 return value
309
310
310 return _UniqSystemEmail
311 return _UniqSystemEmail
311
312
312 class ValidSystemEmail(formencode.validators.FancyValidator):
313 class ValidSystemEmail(formencode.validators.FancyValidator):
313 def to_python(self, value, state):
314 def to_python(self, value, state):
314 value = value.lower()
315 value = value.lower()
315 sa = meta.Session
316 sa = meta.Session
316 try:
317 try:
317 user = sa.query(User).filter(User.email == value).scalar()
318 user = sa.query(User).filter(User.email == value).scalar()
318 if user is None:
319 if user is None:
319 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
320 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
320 value, state)
321 value, state)
321 finally:
322 finally:
322 meta.Session.remove()
323 meta.Session.remove()
323
324
324 return value
325 return value
325
326
326 class LdapLibValidator(formencode.validators.FancyValidator):
327 class LdapLibValidator(formencode.validators.FancyValidator):
327
328
328 def to_python(self, value, state):
329 def to_python(self, value, state):
329
330
330 try:
331 try:
331 import ldap
332 import ldap
332 except ImportError:
333 except ImportError:
333 raise LdapImportError
334 raise LdapImportError
334 return value
335 return value
335
336
336 class BaseDnValidator(formencode.validators.FancyValidator):
337 class BaseDnValidator(formencode.validators.FancyValidator):
337
338
338 def to_python(self, value, state):
339 def to_python(self, value, state):
339
340
340 try:
341 try:
341 value % {'user':'valid'}
342 value % {'user':'valid'}
342
343
343 if value.find('%(user)s') == -1:
344 if value.find('%(user)s') == -1:
344 raise formencode.Invalid(_("You need to specify %(user)s in "
345 raise formencode.Invalid(_("You need to specify %(user)s in "
345 "template for example uid=%(user)s "
346 "template for example uid=%(user)s "
346 ",dc=company...") ,
347 ",dc=company...") ,
347 value, state)
348 value, state)
348
349
349 except KeyError:
350 except KeyError:
350 raise formencode.Invalid(_("Wrong template used, only %(user)s "
351 raise formencode.Invalid(_("Wrong template used, only %(user)s "
351 "is an valid entry") ,
352 "is an valid entry") ,
352 value, state)
353 value, state)
353
354
354 return value
355 return value
355
356
356 #===============================================================================
357 #===============================================================================
357 # FORMS
358 # FORMS
358 #===============================================================================
359 #===============================================================================
359 class LoginForm(formencode.Schema):
360 class LoginForm(formencode.Schema):
360 allow_extra_fields = True
361 allow_extra_fields = True
361 filter_extra_fields = True
362 filter_extra_fields = True
362 username = UnicodeString(
363 username = UnicodeString(
363 strip=True,
364 strip=True,
364 min=1,
365 min=1,
365 not_empty=True,
366 not_empty=True,
366 messages={
367 messages={
367 'empty':_('Please enter a login'),
368 'empty':_('Please enter a login'),
368 'tooShort':_('Enter a value %(min)i characters long or more')}
369 'tooShort':_('Enter a value %(min)i characters long or more')}
369 )
370 )
370
371
371 password = UnicodeString(
372 password = UnicodeString(
372 strip=True,
373 strip=True,
373 min=6,
374 min=6,
374 not_empty=True,
375 not_empty=True,
375 messages={
376 messages={
376 'empty':_('Please enter a password'),
377 'empty':_('Please enter a password'),
377 'tooShort':_('Enter %(min)i characters or more')}
378 'tooShort':_('Enter %(min)i characters or more')}
378 )
379 )
379
380
380
381
381 #chained validators have access to all data
382 #chained validators have access to all data
382 chained_validators = [ValidAuth]
383 chained_validators = [ValidAuth]
383
384
384 def UserForm(edit=False, old_data={}):
385 def UserForm(edit=False, old_data={}):
385 class _UserForm(formencode.Schema):
386 class _UserForm(formencode.Schema):
386 allow_extra_fields = True
387 allow_extra_fields = True
387 filter_extra_fields = True
388 filter_extra_fields = True
388 username = All(UnicodeString(strip=True, min=1, not_empty=True),
389 username = All(UnicodeString(strip=True, min=1, not_empty=True),
389 ValidUsername(edit, old_data))
390 ValidUsername(edit, old_data))
390 if edit:
391 if edit:
391 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
392 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
392 admin = StringBoolean(if_missing=False)
393 admin = StringBoolean(if_missing=False)
393 else:
394 else:
394 password = All(UnicodeString(strip=True, min=6, not_empty=True))
395 password = All(UnicodeString(strip=True, min=6, not_empty=True))
395 active = StringBoolean(if_missing=False)
396 active = StringBoolean(if_missing=False)
396 name = UnicodeString(strip=True, min=1, not_empty=True)
397 name = UnicodeString(strip=True, min=1, not_empty=True)
397 lastname = UnicodeString(strip=True, min=1, not_empty=True)
398 lastname = UnicodeString(strip=True, min=1, not_empty=True)
398 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
399 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
399
400
400 chained_validators = [ValidPassword]
401 chained_validators = [ValidPassword]
401
402
402 return _UserForm
403 return _UserForm
403
404
404
405
405 def UsersGroupForm(edit=False, old_data={}):
406 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
406 class _UsersGroupForm(formencode.Schema):
407 class _UsersGroupForm(formencode.Schema):
407 allow_extra_fields = True
408 allow_extra_fields = True
408 filter_extra_fields = True
409 filter_extra_fields = True
409
410
410 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
411 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
411 ValidUsersGroup(edit, old_data))
412 ValidUsersGroup(edit, old_data))
412
413
413 users_group_active = StringBoolean(if_missing=False)
414 users_group_active = StringBoolean(if_missing=False)
414
415
416 if edit:
417 users_group_members = OneOf(available_members, hideList=False,
418 testValueList=True,
419 if_missing=None, not_empty=False)
420
415 return _UsersGroupForm
421 return _UsersGroupForm
416
422
417 def RegisterForm(edit=False, old_data={}):
423 def RegisterForm(edit=False, old_data={}):
418 class _RegisterForm(formencode.Schema):
424 class _RegisterForm(formencode.Schema):
419 allow_extra_fields = True
425 allow_extra_fields = True
420 filter_extra_fields = True
426 filter_extra_fields = True
421 username = All(ValidUsername(edit, old_data),
427 username = All(ValidUsername(edit, old_data),
422 UnicodeString(strip=True, min=1, not_empty=True))
428 UnicodeString(strip=True, min=1, not_empty=True))
423 password = All(UnicodeString(strip=True, min=6, not_empty=True))
429 password = All(UnicodeString(strip=True, min=6, not_empty=True))
424 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
430 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
425 active = StringBoolean(if_missing=False)
431 active = StringBoolean(if_missing=False)
426 name = UnicodeString(strip=True, min=1, not_empty=True)
432 name = UnicodeString(strip=True, min=1, not_empty=True)
427 lastname = UnicodeString(strip=True, min=1, not_empty=True)
433 lastname = UnicodeString(strip=True, min=1, not_empty=True)
428 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
434 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
429
435
430 chained_validators = [ValidPasswordsMatch, ValidPassword]
436 chained_validators = [ValidPasswordsMatch, ValidPassword]
431
437
432 return _RegisterForm
438 return _RegisterForm
433
439
434 def PasswordResetForm():
440 def PasswordResetForm():
435 class _PasswordResetForm(formencode.Schema):
441 class _PasswordResetForm(formencode.Schema):
436 allow_extra_fields = True
442 allow_extra_fields = True
437 filter_extra_fields = True
443 filter_extra_fields = True
438 email = All(ValidSystemEmail(), Email(not_empty=True))
444 email = All(ValidSystemEmail(), Email(not_empty=True))
439 return _PasswordResetForm
445 return _PasswordResetForm
440
446
441 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
447 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
442 class _RepoForm(formencode.Schema):
448 class _RepoForm(formencode.Schema):
443 allow_extra_fields = True
449 allow_extra_fields = True
444 filter_extra_fields = False
450 filter_extra_fields = False
445 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
451 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
446 ValidRepoName(edit, old_data))
452 ValidRepoName(edit, old_data))
447 description = UnicodeString(strip=True, min=1, not_empty=True)
453 description = UnicodeString(strip=True, min=1, not_empty=True)
448 private = StringBoolean(if_missing=False)
454 private = StringBoolean(if_missing=False)
449 enable_statistics = StringBoolean(if_missing=False)
455 enable_statistics = StringBoolean(if_missing=False)
450 enable_downloads = StringBoolean(if_missing=False)
456 enable_downloads = StringBoolean(if_missing=False)
451 repo_type = OneOf(supported_backends)
457 repo_type = OneOf(supported_backends)
452 if edit:
458 if edit:
453 user = All(Int(not_empty=True), ValidRepoUser)
459 user = All(Int(not_empty=True), ValidRepoUser)
454
460
455 chained_validators = [ValidPerms]
461 chained_validators = [ValidPerms]
456 return _RepoForm
462 return _RepoForm
457
463
458 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
464 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
459 class _RepoForkForm(formencode.Schema):
465 class _RepoForkForm(formencode.Schema):
460 allow_extra_fields = True
466 allow_extra_fields = True
461 filter_extra_fields = False
467 filter_extra_fields = False
462 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
468 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
463 ValidRepoName(edit, old_data))
469 ValidRepoName(edit, old_data))
464 description = UnicodeString(strip=True, min=1, not_empty=True)
470 description = UnicodeString(strip=True, min=1, not_empty=True)
465 private = StringBoolean(if_missing=False)
471 private = StringBoolean(if_missing=False)
466 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
472 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
467 return _RepoForkForm
473 return _RepoForkForm
468
474
469 def RepoSettingsForm(edit=False, old_data={}):
475 def RepoSettingsForm(edit=False, old_data={}):
470 class _RepoForm(formencode.Schema):
476 class _RepoForm(formencode.Schema):
471 allow_extra_fields = True
477 allow_extra_fields = True
472 filter_extra_fields = False
478 filter_extra_fields = False
473 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
479 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
474 ValidRepoName(edit, old_data))
480 ValidRepoName(edit, old_data))
475 description = UnicodeString(strip=True, min=1, not_empty=True)
481 description = UnicodeString(strip=True, min=1, not_empty=True)
476 private = StringBoolean(if_missing=False)
482 private = StringBoolean(if_missing=False)
477
483
478 chained_validators = [ValidPerms, ValidSettings]
484 chained_validators = [ValidPerms, ValidSettings]
479 return _RepoForm
485 return _RepoForm
480
486
481
487
482 def ApplicationSettingsForm():
488 def ApplicationSettingsForm():
483 class _ApplicationSettingsForm(formencode.Schema):
489 class _ApplicationSettingsForm(formencode.Schema):
484 allow_extra_fields = True
490 allow_extra_fields = True
485 filter_extra_fields = False
491 filter_extra_fields = False
486 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
492 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
487 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
493 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
488 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
494 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
489
495
490 return _ApplicationSettingsForm
496 return _ApplicationSettingsForm
491
497
492 def ApplicationUiSettingsForm():
498 def ApplicationUiSettingsForm():
493 class _ApplicationUiSettingsForm(formencode.Schema):
499 class _ApplicationUiSettingsForm(formencode.Schema):
494 allow_extra_fields = True
500 allow_extra_fields = True
495 filter_extra_fields = False
501 filter_extra_fields = False
496 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
502 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
497 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
503 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
498 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
504 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
499 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
505 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
500 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
506 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
501 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
507 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
502
508
503 return _ApplicationUiSettingsForm
509 return _ApplicationUiSettingsForm
504
510
505 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
511 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
506 class _DefaultPermissionsForm(formencode.Schema):
512 class _DefaultPermissionsForm(formencode.Schema):
507 allow_extra_fields = True
513 allow_extra_fields = True
508 filter_extra_fields = True
514 filter_extra_fields = True
509 overwrite_default = StringBoolean(if_missing=False)
515 overwrite_default = StringBoolean(if_missing=False)
510 anonymous = OneOf(['True', 'False'], if_missing=False)
516 anonymous = OneOf(['True', 'False'], if_missing=False)
511 default_perm = OneOf(perms_choices)
517 default_perm = OneOf(perms_choices)
512 default_register = OneOf(register_choices)
518 default_register = OneOf(register_choices)
513 default_create = OneOf(create_choices)
519 default_create = OneOf(create_choices)
514
520
515 return _DefaultPermissionsForm
521 return _DefaultPermissionsForm
516
522
517
523
518 def LdapSettingsForm():
524 def LdapSettingsForm():
519 class _LdapSettingsForm(formencode.Schema):
525 class _LdapSettingsForm(formencode.Schema):
520 allow_extra_fields = True
526 allow_extra_fields = True
521 filter_extra_fields = True
527 filter_extra_fields = True
522 pre_validators = [LdapLibValidator]
528 pre_validators = [LdapLibValidator]
523 ldap_active = StringBoolean(if_missing=False)
529 ldap_active = StringBoolean(if_missing=False)
524 ldap_host = UnicodeString(strip=True,)
530 ldap_host = UnicodeString(strip=True,)
525 ldap_port = Number(strip=True,)
531 ldap_port = Number(strip=True,)
526 ldap_ldaps = StringBoolean(if_missing=False)
532 ldap_ldaps = StringBoolean(if_missing=False)
527 ldap_dn_user = UnicodeString(strip=True,)
533 ldap_dn_user = UnicodeString(strip=True,)
528 ldap_dn_pass = UnicodeString(strip=True,)
534 ldap_dn_pass = UnicodeString(strip=True,)
529 ldap_base_dn = All(BaseDnValidator, UnicodeString(strip=True,))
535 ldap_base_dn = All(BaseDnValidator, UnicodeString(strip=True,))
530
536
531 return _LdapSettingsForm
537 return _LdapSettingsForm
@@ -1,79 +1,101 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user_group
3 rhodecode.model.user_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 users groups model for RhodeCode
6 users groups model for RhodeCode
7
7
8 :created_on: Jan 25, 2011
8 :created_on: Jan 25, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 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
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 import logging
28 import logging
29 import traceback
29 import traceback
30
30
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 from rhodecode.model import BaseModel
33 from rhodecode.model import BaseModel
34 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.caching_query import FromCache
35 from rhodecode.model.db import UsersGroup
35 from rhodecode.model.db import UsersGroup, UsersGroupMember
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38
36
39 from sqlalchemy.exc import DatabaseError
37 from sqlalchemy.exc import DatabaseError
40
38
41 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
42
40
43
41
44 class UsersGroupModel(BaseModel):
42 class UsersGroupModel(BaseModel):
45
43
46 def get(self, users_group_id, cache=False):
44 def get(self, users_group_id, cache=False):
47 users_group = self.sa.query(UsersGroup)
45 users_group = self.sa.query(UsersGroup)
48 if cache:
46 if cache:
49 users_group = users_group.options(FromCache("sql_cache_short",
47 users_group = users_group.options(FromCache("sql_cache_short",
50 "get_users_group_%s" % users_group_id))
48 "get_users_group_%s" % users_group_id))
51 return users_group.get(users_group_id)
49 return users_group.get(users_group_id)
52
50
53
51
54 def get_by_groupname(self, users_group_name, cache=False, case_insensitive=False):
52 def get_by_groupname(self, users_group_name, cache=False,
53 case_insensitive=False):
55
54
56 if case_insensitive:
55 if case_insensitive:
57 user = self.sa.query(UsersGroup)\
56 user = self.sa.query(UsersGroup)\
58 .filter(UsersGroup.users_group_name.ilike(users_group_name))
57 .filter(UsersGroup.users_group_name.ilike(users_group_name))
59 else:
58 else:
60 user = self.sa.query(UsersGroup)\
59 user = self.sa.query(UsersGroup)\
61 .filter(UsersGroup.users_group_name == users_group_name)
60 .filter(UsersGroup.users_group_name == users_group_name)
62 if cache:
61 if cache:
63 user = user.options(FromCache("sql_cache_short",
62 user = user.options(FromCache("sql_cache_short",
64 "get_user_%s" % users_group_name))
63 "get_user_%s" % users_group_name))
65 return user.scalar()
64 return user.scalar()
66
65
67 def create(self, form_data):
66 def create(self, form_data):
68 try:
67 try:
69 new_users_group = UsersGroup()
68 new_users_group = UsersGroup()
70 for k, v in form_data.items():
69 for k, v in form_data.items():
71 setattr(new_users_group, k, v)
70 setattr(new_users_group, k, v)
72
71
73 self.sa.add(new_users_group)
72 self.sa.add(new_users_group)
74 self.sa.commit()
73 self.sa.commit()
75 except:
74 except:
76 log.error(traceback.format_exc())
75 log.error(traceback.format_exc())
77 self.sa.rollback()
76 self.sa.rollback()
78 raise
77 raise
79
78
79 def update(self, users_group_id, form_data):
80
81 try:
82 users_group = self.get(users_group_id, cache=False)
83
84 for k, v in form_data.items():
85 if k == 'users_group_members':
86 users_group.members = []
87 self.sa.flush()
88 members_list = []
89 if v:
90 for u_id in set(v):
91 members_list.append(UsersGroupMember(users_group_id,
92 u_id))
93 setattr(users_group, 'members', members_list)
94 setattr(users_group, k, v)
95
96 self.sa.add(users_group)
97 self.sa.commit()
98 except:
99 log.error(traceback.format_exc())
100 self.sa.rollback()
101 raise
@@ -0,0 +1,166 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${_('Edit users group')} ${c.users_group.users_group_name} - ${c.rhodecode_name}
6 </%def>
7
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
11 ${h.link_to(_('UsersGroups'),h.url('users_groups'))}
12 &raquo;
13 ${_('edit')} "${c.users_group.users_group_name}"
14 </%def>
15
16 <%def name="page_nav()">
17 ${self.menu('admin')}
18 </%def>
19
20 <%def name="main()">
21 <div class="box">
22 <!-- box / title -->
23 <div class="title">
24 ${self.breadcrumbs()}
25 </div>
26 <!-- end box / title -->
27 ${h.form(url('users_group', id=c.users_group.users_group_id),method='put', id='edit_users_group')}
28 <div class="form">
29 <!-- fields -->
30 <div class="fields">
31 <div class="field">
32 <div class="label">
33 <label for="users_group_name">${_('Group name')}:</label>
34 </div>
35 <div class="input">
36 ${h.text('users_group_name',class_='small')}
37 </div>
38 </div>
39
40 <div class="field">
41 <div class="label label-checkbox">
42 <label for="users_group_active">${_('Active')}:</label>
43 </div>
44 <div class="checkboxes">
45 ${h.checkbox('users_group_active',value=True)}
46 </div>
47 </div>
48 <div class="field">
49 <div class="label label-checkbox">
50 <label for="users_group_active">${_('Members')}:</label>
51 </div>
52 <div class="checkboxes">
53 <table>
54 <tr>
55 <td>
56 <div>
57 <div style="float:left">
58 <div class="text">${_('Group members')}</div>
59 ${h.select('users_group_members',[x[0] for x in c.group_members],c.group_members,multiple=True,size=8,style="min-width:210px")}
60 </div>
61 <div style="float:left;width:20px;padding-top:50px">
62 <img alt="add" id="add_element"
63 style="padding:2px;cursor:pointer"
64 src="/images/icons/arrow_left.png">
65 <br />
66 <img alt="remove" id="remove_element"
67 style="padding:2px;cursor:pointer"
68 src="/images/icons/arrow_right.png">
69 </div>
70 <div style="float:left">
71 <div class="text">${_('Available members')}</div>
72 ${h.select('available_members',[],c.available_members,multiple=True,size=8,style="min-width:210px")}
73 </div>
74 </div>
75 </td>
76 </tr>
77 </table>
78 </div>
79
80 </div>
81 <div class="buttons">
82 ${h.submit('save','save',class_="ui-button")}
83 </div>
84 </div>
85 </div>
86 ${h.end_form()}
87 </div>
88
89 <script type="text/javascript">
90 YAHOO.util.Event.onDOMReady(function(){
91 var D = YAHOO.util.Dom;
92 var E = YAHOO.util.Event;
93
94 //definition of containers ID's
95 var available_container = 'available_members';
96 var selected_container = 'users_group_members';
97 //form containing containers id
98 var form_id = 'edit_users_group';
99
100 //temp container for storage.
101 var cache = new Array();
102 var c = D.get(selected_container);
103
104 //get only selected options for further fullfilment
105 for(var i = 0;node =c.options[i];i++){
106 if(node.selected){
107 //push selected to my temp storage left overs :)
108 cache.push(node);
109 }
110 }
111
112 //clear 'selected' select
113 c.options.length = 0;
114
115 //fill it with remembered options
116 for(var i = 0;node = cache[i];i++){
117 c.options[i]=new Option(node.text, node.value, false, false);
118 }
119
120 function prompts_action_callback(e){
121
122 var choosen = D.get(selected_container);
123 var availible = D.get(available_container);
124
125 if (this.id=='add_element'){
126 for(var i=0; node = availible.options[i];i++){
127 if(node.selected){
128 choosen.appendChild(new Option(node.text, node.value, false, false));
129 }
130 }
131 }
132 else if (this.id=='remove_element'){
133
134 //temp container for storage.
135 cache = new Array();
136
137 for(var i = 0;node = choosen.options[i];i++){
138 if(!node.selected){
139 //push left overs :)
140 cache.push(node);
141 }
142 }
143 //clear select
144 choosen.options.length = 0;
145 for(var i = 0;node = cache[i];i++){
146 choosen.options[i]=new Option(node.text, node.value, false, false);
147 }
148 }
149 else{
150
151 }
152 }
153
154
155 E.addListener(['add_element','remove_element'],'click',prompts_action_callback)
156
157 E.addListener(form_id,'submit',function(){
158 var choosen = D.get(selected_container);
159 for (var i = 0; i < choosen.options.length; i++) {
160 choosen.options[i].selected = 'selected';
161 }
162 })
163 });
164 </script>
165
166 </%def> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now