##// END OF EJS Templates
#56 fixed found bugs, implemented adding of new group + forms+validators...
marcink -
r959:fff21c9b beta
parent child Browse files
Show More
@@ -1,213 +1,217
1 """
1 """
2 Routes configuration
2 Routes configuration
3
3
4 The more specific and detailed routes should be defined first so they
4 The more specific and detailed routes should be defined first so they
5 may take precedent over the more generic routes. For more information
5 may take precedent over the more generic routes. For more information
6 refer to the routes manual at http://routes.groovie.org/docs/
6 refer to the routes manual at http://routes.groovie.org/docs/
7 """
7 """
8 from __future__ import with_statement
8 from __future__ import with_statement
9 from routes import Mapper
9 from routes import Mapper
10 from rhodecode.lib.utils import check_repo_fast as cr
10 from rhodecode.lib.utils import check_repo_fast as cr
11
11
12 def make_map(config):
12 def make_map(config):
13 """Create, configure and return the routes Mapper"""
13 """Create, configure and return the routes Mapper"""
14 map = Mapper(directory=config['pylons.paths']['controllers'],
14 map = Mapper(directory=config['pylons.paths']['controllers'],
15 always_scan=config['debug'])
15 always_scan=config['debug'])
16 map.minimization = False
16 map.minimization = False
17 map.explicit = False
17 map.explicit = False
18
18
19 def check_repo(environ, match_dict):
19 def check_repo(environ, match_dict):
20 """
20 """
21 check for valid repository for proper 404 handling
21 check for valid repository for proper 404 handling
22 :param environ:
22 :param environ:
23 :param match_dict:
23 :param match_dict:
24 """
24 """
25 repo_name = match_dict.get('repo_name')
25 repo_name = match_dict.get('repo_name')
26 return not cr(repo_name, config['base_path'])
26 return not cr(repo_name, config['base_path'])
27
27
28 # The ErrorController route (handles 404/500 error pages); it should
28 # The ErrorController route (handles 404/500 error pages); it should
29 # likely stay at the top, ensuring it can always be resolved
29 # likely stay at the top, ensuring it can always be resolved
30 map.connect('/error/{action}', controller='error')
30 map.connect('/error/{action}', controller='error')
31 map.connect('/error/{action}/{id}', controller='error')
31 map.connect('/error/{action}/{id}', controller='error')
32
32
33 #==========================================================================
33 #==========================================================================
34 # CUSTOM ROUTES HERE
34 # CUSTOM ROUTES HERE
35 #==========================================================================
35 #==========================================================================
36
36
37 #MAIN PAGE
37 #MAIN PAGE
38 map.connect('home', '/', controller='home', action='index')
38 map.connect('home', '/', controller='home', action='index')
39 map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
39 map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
40 map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
40 map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
41 #ADMIN REPOSITORY REST ROUTES
41 #ADMIN REPOSITORY REST ROUTES
42 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
42 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
43 m.connect("repos", "/repos",
43 m.connect("repos", "/repos",
44 action="create", conditions=dict(method=["POST"]))
44 action="create", conditions=dict(method=["POST"]))
45 m.connect("repos", "/repos",
45 m.connect("repos", "/repos",
46 action="index", conditions=dict(method=["GET"]))
46 action="index", conditions=dict(method=["GET"]))
47 m.connect("formatted_repos", "/repos.{format}",
47 m.connect("formatted_repos", "/repos.{format}",
48 action="index",
48 action="index",
49 conditions=dict(method=["GET"]))
49 conditions=dict(method=["GET"]))
50 m.connect("new_repo", "/repos/new",
50 m.connect("new_repo", "/repos/new",
51 action="new", conditions=dict(method=["GET"]))
51 action="new", conditions=dict(method=["GET"]))
52 m.connect("formatted_new_repo", "/repos/new.{format}",
52 m.connect("formatted_new_repo", "/repos/new.{format}",
53 action="new", conditions=dict(method=["GET"]))
53 action="new", conditions=dict(method=["GET"]))
54 m.connect("/repos/{repo_name:.*}",
54 m.connect("/repos/{repo_name:.*}",
55 action="update", conditions=dict(method=["PUT"],
55 action="update", conditions=dict(method=["PUT"],
56 function=check_repo))
56 function=check_repo))
57 m.connect("/repos/{repo_name:.*}",
57 m.connect("/repos/{repo_name:.*}",
58 action="delete", conditions=dict(method=["DELETE"],
58 action="delete", conditions=dict(method=["DELETE"],
59 function=check_repo))
59 function=check_repo))
60 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
60 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
61 action="edit", conditions=dict(method=["GET"],
61 action="edit", conditions=dict(method=["GET"],
62 function=check_repo))
62 function=check_repo))
63 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
63 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
64 action="edit", conditions=dict(method=["GET"],
64 action="edit", conditions=dict(method=["GET"],
65 function=check_repo))
65 function=check_repo))
66 m.connect("repo", "/repos/{repo_name:.*}",
66 m.connect("repo", "/repos/{repo_name:.*}",
67 action="show", conditions=dict(method=["GET"],
67 action="show", conditions=dict(method=["GET"],
68 function=check_repo))
68 function=check_repo))
69 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
69 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
70 action="show", conditions=dict(method=["GET"],
70 action="show", conditions=dict(method=["GET"],
71 function=check_repo))
71 function=check_repo))
72 #ajax delete repo perm user
72 #ajax delete repo perm user
73 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
73 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
74 action="delete_perm_user", conditions=dict(method=["DELETE"],
74 action="delete_perm_user", conditions=dict(method=["DELETE"],
75 function=check_repo))
75 function=check_repo))
76 #settings actions
76 #settings actions
77 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
77 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
78 action="repo_stats", conditions=dict(method=["DELETE"],
78 action="repo_stats", conditions=dict(method=["DELETE"],
79 function=check_repo))
79 function=check_repo))
80 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
80 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
81 action="repo_cache", conditions=dict(method=["DELETE"],
81 action="repo_cache", conditions=dict(method=["DELETE"],
82 function=check_repo))
82 function=check_repo))
83
84 #ADMIN USER REST ROUTES
85 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
86
83 #ADMIN USER REST ROUTES
87 #ADMIN USER REST ROUTES
84 map.resource('users_group', 'users_groups', controller='admin/users_groups', path_prefix='/_admin')
88 map.resource('users_group', 'users_groups', controller='admin/users_groups', path_prefix='/_admin')
85
89
86 #ADMIN GROUP REST ROUTES
90 #ADMIN GROUP REST ROUTES
87 map.resource('group', 'groups', controller='admin/groups', path_prefix='/_admin')
91 map.resource('group', 'groups', controller='admin/groups', path_prefix='/_admin')
88
92
89 #ADMIN PERMISSIONS REST ROUTES
93 #ADMIN PERMISSIONS REST ROUTES
90 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
94 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
91
95
92 ##ADMIN LDAP SETTINGS
96 ##ADMIN LDAP SETTINGS
93 map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
97 map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
94 action='ldap_settings', conditions=dict(method=["POST"]))
98 action='ldap_settings', conditions=dict(method=["POST"]))
95 map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
99 map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
96
100
97
101
98 #ADMIN SETTINGS REST ROUTES
102 #ADMIN SETTINGS REST ROUTES
99 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
103 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
100 m.connect("admin_settings", "/settings",
104 m.connect("admin_settings", "/settings",
101 action="create", conditions=dict(method=["POST"]))
105 action="create", conditions=dict(method=["POST"]))
102 m.connect("admin_settings", "/settings",
106 m.connect("admin_settings", "/settings",
103 action="index", conditions=dict(method=["GET"]))
107 action="index", conditions=dict(method=["GET"]))
104 m.connect("formatted_admin_settings", "/settings.{format}",
108 m.connect("formatted_admin_settings", "/settings.{format}",
105 action="index", conditions=dict(method=["GET"]))
109 action="index", conditions=dict(method=["GET"]))
106 m.connect("admin_new_setting", "/settings/new",
110 m.connect("admin_new_setting", "/settings/new",
107 action="new", conditions=dict(method=["GET"]))
111 action="new", conditions=dict(method=["GET"]))
108 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
112 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
109 action="new", conditions=dict(method=["GET"]))
113 action="new", conditions=dict(method=["GET"]))
110 m.connect("/settings/{setting_id}",
114 m.connect("/settings/{setting_id}",
111 action="update", conditions=dict(method=["PUT"]))
115 action="update", conditions=dict(method=["PUT"]))
112 m.connect("/settings/{setting_id}",
116 m.connect("/settings/{setting_id}",
113 action="delete", conditions=dict(method=["DELETE"]))
117 action="delete", conditions=dict(method=["DELETE"]))
114 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
118 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
115 action="edit", conditions=dict(method=["GET"]))
119 action="edit", conditions=dict(method=["GET"]))
116 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
120 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
117 action="edit", conditions=dict(method=["GET"]))
121 action="edit", conditions=dict(method=["GET"]))
118 m.connect("admin_setting", "/settings/{setting_id}",
122 m.connect("admin_setting", "/settings/{setting_id}",
119 action="show", conditions=dict(method=["GET"]))
123 action="show", conditions=dict(method=["GET"]))
120 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
124 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
121 action="show", conditions=dict(method=["GET"]))
125 action="show", conditions=dict(method=["GET"]))
122 m.connect("admin_settings_my_account", "/my_account",
126 m.connect("admin_settings_my_account", "/my_account",
123 action="my_account", conditions=dict(method=["GET"]))
127 action="my_account", conditions=dict(method=["GET"]))
124 m.connect("admin_settings_my_account_update", "/my_account_update",
128 m.connect("admin_settings_my_account_update", "/my_account_update",
125 action="my_account_update", conditions=dict(method=["PUT"]))
129 action="my_account_update", conditions=dict(method=["PUT"]))
126 m.connect("admin_settings_create_repository", "/create_repository",
130 m.connect("admin_settings_create_repository", "/create_repository",
127 action="create_repository", conditions=dict(method=["GET"]))
131 action="create_repository", conditions=dict(method=["GET"]))
128
132
129 #ADMIN MAIN PAGES
133 #ADMIN MAIN PAGES
130 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
134 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
131 m.connect('admin_home', '', action='index')#main page
135 m.connect('admin_home', '', action='index')#main page
132 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
136 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
133 action='add_repo')
137 action='add_repo')
134
138
135
139
136 #USER JOURNAL
140 #USER JOURNAL
137 map.connect('journal', '/_admin/journal', controller='journal',)
141 map.connect('journal', '/_admin/journal', controller='journal',)
138 map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
142 map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
139 action='toggle_following', conditions=dict(method=["POST"]))
143 action='toggle_following', conditions=dict(method=["POST"]))
140
144
141
145
142 #SEARCH
146 #SEARCH
143 map.connect('search', '/_admin/search', controller='search',)
147 map.connect('search', '/_admin/search', controller='search',)
144 map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
148 map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
145
149
146 #LOGIN/LOGOUT/REGISTER/SIGN IN
150 #LOGIN/LOGOUT/REGISTER/SIGN IN
147 map.connect('login_home', '/_admin/login', controller='login')
151 map.connect('login_home', '/_admin/login', controller='login')
148 map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
152 map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
149 map.connect('register', '/_admin/register', controller='login', action='register')
153 map.connect('register', '/_admin/register', controller='login', action='register')
150 map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
154 map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
151
155
152 #FEEDS
156 #FEEDS
153 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
157 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
154 controller='feed', action='rss',
158 controller='feed', action='rss',
155 conditions=dict(function=check_repo))
159 conditions=dict(function=check_repo))
156 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
160 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
157 controller='feed', action='atom',
161 controller='feed', action='atom',
158 conditions=dict(function=check_repo))
162 conditions=dict(function=check_repo))
159
163
160
164
161 #REPOSITORY ROUTES
165 #REPOSITORY ROUTES
162 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
166 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
163 controller='changeset', revision='tip',
167 controller='changeset', revision='tip',
164 conditions=dict(function=check_repo))
168 conditions=dict(function=check_repo))
165 map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
169 map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
166 controller='changeset', action='raw_changeset', revision='tip',
170 controller='changeset', action='raw_changeset', revision='tip',
167 conditions=dict(function=check_repo))
171 conditions=dict(function=check_repo))
168 map.connect('summary_home', '/{repo_name:.*}/summary',
172 map.connect('summary_home', '/{repo_name:.*}/summary',
169 controller='summary', conditions=dict(function=check_repo))
173 controller='summary', conditions=dict(function=check_repo))
170 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
174 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
171 controller='shortlog', conditions=dict(function=check_repo))
175 controller='shortlog', conditions=dict(function=check_repo))
172 map.connect('branches_home', '/{repo_name:.*}/branches',
176 map.connect('branches_home', '/{repo_name:.*}/branches',
173 controller='branches', conditions=dict(function=check_repo))
177 controller='branches', conditions=dict(function=check_repo))
174 map.connect('tags_home', '/{repo_name:.*}/tags',
178 map.connect('tags_home', '/{repo_name:.*}/tags',
175 controller='tags', conditions=dict(function=check_repo))
179 controller='tags', conditions=dict(function=check_repo))
176 map.connect('changelog_home', '/{repo_name:.*}/changelog',
180 map.connect('changelog_home', '/{repo_name:.*}/changelog',
177 controller='changelog', conditions=dict(function=check_repo))
181 controller='changelog', conditions=dict(function=check_repo))
178 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
182 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
179 controller='files', revision='tip', f_path='',
183 controller='files', revision='tip', f_path='',
180 conditions=dict(function=check_repo))
184 conditions=dict(function=check_repo))
181 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
185 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
182 controller='files', action='diff', revision='tip', f_path='',
186 controller='files', action='diff', revision='tip', f_path='',
183 conditions=dict(function=check_repo))
187 conditions=dict(function=check_repo))
184 map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
188 map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
185 controller='files', action='rawfile', revision='tip', f_path='',
189 controller='files', action='rawfile', revision='tip', f_path='',
186 conditions=dict(function=check_repo))
190 conditions=dict(function=check_repo))
187 map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
191 map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
188 controller='files', action='raw', revision='tip', f_path='',
192 controller='files', action='raw', revision='tip', f_path='',
189 conditions=dict(function=check_repo))
193 conditions=dict(function=check_repo))
190 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
194 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
191 controller='files', action='annotate', revision='tip', f_path='',
195 controller='files', action='annotate', revision='tip', f_path='',
192 conditions=dict(function=check_repo))
196 conditions=dict(function=check_repo))
193 map.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
197 map.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
194 controller='files', action='archivefile',
198 controller='files', action='archivefile',
195 conditions=dict(function=check_repo))
199 conditions=dict(function=check_repo))
196 map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
200 map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
197 controller='settings', action="delete",
201 controller='settings', action="delete",
198 conditions=dict(method=["DELETE"], function=check_repo))
202 conditions=dict(method=["DELETE"], function=check_repo))
199 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
203 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
200 controller='settings', action="update",
204 controller='settings', action="update",
201 conditions=dict(method=["PUT"], function=check_repo))
205 conditions=dict(method=["PUT"], function=check_repo))
202 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
206 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
203 controller='settings', action='index',
207 controller='settings', action='index',
204 conditions=dict(function=check_repo))
208 conditions=dict(function=check_repo))
205
209
206 map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
210 map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
207 controller='settings', action='fork_create',
211 controller='settings', action='fork_create',
208 conditions=dict(function=check_repo, method=["POST"]))
212 conditions=dict(function=check_repo, method=["POST"]))
209 map.connect('repo_fork_home', '/{repo_name:.*}/fork',
213 map.connect('repo_fork_home', '/{repo_name:.*}/fork',
210 controller='settings', action='fork',
214 controller='settings', action='fork',
211 conditions=dict(function=check_repo))
215 conditions=dict(function=check_repo))
212
216
213 return map
217 return map
@@ -1,101 +1,124
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
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
47
47 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
48
49
49 class UsersGroupsController(BaseController):
50 class UsersGroupsController(BaseController):
50 """REST Controller styled on the Atom Publishing Protocol"""
51 """REST Controller styled on the Atom Publishing Protocol"""
51 # To properly map this controller, ensure your config/routing.py
52 # To properly map this controller, ensure your config/routing.py
52 # file has a resource setup:
53 # file has a resource setup:
53 # map.resource('users_group', 'users_groups')
54 # map.resource('users_group', 'users_groups')
54
55
55 @LoginRequired()
56 @LoginRequired()
56 @HasPermissionAllDecorator('hg.admin')
57 @HasPermissionAllDecorator('hg.admin')
57 def __before__(self):
58 def __before__(self):
58 c.admin_user = session.get('admin_user')
59 c.admin_user = session.get('admin_user')
59 c.admin_username = session.get('admin_username')
60 c.admin_username = session.get('admin_username')
60 super(UsersGroupsController, self).__before__()
61 super(UsersGroupsController, self).__before__()
61 c.available_permissions = config['available_permissions']
62 c.available_permissions = config['available_permissions']
62
63
63 def index(self, format='html'):
64 def index(self, format='html'):
64 """GET /users_groups: All items in the collection"""
65 """GET /users_groups: All items in the collection"""
65 # url('users_groups')
66 # url('users_groups')
66 c.users_groups_list = []
67 c.users_groups_list = self.sa.query(UsersGroup).all()
67 return render('admin/users_groups/users_groups.html')
68 return render('admin/users_groups/users_groups.html')
68
69
69 def create(self):
70 def create(self):
70 """POST /users_groups: Create a new item"""
71 """POST /users_groups: Create a new item"""
71 # url('users_groups')
72 # url('users_groups')
73 users_group_model = UsersGroupModel()
74 users_group_form = UsersGroupForm()()
75 try:
76 form_result = users_group_form.to_python(dict(request.POST))
77 users_group_model.create(form_result)
78 h.flash(_('created users group %s') % form_result['users_group_name'],
79 category='success')
80 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
81 except formencode.Invalid, errors:
82 return htmlfill.render(
83 render('admin/users_groups/users_group_add.html'),
84 defaults=errors.value,
85 errors=errors.error_dict or {},
86 prefix_error=False,
87 encoding="UTF-8")
88 except Exception:
89 log.error(traceback.format_exc())
90 h.flash(_('error occurred during creation of users group %s') \
91 % request.POST.get('users_group_name'), category='error')
92
93 return redirect(url('users_groups'))
72
94
73 def new(self, format='html'):
95 def new(self, format='html'):
74 """GET /users_groups/new: Form to create a new item"""
96 """GET /users_groups/new: Form to create a new item"""
75 # url('new_users_group')
97 # url('new_users_group')
98 return render('admin/users_groups/users_group_add.html')
76
99
77 def update(self, id):
100 def update(self, id):
78 """PUT /users_groups/id: Update an existing item"""
101 """PUT /users_groups/id: Update an existing item"""
79 # Forms posted to this method should contain a hidden field:
102 # Forms posted to this method should contain a hidden field:
80 # <input type="hidden" name="_method" value="PUT" />
103 # <input type="hidden" name="_method" value="PUT" />
81 # Or using helpers:
104 # Or using helpers:
82 # h.form(url('users_group', id=ID),
105 # h.form(url('users_group', id=ID),
83 # method='put')
106 # method='put')
84 # url('users_group', id=ID)
107 # url('users_group', id=ID)
85
108
86 def delete(self, id):
109 def delete(self, id):
87 """DELETE /users_groups/id: Delete an existing item"""
110 """DELETE /users_groups/id: Delete an existing item"""
88 # Forms posted to this method should contain a hidden field:
111 # Forms posted to this method should contain a hidden field:
89 # <input type="hidden" name="_method" value="DELETE" />
112 # <input type="hidden" name="_method" value="DELETE" />
90 # Or using helpers:
113 # Or using helpers:
91 # h.form(url('users_group', id=ID),
114 # h.form(url('users_group', id=ID),
92 # method='delete')
115 # method='delete')
93 # url('users_group', id=ID)
116 # url('users_group', id=ID)
94
117
95 def show(self, id, format='html'):
118 def show(self, id, format='html'):
96 """GET /users_groups/id: Show a specific item"""
119 """GET /users_groups/id: Show a specific item"""
97 # url('users_group', id=ID)
120 # url('users_group', id=ID)
98
121
99 def edit(self, id, format='html'):
122 def edit(self, id, format='html'):
100 """GET /users_groups/id/edit: Form to edit an existing item"""
123 """GET /users_groups/id/edit: Form to edit an existing item"""
101 # url('edit_users_group', id=ID)
124 # url('edit_users_group', id=ID)
@@ -1,331 +1,330
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 relation, 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 = relation('UserLog', cascade='all')
111 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
111 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
112
112
113 repositories = relation('Repository')
113 repositories = relation('Repository')
114 user_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
114 user_followers = relation('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 = relation('User')
154 repository = relation('Repository')
154 repository = relation('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 user_group_id = Column("users_groups_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 user_group_name = Column("user_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
163 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
164
164
165 members = relation('UsersGroupMember')
165 members = relation('UsersGroupMember')
166
166
167
168 class UsersGroupMember(Base, BaseModel):
167 class UsersGroupMember(Base, BaseModel):
169 __tablename__ = 'users_groups_members'
168 __tablename__ = 'users_groups_members'
170 __table_args__ = {'useexisting':True}
169 __table_args__ = {'useexisting':True}
171
170
172 user_groups_members_id = Column("user_groups_members_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)
173 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_groups_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)
174 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)
175
174
176 user = relation('User')
175 user = relation('User')
177 users_group = relation('UsersGroup')
176 users_group = relation('UsersGroup')
178
177
179 class Repository(Base, BaseModel):
178 class Repository(Base, BaseModel):
180 __tablename__ = 'repositories'
179 __tablename__ = 'repositories'
181 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
180 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
182 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
181 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
183 repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
182 repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
184 repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
183 repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
185 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
184 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
186 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
185 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
187 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
186 enable_statistics = Column("statistics", 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)
187 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)
188 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)
189 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
191
190
192 user = relation('User')
191 user = relation('User')
193 fork = relation('Repository', remote_side=repo_id)
192 fork = relation('Repository', remote_side=repo_id)
194 group = relation('Group')
193 group = relation('Group')
195 repo_to_perm = relation('RepoToPerm', cascade='all')
194 repo_to_perm = relation('RepoToPerm', cascade='all')
196 stats = relation('Statistics', cascade='all', uselist=False)
195 stats = relation('Statistics', cascade='all', uselist=False)
197
196
198 repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
197 repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
199
198
200 def __repr__(self):
199 def __repr__(self):
201 return "<%s('%s:%s')>" % (self.__class__.__name__,
200 return "<%s('%s:%s')>" % (self.__class__.__name__,
202 self.repo_id, self.repo_name)
201 self.repo_id, self.repo_name)
203
202
204 class Group(Base, BaseModel):
203 class Group(Base, BaseModel):
205 __tablename__ = 'groups'
204 __tablename__ = 'groups'
206 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
205 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
207
206
208 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
207 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)
208 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)
209 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
211
210
212 parent_group = relation('Group', remote_side=group_id)
211 parent_group = relation('Group', remote_side=group_id)
213
212
214
213
215 def __init__(self, group_name='', parent_group=None):
214 def __init__(self, group_name='', parent_group=None):
216 self.group_name = group_name
215 self.group_name = group_name
217 self.parent_group = parent_group
216 self.parent_group = parent_group
218
217
219 def __repr__(self):
218 def __repr__(self):
220 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
219 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
221 self.group_name)
220 self.group_name)
222
221
223 class Permission(Base, BaseModel):
222 class Permission(Base, BaseModel):
224 __tablename__ = 'permissions'
223 __tablename__ = 'permissions'
225 __table_args__ = {'useexisting':True}
224 __table_args__ = {'useexisting':True}
226 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
225 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)
226 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)
227 permission_longname = Column("permission_longname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
229
228
230 def __repr__(self):
229 def __repr__(self):
231 return "<%s('%s:%s')>" % (self.__class__.__name__,
230 return "<%s('%s:%s')>" % (self.__class__.__name__,
232 self.permission_id, self.permission_name)
231 self.permission_id, self.permission_name)
233
232
234 class RepoToPerm(Base, BaseModel):
233 class RepoToPerm(Base, BaseModel):
235 __tablename__ = 'repo_to_perm'
234 __tablename__ = 'repo_to_perm'
236 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
235 __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)
236 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)
237 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)
238 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)
239 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
241
240
242 user = relation('User')
241 user = relation('User')
243 permission = relation('Permission')
242 permission = relation('Permission')
244 repository = relation('Repository')
243 repository = relation('Repository')
245
244
246 class UserToPerm(Base, BaseModel):
245 class UserToPerm(Base, BaseModel):
247 __tablename__ = 'user_to_perm'
246 __tablename__ = 'user_to_perm'
248 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
247 __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)
248 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)
249 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)
250 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
252
251
253 user = relation('User')
252 user = relation('User')
254 permission = relation('Permission')
253 permission = relation('Permission')
255
254
256 class UsersGroupToPerm(Base, BaseModel):
255 class UsersGroupToPerm(Base, BaseModel):
257 __tablename__ = 'users_group_to_perm'
256 __tablename__ = 'users_group_to_perm'
258 __table_args__ = (UniqueConstraint('users_group_id', 'permission_id'), {'useexisting':True})
257 __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)
258 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_groups_id'), nullable=False, unique=None, default=None)
259 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)
260 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
262
261
263 users_group = relation('UsersGroup')
262 users_group = relation('UsersGroup')
264 permission = relation('Permission')
263 permission = relation('Permission')
265
264
266 class GroupToPerm(Base, BaseModel):
265 class GroupToPerm(Base, BaseModel):
267 __tablename__ = 'group_to_perm'
266 __tablename__ = 'group_to_perm'
268 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
267 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
269
268
270 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
269 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)
270 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)
271 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)
272 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
274
273
275 user = relation('User')
274 user = relation('User')
276 permission = relation('Permission')
275 permission = relation('Permission')
277 group = relation('Group')
276 group = relation('Group')
278
277
279 class Statistics(Base, BaseModel):
278 class Statistics(Base, BaseModel):
280 __tablename__ = 'statistics'
279 __tablename__ = 'statistics'
281 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
280 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
282 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
281 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)
282 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)
283 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
285 commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
284 commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
286 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
285 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
287 languages = Column("languages", LargeBinary(), nullable=False)#JSON data
286 languages = Column("languages", LargeBinary(), nullable=False)#JSON data
288
287
289 repository = relation('Repository', single_parent=True)
288 repository = relation('Repository', single_parent=True)
290
289
291 class UserFollowing(Base, BaseModel):
290 class UserFollowing(Base, BaseModel):
292 __tablename__ = 'user_followings'
291 __tablename__ = 'user_followings'
293 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
292 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
294 UniqueConstraint('user_id', 'follows_user_id')
293 UniqueConstraint('user_id', 'follows_user_id')
295 , {'useexisting':True})
294 , {'useexisting':True})
296
295
297 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
296 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)
297 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)
298 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)
299 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
301
300
302 user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
301 user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
303
302
304 follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
303 follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
305 follows_repository = relation('Repository')
304 follows_repository = relation('Repository')
306
305
307 class CacheInvalidation(Base, BaseModel):
306 class CacheInvalidation(Base, BaseModel):
308 __tablename__ = 'cache_invalidation'
307 __tablename__ = 'cache_invalidation'
309 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
308 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
310 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
309 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)
310 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)
311 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)
312 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
314
313
315
314
316 def __init__(self, cache_key, cache_args=''):
315 def __init__(self, cache_key, cache_args=''):
317 self.cache_key = cache_key
316 self.cache_key = cache_key
318 self.cache_args = cache_args
317 self.cache_args = cache_args
319 self.cache_active = False
318 self.cache_active = False
320
319
321 def __repr__(self):
320 def __repr__(self):
322 return "<%s('%s:%s')>" % (self.__class__.__name__,
321 return "<%s('%s:%s')>" % (self.__class__.__name__,
323 self.cache_id, self.cache_key)
322 self.cache_id, self.cache_key)
324
323
325 class DbMigrateVersion(Base, BaseModel):
324 class DbMigrateVersion(Base, BaseModel):
326 __tablename__ = 'db_migrate_version'
325 __tablename__ = 'db_migrate_version'
327 __table_args__ = {'useexisting':True}
326 __table_args__ = {'useexisting':True}
328 repository_id = Column('repository_id', String(250), primary_key=True)
327 repository_id = Column('repository_id', String(250), primary_key=True)
329 repository_path = Column('repository_path', Text)
328 repository_path = Column('repository_path', Text)
330 version = Column('version', Integer)
329 version = Column('version', Integer)
331
330
@@ -1,484 +1,530
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
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.db import User
40 from rhodecode.model.db import User
40 from rhodecode import BACKENDS
41 from rhodecode import BACKENDS
41
42
42 from webhelpers.pylonslib.secure_form import authentication_token
43 from webhelpers.pylonslib.secure_form import authentication_token
43
44
44 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
45
46
46 #this is needed to translate the messages using _() in validators
47 #this is needed to translate the messages using _() in validators
47 class State_obj(object):
48 class State_obj(object):
48 _ = staticmethod(_)
49 _ = staticmethod(_)
49
50
50 #===============================================================================
51 #===============================================================================
51 # VALIDATORS
52 # VALIDATORS
52 #===============================================================================
53 #===============================================================================
53 class ValidAuthToken(formencode.validators.FancyValidator):
54 class ValidAuthToken(formencode.validators.FancyValidator):
54 messages = {'invalid_token':_('Token mismatch')}
55 messages = {'invalid_token':_('Token mismatch')}
55
56
56 def validate_python(self, value, state):
57 def validate_python(self, value, state):
57
58
58 if value != authentication_token():
59 if value != authentication_token():
59 raise formencode.Invalid(self.message('invalid_token', state,
60 raise formencode.Invalid(self.message('invalid_token', state,
60 search_number=value), value, state)
61 search_number=value), value, state)
61
62
62 def ValidUsername(edit, old_data):
63 def ValidUsername(edit, old_data):
63 class _ValidUsername(formencode.validators.FancyValidator):
64 class _ValidUsername(formencode.validators.FancyValidator):
64
65
65 def validate_python(self, value, state):
66 def validate_python(self, value, state):
66 if value in ['default', 'new_user']:
67 if value in ['default', 'new_user']:
67 raise formencode.Invalid(_('Invalid username'), value, state)
68 raise formencode.Invalid(_('Invalid username'), value, state)
68 #check if user is unique
69 #check if user is unique
69 old_un = None
70 old_un = None
70 if edit:
71 if edit:
71 old_un = UserModel().get(old_data.get('user_id')).username
72 old_un = UserModel().get(old_data.get('user_id')).username
72
73
73 if old_un != value or not edit:
74 if old_un != value or not edit:
74 if UserModel().get_by_username(value, cache=False,
75 if UserModel().get_by_username(value, cache=False,
75 case_insensitive=True):
76 case_insensitive=True):
76 raise formencode.Invalid(_('This username already exists') ,
77 raise formencode.Invalid(_('This username already exists') ,
77 value, state)
78 value, state)
78
79
79
80
80 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:
81 raise formencode.Invalid(_('Username may only contain '
82 raise formencode.Invalid(_('Username may only contain '
82 'alphanumeric characters underscores '
83 'alphanumeric characters underscores '
83 'or dashes and must begin with '
84 'or dashes and must begin with '
84 'alphanumeric character'),
85 'alphanumeric character'),
85 value, state)
86 value, state)
86
87
87
88
88
89
89 return _ValidUsername
90 return _ValidUsername
90
91
92
93
94 def ValidUsersGroup(edit, old_data):
95
96 class _ValidUsersGroup(formencode.validators.FancyValidator):
97
98 def validate_python(self, value, state):
99 if value in ['default']:
100 raise formencode.Invalid(_('Invalid group name'), value, state)
101 #check if group is unique
102 old_un = None
103 if edit:
104 old_un = UserModel().get(old_data.get('users_group_id')).username
105
106 if old_un != value or not edit:
107 if UsersGroupModel().get_by_groupname(value, cache=False,
108 case_insensitive=True):
109 raise formencode.Invalid(_('This users group already exists') ,
110 value, state)
111
112
113 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 'alphanumeric characters underscores, '
116 'periods or dashes and must begin with '
117 'alphanumeric character'),
118 value, state)
119
120 return _ValidUsersGroup
121
122
123
91 class ValidPassword(formencode.validators.FancyValidator):
124 class ValidPassword(formencode.validators.FancyValidator):
92
125
93 def to_python(self, value, state):
126 def to_python(self, value, state):
94
127
95 if value:
128 if value:
96
129
97 if value.get('password'):
130 if value.get('password'):
98 try:
131 try:
99 value['password'] = get_crypt_password(value['password'])
132 value['password'] = get_crypt_password(value['password'])
100 except UnicodeEncodeError:
133 except UnicodeEncodeError:
101 e_dict = {'password':_('Invalid characters in password')}
134 e_dict = {'password':_('Invalid characters in password')}
102 raise formencode.Invalid('', value, state, error_dict=e_dict)
135 raise formencode.Invalid('', value, state, error_dict=e_dict)
103
136
104 if value.get('password_confirmation'):
137 if value.get('password_confirmation'):
105 try:
138 try:
106 value['password_confirmation'] = \
139 value['password_confirmation'] = \
107 get_crypt_password(value['password_confirmation'])
140 get_crypt_password(value['password_confirmation'])
108 except UnicodeEncodeError:
141 except UnicodeEncodeError:
109 e_dict = {'password_confirmation':_('Invalid characters in password')}
142 e_dict = {'password_confirmation':_('Invalid characters in password')}
110 raise formencode.Invalid('', value, state, error_dict=e_dict)
143 raise formencode.Invalid('', value, state, error_dict=e_dict)
111
144
112 if value.get('new_password'):
145 if value.get('new_password'):
113 try:
146 try:
114 value['new_password'] = \
147 value['new_password'] = \
115 get_crypt_password(value['new_password'])
148 get_crypt_password(value['new_password'])
116 except UnicodeEncodeError:
149 except UnicodeEncodeError:
117 e_dict = {'new_password':_('Invalid characters in password')}
150 e_dict = {'new_password':_('Invalid characters in password')}
118 raise formencode.Invalid('', value, state, error_dict=e_dict)
151 raise formencode.Invalid('', value, state, error_dict=e_dict)
119
152
120 return value
153 return value
121
154
122 class ValidPasswordsMatch(formencode.validators.FancyValidator):
155 class ValidPasswordsMatch(formencode.validators.FancyValidator):
123
156
124 def validate_python(self, value, state):
157 def validate_python(self, value, state):
125
158
126 if value['password'] != value['password_confirmation']:
159 if value['password'] != value['password_confirmation']:
127 e_dict = {'password_confirmation':
160 e_dict = {'password_confirmation':
128 _('Password do not match')}
161 _('Password do not match')}
129 raise formencode.Invalid('', value, state, error_dict=e_dict)
162 raise formencode.Invalid('', value, state, error_dict=e_dict)
130
163
131 class ValidAuth(formencode.validators.FancyValidator):
164 class ValidAuth(formencode.validators.FancyValidator):
132 messages = {
165 messages = {
133 'invalid_password':_('invalid password'),
166 'invalid_password':_('invalid password'),
134 'invalid_login':_('invalid user name'),
167 'invalid_login':_('invalid user name'),
135 'disabled_account':_('Your account is disabled')
168 'disabled_account':_('Your account is disabled')
136
169
137 }
170 }
138 #error mapping
171 #error mapping
139 e_dict = {'username':messages['invalid_login'],
172 e_dict = {'username':messages['invalid_login'],
140 'password':messages['invalid_password']}
173 'password':messages['invalid_password']}
141 e_dict_disable = {'username':messages['disabled_account']}
174 e_dict_disable = {'username':messages['disabled_account']}
142
175
143 def validate_python(self, value, state):
176 def validate_python(self, value, state):
144 password = value['password']
177 password = value['password']
145 username = value['username']
178 username = value['username']
146 user = UserModel().get_by_username(username)
179 user = UserModel().get_by_username(username)
147
180
148 if authenticate(username, password):
181 if authenticate(username, password):
149 return value
182 return value
150 else:
183 else:
151 if user and user.active is False:
184 if user and user.active is False:
152 log.warning('user %s is disabled', username)
185 log.warning('user %s is disabled', username)
153 raise formencode.Invalid(self.message('disabled_account',
186 raise formencode.Invalid(self.message('disabled_account',
154 state=State_obj),
187 state=State_obj),
155 value, state,
188 value, state,
156 error_dict=self.e_dict_disable)
189 error_dict=self.e_dict_disable)
157 else:
190 else:
158 log.warning('user %s not authenticated', username)
191 log.warning('user %s not authenticated', username)
159 raise formencode.Invalid(self.message('invalid_password',
192 raise formencode.Invalid(self.message('invalid_password',
160 state=State_obj), value, state,
193 state=State_obj), value, state,
161 error_dict=self.e_dict)
194 error_dict=self.e_dict)
162
195
163 class ValidRepoUser(formencode.validators.FancyValidator):
196 class ValidRepoUser(formencode.validators.FancyValidator):
164
197
165 def to_python(self, value, state):
198 def to_python(self, value, state):
166 sa = meta.Session()
199 sa = meta.Session()
167 try:
200 try:
168 self.user_db = sa.query(User)\
201 self.user_db = sa.query(User)\
169 .filter(User.active == True)\
202 .filter(User.active == True)\
170 .filter(User.username == value).one()
203 .filter(User.username == value).one()
171 except Exception:
204 except Exception:
172 raise formencode.Invalid(_('This username is not valid'),
205 raise formencode.Invalid(_('This username is not valid'),
173 value, state)
206 value, state)
174 finally:
207 finally:
175 meta.Session.remove()
208 meta.Session.remove()
176
209
177 return self.user_db.user_id
210 return self.user_db.user_id
178
211
179 def ValidRepoName(edit, old_data):
212 def ValidRepoName(edit, old_data):
180 class _ValidRepoName(formencode.validators.FancyValidator):
213 class _ValidRepoName(formencode.validators.FancyValidator):
181
214
182 def to_python(self, value, state):
215 def to_python(self, value, state):
183 slug = h.repo_name_slug(value)
216 slug = h.repo_name_slug(value)
184 if slug in ['_admin']:
217 if slug in ['_admin']:
185 raise formencode.Invalid(_('This repository name is disallowed'),
218 raise formencode.Invalid(_('This repository name is disallowed'),
186 value, state)
219 value, state)
187 if old_data.get('repo_name') != value or not edit:
220 if old_data.get('repo_name') != value or not edit:
188 if RepoModel().get_by_repo_name(slug, cache=False):
221 if RepoModel().get_by_repo_name(slug, cache=False):
189 raise formencode.Invalid(_('This repository already exists') ,
222 raise formencode.Invalid(_('This repository already exists') ,
190 value, state)
223 value, state)
191 return slug
224 return slug
192
225
193
226
194 return _ValidRepoName
227 return _ValidRepoName
195
228
196 def ValidForkType(old_data):
229 def ValidForkType(old_data):
197 class _ValidForkType(formencode.validators.FancyValidator):
230 class _ValidForkType(formencode.validators.FancyValidator):
198
231
199 def to_python(self, value, state):
232 def to_python(self, value, state):
200 if old_data['repo_type'] != value:
233 if old_data['repo_type'] != value:
201 raise formencode.Invalid(_('Fork have to be the same type as original'),
234 raise formencode.Invalid(_('Fork have to be the same type as original'),
202 value, state)
235 value, state)
203 return value
236 return value
204 return _ValidForkType
237 return _ValidForkType
205
238
206 class ValidPerms(formencode.validators.FancyValidator):
239 class ValidPerms(formencode.validators.FancyValidator):
207 messages = {'perm_new_user_name':_('This username is not valid')}
240 messages = {'perm_new_user_name':_('This username is not valid')}
208
241
209 def to_python(self, value, state):
242 def to_python(self, value, state):
210 perms_update = []
243 perms_update = []
211 perms_new = []
244 perms_new = []
212 #build a list of permission to update and new permission to create
245 #build a list of permission to update and new permission to create
213 for k, v in value.items():
246 for k, v in value.items():
214 if k.startswith('perm_'):
247 if k.startswith('perm_'):
215 if k.startswith('perm_new_user'):
248 if k.startswith('perm_new_user'):
216 new_perm = value.get('perm_new_user', False)
249 new_perm = value.get('perm_new_user', False)
217 new_user = value.get('perm_new_user_name', False)
250 new_user = value.get('perm_new_user_name', False)
218 if new_user and new_perm:
251 if new_user and new_perm:
219 if (new_user, new_perm) not in perms_new:
252 if (new_user, new_perm) not in perms_new:
220 perms_new.append((new_user, new_perm))
253 perms_new.append((new_user, new_perm))
221 else:
254 else:
222 usr = k[5:]
255 usr = k[5:]
223 if usr == 'default':
256 if usr == 'default':
224 if value['private']:
257 if value['private']:
225 #set none for default when updating to private repo
258 #set none for default when updating to private repo
226 v = 'repository.none'
259 v = 'repository.none'
227 perms_update.append((usr, v))
260 perms_update.append((usr, v))
228 value['perms_updates'] = perms_update
261 value['perms_updates'] = perms_update
229 value['perms_new'] = perms_new
262 value['perms_new'] = perms_new
230 sa = meta.Session
263 sa = meta.Session
231 for k, v in perms_new:
264 for k, v in perms_new:
232 try:
265 try:
233 self.user_db = sa.query(User)\
266 self.user_db = sa.query(User)\
234 .filter(User.active == True)\
267 .filter(User.active == True)\
235 .filter(User.username == k).one()
268 .filter(User.username == k).one()
236 except Exception:
269 except Exception:
237 msg = self.message('perm_new_user_name',
270 msg = self.message('perm_new_user_name',
238 state=State_obj)
271 state=State_obj)
239 raise formencode.Invalid(msg, value, state,
272 raise formencode.Invalid(msg, value, state,
240 error_dict={'perm_new_user_name':msg})
273 error_dict={'perm_new_user_name':msg})
241 return value
274 return value
242
275
243 class ValidSettings(formencode.validators.FancyValidator):
276 class ValidSettings(formencode.validators.FancyValidator):
244
277
245 def to_python(self, value, state):
278 def to_python(self, value, state):
246 #settings form can't edit user
279 #settings form can't edit user
247 if value.has_key('user'):
280 if value.has_key('user'):
248 del['value']['user']
281 del['value']['user']
249
282
250 return value
283 return value
251
284
252 class ValidPath(formencode.validators.FancyValidator):
285 class ValidPath(formencode.validators.FancyValidator):
253 def to_python(self, value, state):
286 def to_python(self, value, state):
254
287
255 if not os.path.isdir(value):
288 if not os.path.isdir(value):
256 msg = _('This is not a valid path')
289 msg = _('This is not a valid path')
257 raise formencode.Invalid(msg, value, state,
290 raise formencode.Invalid(msg, value, state,
258 error_dict={'paths_root_path':msg})
291 error_dict={'paths_root_path':msg})
259 return value
292 return value
260
293
261 def UniqSystemEmail(old_data):
294 def UniqSystemEmail(old_data):
262 class _UniqSystemEmail(formencode.validators.FancyValidator):
295 class _UniqSystemEmail(formencode.validators.FancyValidator):
263 def to_python(self, value, state):
296 def to_python(self, value, state):
264 value = value.lower()
297 value = value.lower()
265 if old_data.get('email') != value:
298 if old_data.get('email') != value:
266 sa = meta.Session()
299 sa = meta.Session()
267 try:
300 try:
268 user = sa.query(User).filter(User.email == value).scalar()
301 user = sa.query(User).filter(User.email == value).scalar()
269 if user:
302 if user:
270 raise formencode.Invalid(_("This e-mail address is already taken") ,
303 raise formencode.Invalid(_("This e-mail address is already taken") ,
271 value, state)
304 value, state)
272 finally:
305 finally:
273 meta.Session.remove()
306 meta.Session.remove()
274
307
275 return value
308 return value
276
309
277 return _UniqSystemEmail
310 return _UniqSystemEmail
278
311
279 class ValidSystemEmail(formencode.validators.FancyValidator):
312 class ValidSystemEmail(formencode.validators.FancyValidator):
280 def to_python(self, value, state):
313 def to_python(self, value, state):
281 value = value.lower()
314 value = value.lower()
282 sa = meta.Session
315 sa = meta.Session
283 try:
316 try:
284 user = sa.query(User).filter(User.email == value).scalar()
317 user = sa.query(User).filter(User.email == value).scalar()
285 if user is None:
318 if user is None:
286 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
319 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
287 value, state)
320 value, state)
288 finally:
321 finally:
289 meta.Session.remove()
322 meta.Session.remove()
290
323
291 return value
324 return value
292
325
293 class LdapLibValidator(formencode.validators.FancyValidator):
326 class LdapLibValidator(formencode.validators.FancyValidator):
294
327
295 def to_python(self, value, state):
328 def to_python(self, value, state):
296
329
297 try:
330 try:
298 import ldap
331 import ldap
299 except ImportError:
332 except ImportError:
300 raise LdapImportError
333 raise LdapImportError
301 return value
334 return value
302
335
303 class BaseDnValidator(formencode.validators.FancyValidator):
336 class BaseDnValidator(formencode.validators.FancyValidator):
304
337
305 def to_python(self, value, state):
338 def to_python(self, value, state):
306
339
307 try:
340 try:
308 value % {'user':'valid'}
341 value % {'user':'valid'}
309
342
310 if value.find('%(user)s') == -1:
343 if value.find('%(user)s') == -1:
311 raise formencode.Invalid(_("You need to specify %(user)s in "
344 raise formencode.Invalid(_("You need to specify %(user)s in "
312 "template for example uid=%(user)s "
345 "template for example uid=%(user)s "
313 ",dc=company...") ,
346 ",dc=company...") ,
314 value, state)
347 value, state)
315
348
316 except KeyError:
349 except KeyError:
317 raise formencode.Invalid(_("Wrong template used, only %(user)s "
350 raise formencode.Invalid(_("Wrong template used, only %(user)s "
318 "is an valid entry") ,
351 "is an valid entry") ,
319 value, state)
352 value, state)
320
353
321 return value
354 return value
322
355
323 #===============================================================================
356 #===============================================================================
324 # FORMS
357 # FORMS
325 #===============================================================================
358 #===============================================================================
326 class LoginForm(formencode.Schema):
359 class LoginForm(formencode.Schema):
327 allow_extra_fields = True
360 allow_extra_fields = True
328 filter_extra_fields = True
361 filter_extra_fields = True
329 username = UnicodeString(
362 username = UnicodeString(
330 strip=True,
363 strip=True,
331 min=1,
364 min=1,
332 not_empty=True,
365 not_empty=True,
333 messages={
366 messages={
334 'empty':_('Please enter a login'),
367 'empty':_('Please enter a login'),
335 'tooShort':_('Enter a value %(min)i characters long or more')}
368 'tooShort':_('Enter a value %(min)i characters long or more')}
336 )
369 )
337
370
338 password = UnicodeString(
371 password = UnicodeString(
339 strip=True,
372 strip=True,
340 min=6,
373 min=6,
341 not_empty=True,
374 not_empty=True,
342 messages={
375 messages={
343 'empty':_('Please enter a password'),
376 'empty':_('Please enter a password'),
344 'tooShort':_('Enter %(min)i characters or more')}
377 'tooShort':_('Enter %(min)i characters or more')}
345 )
378 )
346
379
347
380
348 #chained validators have access to all data
381 #chained validators have access to all data
349 chained_validators = [ValidAuth]
382 chained_validators = [ValidAuth]
350
383
351 def UserForm(edit=False, old_data={}):
384 def UserForm(edit=False, old_data={}):
352 class _UserForm(formencode.Schema):
385 class _UserForm(formencode.Schema):
353 allow_extra_fields = True
386 allow_extra_fields = True
354 filter_extra_fields = True
387 filter_extra_fields = True
355 username = All(UnicodeString(strip=True, min=1, not_empty=True),
388 username = All(UnicodeString(strip=True, min=1, not_empty=True),
356 ValidUsername(edit, old_data))
389 ValidUsername(edit, old_data))
357 if edit:
390 if edit:
358 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
391 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
359 admin = StringBoolean(if_missing=False)
392 admin = StringBoolean(if_missing=False)
360 else:
393 else:
361 password = All(UnicodeString(strip=True, min=6, not_empty=True))
394 password = All(UnicodeString(strip=True, min=6, not_empty=True))
362 active = StringBoolean(if_missing=False)
395 active = StringBoolean(if_missing=False)
363 name = UnicodeString(strip=True, min=1, not_empty=True)
396 name = UnicodeString(strip=True, min=1, not_empty=True)
364 lastname = UnicodeString(strip=True, min=1, not_empty=True)
397 lastname = UnicodeString(strip=True, min=1, not_empty=True)
365 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
398 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
366
399
367 chained_validators = [ValidPassword]
400 chained_validators = [ValidPassword]
368
401
369 return _UserForm
402 return _UserForm
370
403
404
405 def UsersGroupForm(edit=False, old_data={}):
406 class _UsersGroupForm(formencode.Schema):
407 allow_extra_fields = True
408 filter_extra_fields = True
409
410 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
411 ValidUsersGroup(edit, old_data))
412
413 users_group_active = StringBoolean(if_missing=False)
414
415 return _UsersGroupForm
416
371 def RegisterForm(edit=False, old_data={}):
417 def RegisterForm(edit=False, old_data={}):
372 class _RegisterForm(formencode.Schema):
418 class _RegisterForm(formencode.Schema):
373 allow_extra_fields = True
419 allow_extra_fields = True
374 filter_extra_fields = True
420 filter_extra_fields = True
375 username = All(ValidUsername(edit, old_data),
421 username = All(ValidUsername(edit, old_data),
376 UnicodeString(strip=True, min=1, not_empty=True))
422 UnicodeString(strip=True, min=1, not_empty=True))
377 password = All(UnicodeString(strip=True, min=6, not_empty=True))
423 password = All(UnicodeString(strip=True, min=6, not_empty=True))
378 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
424 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
379 active = StringBoolean(if_missing=False)
425 active = StringBoolean(if_missing=False)
380 name = UnicodeString(strip=True, min=1, not_empty=True)
426 name = UnicodeString(strip=True, min=1, not_empty=True)
381 lastname = UnicodeString(strip=True, min=1, not_empty=True)
427 lastname = UnicodeString(strip=True, min=1, not_empty=True)
382 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
428 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
383
429
384 chained_validators = [ValidPasswordsMatch, ValidPassword]
430 chained_validators = [ValidPasswordsMatch, ValidPassword]
385
431
386 return _RegisterForm
432 return _RegisterForm
387
433
388 def PasswordResetForm():
434 def PasswordResetForm():
389 class _PasswordResetForm(formencode.Schema):
435 class _PasswordResetForm(formencode.Schema):
390 allow_extra_fields = True
436 allow_extra_fields = True
391 filter_extra_fields = True
437 filter_extra_fields = True
392 email = All(ValidSystemEmail(), Email(not_empty=True))
438 email = All(ValidSystemEmail(), Email(not_empty=True))
393 return _PasswordResetForm
439 return _PasswordResetForm
394
440
395 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
441 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
396 class _RepoForm(formencode.Schema):
442 class _RepoForm(formencode.Schema):
397 allow_extra_fields = True
443 allow_extra_fields = True
398 filter_extra_fields = False
444 filter_extra_fields = False
399 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
445 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
400 ValidRepoName(edit, old_data))
446 ValidRepoName(edit, old_data))
401 description = UnicodeString(strip=True, min=1, not_empty=True)
447 description = UnicodeString(strip=True, min=1, not_empty=True)
402 private = StringBoolean(if_missing=False)
448 private = StringBoolean(if_missing=False)
403 enable_statistics = StringBoolean(if_missing=False)
449 enable_statistics = StringBoolean(if_missing=False)
404 repo_type = OneOf(supported_backends)
450 repo_type = OneOf(supported_backends)
405 if edit:
451 if edit:
406 user = All(Int(not_empty=True), ValidRepoUser)
452 user = All(Int(not_empty=True), ValidRepoUser)
407
453
408 chained_validators = [ValidPerms]
454 chained_validators = [ValidPerms]
409 return _RepoForm
455 return _RepoForm
410
456
411 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
457 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
412 class _RepoForkForm(formencode.Schema):
458 class _RepoForkForm(formencode.Schema):
413 allow_extra_fields = True
459 allow_extra_fields = True
414 filter_extra_fields = False
460 filter_extra_fields = False
415 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
461 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
416 ValidRepoName(edit, old_data))
462 ValidRepoName(edit, old_data))
417 description = UnicodeString(strip=True, min=1, not_empty=True)
463 description = UnicodeString(strip=True, min=1, not_empty=True)
418 private = StringBoolean(if_missing=False)
464 private = StringBoolean(if_missing=False)
419 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
465 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
420 return _RepoForkForm
466 return _RepoForkForm
421
467
422 def RepoSettingsForm(edit=False, old_data={}):
468 def RepoSettingsForm(edit=False, old_data={}):
423 class _RepoForm(formencode.Schema):
469 class _RepoForm(formencode.Schema):
424 allow_extra_fields = True
470 allow_extra_fields = True
425 filter_extra_fields = False
471 filter_extra_fields = False
426 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
472 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
427 ValidRepoName(edit, old_data))
473 ValidRepoName(edit, old_data))
428 description = UnicodeString(strip=True, min=1, not_empty=True)
474 description = UnicodeString(strip=True, min=1, not_empty=True)
429 private = StringBoolean(if_missing=False)
475 private = StringBoolean(if_missing=False)
430
476
431 chained_validators = [ValidPerms, ValidSettings]
477 chained_validators = [ValidPerms, ValidSettings]
432 return _RepoForm
478 return _RepoForm
433
479
434
480
435 def ApplicationSettingsForm():
481 def ApplicationSettingsForm():
436 class _ApplicationSettingsForm(formencode.Schema):
482 class _ApplicationSettingsForm(formencode.Schema):
437 allow_extra_fields = True
483 allow_extra_fields = True
438 filter_extra_fields = False
484 filter_extra_fields = False
439 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
485 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
440 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
486 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
441 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
487 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
442
488
443 return _ApplicationSettingsForm
489 return _ApplicationSettingsForm
444
490
445 def ApplicationUiSettingsForm():
491 def ApplicationUiSettingsForm():
446 class _ApplicationUiSettingsForm(formencode.Schema):
492 class _ApplicationUiSettingsForm(formencode.Schema):
447 allow_extra_fields = True
493 allow_extra_fields = True
448 filter_extra_fields = False
494 filter_extra_fields = False
449 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
495 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
450 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
496 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
451 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
497 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
452 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
498 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
453 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
499 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
454 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
500 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
455
501
456 return _ApplicationUiSettingsForm
502 return _ApplicationUiSettingsForm
457
503
458 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
504 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
459 class _DefaultPermissionsForm(formencode.Schema):
505 class _DefaultPermissionsForm(formencode.Schema):
460 allow_extra_fields = True
506 allow_extra_fields = True
461 filter_extra_fields = True
507 filter_extra_fields = True
462 overwrite_default = StringBoolean(if_missing=False)
508 overwrite_default = StringBoolean(if_missing=False)
463 anonymous = OneOf(['True', 'False'], if_missing=False)
509 anonymous = OneOf(['True', 'False'], if_missing=False)
464 default_perm = OneOf(perms_choices)
510 default_perm = OneOf(perms_choices)
465 default_register = OneOf(register_choices)
511 default_register = OneOf(register_choices)
466 default_create = OneOf(create_choices)
512 default_create = OneOf(create_choices)
467
513
468 return _DefaultPermissionsForm
514 return _DefaultPermissionsForm
469
515
470
516
471 def LdapSettingsForm():
517 def LdapSettingsForm():
472 class _LdapSettingsForm(formencode.Schema):
518 class _LdapSettingsForm(formencode.Schema):
473 allow_extra_fields = True
519 allow_extra_fields = True
474 filter_extra_fields = True
520 filter_extra_fields = True
475 pre_validators = [LdapLibValidator]
521 pre_validators = [LdapLibValidator]
476 ldap_active = StringBoolean(if_missing=False)
522 ldap_active = StringBoolean(if_missing=False)
477 ldap_host = UnicodeString(strip=True,)
523 ldap_host = UnicodeString(strip=True,)
478 ldap_port = Number(strip=True,)
524 ldap_port = Number(strip=True,)
479 ldap_ldaps = StringBoolean(if_missing=False)
525 ldap_ldaps = StringBoolean(if_missing=False)
480 ldap_dn_user = UnicodeString(strip=True,)
526 ldap_dn_user = UnicodeString(strip=True,)
481 ldap_dn_pass = UnicodeString(strip=True,)
527 ldap_dn_pass = UnicodeString(strip=True,)
482 ldap_base_dn = All(BaseDnValidator, UnicodeString(strip=True,))
528 ldap_base_dn = All(BaseDnValidator, UnicodeString(strip=True,))
483
529
484 return _LdapSettingsForm
530 return _LdapSettingsForm
@@ -1,26 +1,79
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
28 import logging
29 import traceback
30
31 from pylons.i18n.translation import _
32
33 from rhodecode.model import BaseModel
34 from rhodecode.model.caching_query import FromCache
35 from rhodecode.model.db import UsersGroup
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38
39 from sqlalchemy.exc import DatabaseError
40
41 log = logging.getLogger(__name__)
42
43
44 class UsersGroupModel(BaseModel):
45
46 def get(self, users_group_id, cache=False):
47 users_group = self.sa.query(UsersGroup)
48 if cache:
49 users_group = users_group.options(FromCache("sql_cache_short",
50 "get_users_group_%s" % users_group_id))
51 return users_group.get(users_group_id)
52
53
54 def get_by_groupname(self, users_group_name, cache=False, case_insensitive=False):
55
56 if case_insensitive:
57 user = self.sa.query(UsersGroup)\
58 .filter(UsersGroup.users_group_name.ilike(users_group_name))
59 else:
60 user = self.sa.query(UsersGroup)\
61 .filter(UsersGroup.users_group_name == users_group_name)
62 if cache:
63 user = user.options(FromCache("sql_cache_short",
64 "get_user_%s" % users_group_name))
65 return user.scalar()
66
67 def create(self, form_data):
68 try:
69 new_users_group = UsersGroup()
70 for k, v in form_data.items():
71 setattr(new_users_group, k, v)
72
73 self.sa.add(new_users_group)
74 self.sa.commit()
75 except:
76 log.error(traceback.format_exc())
77 self.sa.rollback()
78 raise
79
@@ -0,0 +1,55
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${_('Add users group')} - ${c.rhodecode_name}
6 </%def>
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 &raquo;
10 ${h.link_to(_('Users groups'),h.url('users_groups'))}
11 &raquo;
12 ${_('add new users group')}
13 </%def>
14
15 <%def name="page_nav()">
16 ${self.menu('admin')}
17 </%def>
18
19 <%def name="main()">
20 <div class="box">
21 <!-- box / title -->
22 <div class="title">
23 ${self.breadcrumbs()}
24 </div>
25 <!-- end box / title -->
26 ${h.form(url('users_groups'))}
27 <div class="form">
28 <!-- fields -->
29 <div class="fields">
30 <div class="field">
31 <div class="label">
32 <label for="users_group_name">${_('Group name')}:</label>
33 </div>
34 <div class="input">
35 ${h.text('users_group_name',class_='small')}
36 </div>
37 </div>
38
39 <div class="field">
40 <div class="label label-checkbox">
41 <label for="users_group_active">${_('Active')}:</label>
42 </div>
43 <div class="checkboxes">
44 ${h.checkbox('users_group_active',value=True)}
45 </div>
46 </div>
47
48 <div class="buttons">
49 ${h.submit('save','save',class_="ui-button")}
50 </div>
51 </div>
52 </div>
53 ${h.end_form()}
54 </div>
55 </%def> No newline at end of file
@@ -1,54 +1,53
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Users groups administration')} - ${c.rhodecode_name}
5 ${_('Users groups administration')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Users groups')}
9 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Users groups')}
10 </%def>
10 </%def>
11
11
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 </%def>
14 </%def>
15
15
16 <%def name="main()">
16 <%def name="main()">
17 <div class="box">
17 <div class="box">
18 <!-- box / title -->
18 <!-- box / title -->
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 <ul class="links">
21 <ul class="links">
22 <li>
22 <li>
23 <span>${h.link_to(u'ADD NEW USER GROUP',h.url('new_users_group'))}</span>
23 <span>${h.link_to(u'ADD NEW USER GROUP',h.url('new_users_group'))}</span>
24 </li>
24 </li>
25
25
26 </ul>
26 </ul>
27 </div>
27 </div>
28 <!-- end box / title -->
28 <!-- end box / title -->
29 <div class="table">
29 <div class="table">
30 <table class="table_disp">
30 <table class="table_disp">
31 <tr class="header">
31 <tr class="header">
32 <th></th>
33 <th class="left">${_('group name')}</th>
32 <th class="left">${_('group name')}</th>
34 <th class="left">${_('members')}</th>
33 <th class="left">${_('members')}</th>
35 <th class="left">${_('active')}</th>
34 <th class="left">${_('active')}</th>
36 <th class="left">${_('action')}</th>
35 <th class="left">${_('action')}</th>
37 </tr>
36 </tr>
38 %for cnt,u_group in enumerate(c.users_groups_list):
37 %for cnt,u_group in enumerate(c.users_groups_list):
39 <tr class="parity${cnt%2}">
38 <tr class="parity${cnt%2}">
40 <td>${h.link_to(u_group.groupname,h.url('edit_user_group', id=u_group.group_id))}</td>
39 <td>${h.link_to(u_group.users_group_name,h.url('edit_users_group', id=u_group.users_group_id))}</td>
41 <td>${u_group.members}</td>
40 <td>${len(u_group.members)}</td>
42 <td>${h.bool2icon(u_group.active)}</td>
41 <td>${h.bool2icon(u_group.users_group_active)}</td>
43 <td>
42 <td>
44 ${h.form(url('users_group', id=group.group_id),method='delete')}
43 ${h.form(url('users_group', id=u_group.users_group_id),method='delete')}
45 ${h.submit('remove_','delete',id="remove_group_%s" % group.group_id,
44 ${h.submit('remove_','delete',id="remove_group_%s" % u_group.users_group_id,
46 class_="delete_icon action_button",onclick="return confirm('Confirm to delete this user group');")}
45 class_="delete_icon action_button",onclick="return confirm('Confirm to delete this users group');")}
47 ${h.end_form()}
46 ${h.end_form()}
48 </td>
47 </td>
49 </tr>
48 </tr>
50 %endfor
49 %endfor
51 </table>
50 </table>
52 </div>
51 </div>
53 </div>
52 </div>
54 </%def>
53 </%def>
General Comments 0
You need to be logged in to leave comments. Login now