##// END OF EJS Templates
#49 Enabled anonymous access for web interface controllable from permissions pannel
marcink -
r673:dd532af2 beta
parent child Browse files
Show More
@@ -1,162 +1,165 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # permissions controller for pylons
3 # permissions controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 27, 2010
21 Created on April 27, 2010
22 permissions controller for pylons
22 permissions controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25
25
26 from formencode import htmlfill
26 from formencode import htmlfill
27 from pylons import request, session, tmpl_context as c, url
27 from pylons import request, session, tmpl_context as c, url
28 from pylons.controllers.util import abort, redirect
28 from pylons.controllers.util import abort, redirect
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from rhodecode.lib.base import BaseController, render
32 from rhodecode.lib.base import BaseController, render
33 from rhodecode.model.forms import UserForm, DefaultPermissionsForm
33 from rhodecode.model.forms import UserForm, DefaultPermissionsForm
34 from rhodecode.model.permission_model import PermissionModel
34 from rhodecode.model.permission_model import PermissionModel
35 from rhodecode.model.user import UserModel
35 from rhodecode.model.user import UserModel
36 import formencode
36 import formencode
37 import logging
37 import logging
38 import traceback
38 import traceback
39
39
40 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
41
41
42 class PermissionsController(BaseController):
42 class PermissionsController(BaseController):
43 """REST Controller styled on the Atom Publishing Protocol"""
43 """REST Controller styled on the Atom Publishing Protocol"""
44 # To properly map this controller, ensure your config/routing.py
44 # To properly map this controller, ensure your config/routing.py
45 # file has a resource setup:
45 # file has a resource setup:
46 # map.resource('permission', 'permissions')
46 # map.resource('permission', 'permissions')
47
47
48 @LoginRequired()
48 @LoginRequired()
49 @HasPermissionAllDecorator('hg.admin')
49 @HasPermissionAllDecorator('hg.admin')
50 def __before__(self):
50 def __before__(self):
51 c.admin_user = session.get('admin_user')
51 c.admin_user = session.get('admin_user')
52 c.admin_username = session.get('admin_username')
52 c.admin_username = session.get('admin_username')
53 super(PermissionsController, self).__before__()
53 super(PermissionsController, self).__before__()
54
54
55 self.perms_choices = [('repository.none', _('None'),),
55 self.perms_choices = [('repository.none', _('None'),),
56 ('repository.read', _('Read'),),
56 ('repository.read', _('Read'),),
57 ('repository.write', _('Write'),),
57 ('repository.write', _('Write'),),
58 ('repository.admin', _('Admin'),)]
58 ('repository.admin', _('Admin'),)]
59 self.register_choices = [
59 self.register_choices = [
60 ('hg.register.none', 'disabled'),
60 ('hg.register.none',
61 _('disabled')),
61 ('hg.register.manual_activate',
62 ('hg.register.manual_activate',
62 _('allowed with manual account activation')),
63 _('allowed with manual account activation')),
63 ('hg.register.auto_activate',
64 ('hg.register.auto_activate',
64 _('allowed with automatic account activation')), ]
65 _('allowed with automatic account activation')), ]
65
66
66 self.create_choices = [('hg.create.none', _('Disabled')),
67 self.create_choices = [('hg.create.none', _('Disabled')),
67 ('hg.create.repository', _('Enabled'))]
68 ('hg.create.repository', _('Enabled'))]
68
69
69
70
70 def index(self, format='html'):
71 def index(self, format='html'):
71 """GET /permissions: All items in the collection"""
72 """GET /permissions: All items in the collection"""
72 # url('permissions')
73 # url('permissions')
73
74
74 def create(self):
75 def create(self):
75 """POST /permissions: Create a new item"""
76 """POST /permissions: Create a new item"""
76 # url('permissions')
77 # url('permissions')
77
78
78 def new(self, format='html'):
79 def new(self, format='html'):
79 """GET /permissions/new: Form to create a new item"""
80 """GET /permissions/new: Form to create a new item"""
80 # url('new_permission')
81 # url('new_permission')
81
82
82 def update(self, id):
83 def update(self, id):
83 """PUT /permissions/id: Update an existing item"""
84 """PUT /permissions/id: Update an existing item"""
84 # Forms posted to this method should contain a hidden field:
85 # Forms posted to this method should contain a hidden field:
85 # <input type="hidden" name="_method" value="PUT" />
86 # <input type="hidden" name="_method" value="PUT" />
86 # Or using helpers:
87 # Or using helpers:
87 # h.form(url('permission', id=ID),
88 # h.form(url('permission', id=ID),
88 # method='put')
89 # method='put')
89 # url('permission', id=ID)
90 # url('permission', id=ID)
90
91
91 permission_model = PermissionModel()
92 permission_model = PermissionModel()
92
93
93 _form = DefaultPermissionsForm([x[0] for x in self.perms_choices],
94 _form = DefaultPermissionsForm([x[0] for x in self.perms_choices],
94 [x[0] for x in self.register_choices],
95 [x[0] for x in self.register_choices],
95 [x[0] for x in self.create_choices])()
96 [x[0] for x in self.create_choices])()
96
97
97 try:
98 try:
98 form_result = _form.to_python(dict(request.POST))
99 form_result = _form.to_python(dict(request.POST))
99 form_result.update({'perm_user_name':id})
100 form_result.update({'perm_user_name':id})
100 permission_model.update(form_result)
101 permission_model.update(form_result)
101 h.flash(_('Default permissions updated succesfully'),
102 h.flash(_('Default permissions updated succesfully'),
102 category='success')
103 category='success')
103
104
104 except formencode.Invalid, errors:
105 except formencode.Invalid, errors:
105 c.perms_choices = self.perms_choices
106 c.perms_choices = self.perms_choices
106 c.register_choices = self.register_choices
107 c.register_choices = self.register_choices
107 c.create_choices = self.create_choices
108 c.create_choices = self.create_choices
108
109
109 return htmlfill.render(
110 return htmlfill.render(
110 render('admin/permissions/permissions.html'),
111 render('admin/permissions/permissions.html'),
111 defaults=errors.value,
112 defaults=errors.value,
112 errors=errors.error_dict or {},
113 errors=errors.error_dict or {},
113 prefix_error=False,
114 prefix_error=False,
114 encoding="UTF-8")
115 encoding="UTF-8")
115 except Exception:
116 except Exception:
116 log.error(traceback.format_exc())
117 log.error(traceback.format_exc())
117 h.flash(_('error occured during update of permissions'),
118 h.flash(_('error occured during update of permissions'),
118 category='error')
119 category='error')
119
120
120 return redirect(url('edit_permission', id=id))
121 return redirect(url('edit_permission', id=id))
121
122
122
123
123
124
124 def delete(self, id):
125 def delete(self, id):
125 """DELETE /permissions/id: Delete an existing item"""
126 """DELETE /permissions/id: Delete an existing item"""
126 # Forms posted to this method should contain a hidden field:
127 # Forms posted to this method should contain a hidden field:
127 # <input type="hidden" name="_method" value="DELETE" />
128 # <input type="hidden" name="_method" value="DELETE" />
128 # Or using helpers:
129 # Or using helpers:
129 # h.form(url('permission', id=ID),
130 # h.form(url('permission', id=ID),
130 # method='delete')
131 # method='delete')
131 # url('permission', id=ID)
132 # url('permission', id=ID)
132
133
133 def show(self, id, format='html'):
134 def show(self, id, format='html'):
134 """GET /permissions/id: Show a specific item"""
135 """GET /permissions/id: Show a specific item"""
135 # url('permission', id=ID)
136 # url('permission', id=ID)
136
137
137 def edit(self, id, format='html'):
138 def edit(self, id, format='html'):
138 """GET /permissions/id/edit: Form to edit an existing item"""
139 """GET /permissions/id/edit: Form to edit an existing item"""
139 #url('edit_permission', id=ID)
140 #url('edit_permission', id=ID)
140 c.perms_choices = self.perms_choices
141 c.perms_choices = self.perms_choices
141 c.register_choices = self.register_choices
142 c.register_choices = self.register_choices
142 c.create_choices = self.create_choices
143 c.create_choices = self.create_choices
143
144
144 if id == 'default':
145 if id == 'default':
145 defaults = {'_method':'put'}
146 default_user = UserModel().get_by_username('default')
146 for p in UserModel().get_by_username('default').user_perms:
147 defaults = {'_method':'put',
148 'anonymous':default_user.active}
149 for p in default_user.user_perms:
147 if p.permission.permission_name.startswith('repository.'):
150 if p.permission.permission_name.startswith('repository.'):
148 defaults['default_perm'] = p.permission.permission_name
151 defaults['default_perm'] = p.permission.permission_name
149
152
150 if p.permission.permission_name.startswith('hg.register.'):
153 if p.permission.permission_name.startswith('hg.register.'):
151 defaults['default_register'] = p.permission.permission_name
154 defaults['default_register'] = p.permission.permission_name
152
155
153 if p.permission.permission_name.startswith('hg.create.'):
156 if p.permission.permission_name.startswith('hg.create.'):
154 defaults['default_create'] = p.permission.permission_name
157 defaults['default_create'] = p.permission.permission_name
155
158
156 return htmlfill.render(
159 return htmlfill.render(
157 render('admin/permissions/permissions.html'),
160 render('admin/permissions/permissions.html'),
158 defaults=defaults,
161 defaults=defaults,
159 encoding="UTF-8",
162 encoding="UTF-8",
160 force_defaults=True,)
163 force_defaults=True,)
161 else:
164 else:
162 return redirect(url('admin_home'))
165 return redirect(url('admin_home'))
@@ -1,312 +1,316 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # settings controller for pylons
3 # settings controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on July 14, 2010
21 Created on July 14, 2010
22 settings controller for pylons
22 settings controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from formencode import htmlfill
25 from formencode import htmlfill
26 from pylons import request, session, tmpl_context as c, url, app_globals as g, \
26 from pylons import request, session, tmpl_context as c, url, app_globals as g, \
27 config
27 config
28 from pylons.controllers.util import abort, redirect
28 from pylons.controllers.util import abort, redirect
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
32 HasPermissionAnyDecorator
32 HasPermissionAnyDecorator
33 from rhodecode.lib.base import BaseController, render
33 from rhodecode.lib.base import BaseController, render
34 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
34 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
35 set_rhodecode_config, get_hg_settings, get_hg_ui_settings
35 set_rhodecode_config, get_hg_settings, get_hg_ui_settings
36 from rhodecode.model.db import RhodeCodeSettings, RhodeCodeUi, Repository
36 from rhodecode.model.db import RhodeCodeSettings, RhodeCodeUi, Repository
37 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
37 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
38 ApplicationUiSettingsForm
38 ApplicationUiSettingsForm
39 from rhodecode.model.hg import HgModel
39 from rhodecode.model.hg import HgModel
40 from rhodecode.model.user import UserModel
40 from rhodecode.model.user import UserModel
41 from rhodecode.lib.celerylib import tasks, run_task
41 from rhodecode.lib.celerylib import tasks, run_task
42 from sqlalchemy import func
42 from sqlalchemy import func
43 import formencode
43 import formencode
44 import logging
44 import logging
45 import traceback
45 import traceback
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class SettingsController(BaseController):
50 class SettingsController(BaseController):
51 """REST Controller styled on the Atom Publishing Protocol"""
51 """REST Controller styled on the Atom Publishing Protocol"""
52 # To properly map this controller, ensure your config/routing.py
52 # To properly map this controller, ensure your config/routing.py
53 # file has a resource setup:
53 # file has a resource setup:
54 # map.resource('setting', 'settings', controller='admin/settings',
54 # map.resource('setting', 'settings', controller='admin/settings',
55 # path_prefix='/admin', name_prefix='admin_')
55 # path_prefix='/admin', name_prefix='admin_')
56
56
57
57
58 @LoginRequired()
58 @LoginRequired()
59 def __before__(self):
59 def __before__(self):
60 c.admin_user = session.get('admin_user')
60 c.admin_user = session.get('admin_user')
61 c.admin_username = session.get('admin_username')
61 c.admin_username = session.get('admin_username')
62 super(SettingsController, self).__before__()
62 super(SettingsController, self).__before__()
63
63
64
64
65 @HasPermissionAllDecorator('hg.admin')
65 @HasPermissionAllDecorator('hg.admin')
66 def index(self, format='html'):
66 def index(self, format='html'):
67 """GET /admin/settings: All items in the collection"""
67 """GET /admin/settings: All items in the collection"""
68 # url('admin_settings')
68 # url('admin_settings')
69
69
70 defaults = get_hg_settings()
70 defaults = get_hg_settings()
71 defaults.update(get_hg_ui_settings())
71 defaults.update(get_hg_ui_settings())
72 return htmlfill.render(
72 return htmlfill.render(
73 render('admin/settings/settings.html'),
73 render('admin/settings/settings.html'),
74 defaults=defaults,
74 defaults=defaults,
75 encoding="UTF-8",
75 encoding="UTF-8",
76 force_defaults=False
76 force_defaults=False
77 )
77 )
78
78
79 @HasPermissionAllDecorator('hg.admin')
79 @HasPermissionAllDecorator('hg.admin')
80 def create(self):
80 def create(self):
81 """POST /admin/settings: Create a new item"""
81 """POST /admin/settings: Create a new item"""
82 # url('admin_settings')
82 # url('admin_settings')
83
83
84 @HasPermissionAllDecorator('hg.admin')
84 @HasPermissionAllDecorator('hg.admin')
85 def new(self, format='html'):
85 def new(self, format='html'):
86 """GET /admin/settings/new: Form to create a new item"""
86 """GET /admin/settings/new: Form to create a new item"""
87 # url('admin_new_setting')
87 # url('admin_new_setting')
88
88
89 @HasPermissionAllDecorator('hg.admin')
89 @HasPermissionAllDecorator('hg.admin')
90 def update(self, setting_id):
90 def update(self, setting_id):
91 """PUT /admin/settings/setting_id: Update an existing item"""
91 """PUT /admin/settings/setting_id: Update an existing item"""
92 # Forms posted to this method should contain a hidden field:
92 # Forms posted to this method should contain a hidden field:
93 # <input type="hidden" name="_method" value="PUT" />
93 # <input type="hidden" name="_method" value="PUT" />
94 # Or using helpers:
94 # Or using helpers:
95 # h.form(url('admin_setting', setting_id=ID),
95 # h.form(url('admin_setting', setting_id=ID),
96 # method='put')
96 # method='put')
97 # url('admin_setting', setting_id=ID)
97 # url('admin_setting', setting_id=ID)
98 if setting_id == 'mapping':
98 if setting_id == 'mapping':
99 rm_obsolete = request.POST.get('destroy', False)
99 rm_obsolete = request.POST.get('destroy', False)
100 log.debug('Rescanning directories with destroy=%s', rm_obsolete)
100 log.debug('Rescanning directories with destroy=%s', rm_obsolete)
101
101
102 initial = HgModel().repo_scan(g.paths[0][1], g.baseui)
102 initial = HgModel().repo_scan(g.paths[0][1], g.baseui)
103 for repo_name in initial.keys():
103 for repo_name in initial.keys():
104 invalidate_cache('get_repo_cached_%s' % repo_name)
104 invalidate_cache('get_repo_cached_%s' % repo_name)
105
105
106 repo2db_mapper(initial, rm_obsolete)
106 repo2db_mapper(initial, rm_obsolete)
107
107
108 h.flash(_('Repositories successfully rescanned'), category='success')
108 h.flash(_('Repositories successfully rescanned'), category='success')
109
109
110 if setting_id == 'whoosh':
110 if setting_id == 'whoosh':
111 repo_location = get_hg_ui_settings()['paths_root_path']
111 repo_location = get_hg_ui_settings()['paths_root_path']
112 full_index = request.POST.get('full_index', False)
112 full_index = request.POST.get('full_index', False)
113 task = run_task(tasks.whoosh_index, repo_location, full_index)
113 task = run_task(tasks.whoosh_index, repo_location, full_index)
114
114
115 h.flash(_('Whoosh reindex task scheduled'), category='success')
115 h.flash(_('Whoosh reindex task scheduled'), category='success')
116 if setting_id == 'global':
116 if setting_id == 'global':
117
117
118 application_form = ApplicationSettingsForm()()
118 application_form = ApplicationSettingsForm()()
119 try:
119 try:
120 form_result = application_form.to_python(dict(request.POST))
120 form_result = application_form.to_python(dict(request.POST))
121
121
122 try:
122 try:
123 hgsettings1 = self.sa.query(RhodeCodeSettings)\
123 hgsettings1 = self.sa.query(RhodeCodeSettings)\
124 .filter(RhodeCodeSettings.app_settings_name == 'title').one()
124 .filter(RhodeCodeSettings.app_settings_name \
125 == 'title').one()
126
125 hgsettings1.app_settings_value = form_result['rhodecode_title']
127 hgsettings1.app_settings_value = form_result['rhodecode_title']
126
128
127 hgsettings2 = self.sa.query(RhodeCodeSettings)\
129 hgsettings2 = self.sa.query(RhodeCodeSettings)\
128 .filter(RhodeCodeSettings.app_settings_name == 'realm').one()
130 .filter(RhodeCodeSettings.app_settings_name \
131 == 'realm').one()
132
129 hgsettings2.app_settings_value = form_result['rhodecode_realm']
133 hgsettings2.app_settings_value = form_result['rhodecode_realm']
130
134
131
135
132 self.sa.add(hgsettings1)
136 self.sa.add(hgsettings1)
133 self.sa.add(hgsettings2)
137 self.sa.add(hgsettings2)
134 self.sa.commit()
138 self.sa.commit()
135 set_rhodecode_config(config)
139 set_rhodecode_config(config)
136 h.flash(_('Updated application settings'),
140 h.flash(_('Updated application settings'),
137 category='success')
141 category='success')
138
142
139 except:
143 except:
140 log.error(traceback.format_exc())
144 log.error(traceback.format_exc())
141 h.flash(_('error occurred during updating application settings'),
145 h.flash(_('error occurred during updating application settings'),
142 category='error')
146 category='error')
143
147
144 self.sa.rollback()
148 self.sa.rollback()
145
149
146
150
147 except formencode.Invalid, errors:
151 except formencode.Invalid, errors:
148 return htmlfill.render(
152 return htmlfill.render(
149 render('admin/settings/settings.html'),
153 render('admin/settings/settings.html'),
150 defaults=errors.value,
154 defaults=errors.value,
151 errors=errors.error_dict or {},
155 errors=errors.error_dict or {},
152 prefix_error=False,
156 prefix_error=False,
153 encoding="UTF-8")
157 encoding="UTF-8")
154
158
155 if setting_id == 'mercurial':
159 if setting_id == 'mercurial':
156 application_form = ApplicationUiSettingsForm()()
160 application_form = ApplicationUiSettingsForm()()
157 try:
161 try:
158 form_result = application_form.to_python(dict(request.POST))
162 form_result = application_form.to_python(dict(request.POST))
159
163
160 try:
164 try:
161
165
162 hgsettings1 = self.sa.query(RhodeCodeUi)\
166 hgsettings1 = self.sa.query(RhodeCodeUi)\
163 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
167 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
164 hgsettings1.ui_value = form_result['web_push_ssl']
168 hgsettings1.ui_value = form_result['web_push_ssl']
165
169
166 hgsettings2 = self.sa.query(RhodeCodeUi)\
170 hgsettings2 = self.sa.query(RhodeCodeUi)\
167 .filter(RhodeCodeUi.ui_key == '/').one()
171 .filter(RhodeCodeUi.ui_key == '/').one()
168 hgsettings2.ui_value = form_result['paths_root_path']
172 hgsettings2.ui_value = form_result['paths_root_path']
169
173
170
174
171 #HOOKS
175 #HOOKS
172 hgsettings3 = self.sa.query(RhodeCodeUi)\
176 hgsettings3 = self.sa.query(RhodeCodeUi)\
173 .filter(RhodeCodeUi.ui_key == 'changegroup.update').one()
177 .filter(RhodeCodeUi.ui_key == 'changegroup.update').one()
174 hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
178 hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
175
179
176 hgsettings4 = self.sa.query(RhodeCodeUi)\
180 hgsettings4 = self.sa.query(RhodeCodeUi)\
177 .filter(RhodeCodeUi.ui_key == 'changegroup.repo_size').one()
181 .filter(RhodeCodeUi.ui_key == 'changegroup.repo_size').one()
178 hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
182 hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
179
183
180 hgsettings5 = self.sa.query(RhodeCodeUi)\
184 hgsettings5 = self.sa.query(RhodeCodeUi)\
181 .filter(RhodeCodeUi.ui_key == 'pretxnchangegroup.push_logger').one()
185 .filter(RhodeCodeUi.ui_key == 'pretxnchangegroup.push_logger').one()
182 hgsettings5.ui_active = bool(form_result['hooks_pretxnchangegroup_push_logger'])
186 hgsettings5.ui_active = bool(form_result['hooks_pretxnchangegroup_push_logger'])
183
187
184 hgsettings6 = self.sa.query(RhodeCodeUi)\
188 hgsettings6 = self.sa.query(RhodeCodeUi)\
185 .filter(RhodeCodeUi.ui_key == 'preoutgoing.pull_logger').one()
189 .filter(RhodeCodeUi.ui_key == 'preoutgoing.pull_logger').one()
186 hgsettings6.ui_active = bool(form_result['hooks_preoutgoing_pull_logger'])
190 hgsettings6.ui_active = bool(form_result['hooks_preoutgoing_pull_logger'])
187
191
188
192
189 self.sa.add(hgsettings1)
193 self.sa.add(hgsettings1)
190 self.sa.add(hgsettings2)
194 self.sa.add(hgsettings2)
191 self.sa.add(hgsettings3)
195 self.sa.add(hgsettings3)
192 self.sa.add(hgsettings4)
196 self.sa.add(hgsettings4)
193 self.sa.add(hgsettings5)
197 self.sa.add(hgsettings5)
194 self.sa.add(hgsettings6)
198 self.sa.add(hgsettings6)
195 self.sa.commit()
199 self.sa.commit()
196
200
197 h.flash(_('Updated mercurial settings'),
201 h.flash(_('Updated mercurial settings'),
198 category='success')
202 category='success')
199
203
200 except:
204 except:
201 log.error(traceback.format_exc())
205 log.error(traceback.format_exc())
202 h.flash(_('error occurred during updating application settings'),
206 h.flash(_('error occurred during updating application settings'),
203 category='error')
207 category='error')
204
208
205 self.sa.rollback()
209 self.sa.rollback()
206
210
207
211
208 except formencode.Invalid, errors:
212 except formencode.Invalid, errors:
209 return htmlfill.render(
213 return htmlfill.render(
210 render('admin/settings/settings.html'),
214 render('admin/settings/settings.html'),
211 defaults=errors.value,
215 defaults=errors.value,
212 errors=errors.error_dict or {},
216 errors=errors.error_dict or {},
213 prefix_error=False,
217 prefix_error=False,
214 encoding="UTF-8")
218 encoding="UTF-8")
215
219
216
220
217
221
218 return redirect(url('admin_settings'))
222 return redirect(url('admin_settings'))
219
223
220 @HasPermissionAllDecorator('hg.admin')
224 @HasPermissionAllDecorator('hg.admin')
221 def delete(self, setting_id):
225 def delete(self, setting_id):
222 """DELETE /admin/settings/setting_id: Delete an existing item"""
226 """DELETE /admin/settings/setting_id: Delete an existing item"""
223 # Forms posted to this method should contain a hidden field:
227 # Forms posted to this method should contain a hidden field:
224 # <input type="hidden" name="_method" value="DELETE" />
228 # <input type="hidden" name="_method" value="DELETE" />
225 # Or using helpers:
229 # Or using helpers:
226 # h.form(url('admin_setting', setting_id=ID),
230 # h.form(url('admin_setting', setting_id=ID),
227 # method='delete')
231 # method='delete')
228 # url('admin_setting', setting_id=ID)
232 # url('admin_setting', setting_id=ID)
229
233
230 @HasPermissionAllDecorator('hg.admin')
234 @HasPermissionAllDecorator('hg.admin')
231 def show(self, setting_id, format='html'):
235 def show(self, setting_id, format='html'):
232 """GET /admin/settings/setting_id: Show a specific item"""
236 """GET /admin/settings/setting_id: Show a specific item"""
233 # url('admin_setting', setting_id=ID)
237 # url('admin_setting', setting_id=ID)
234
238
235 @HasPermissionAllDecorator('hg.admin')
239 @HasPermissionAllDecorator('hg.admin')
236 def edit(self, setting_id, format='html'):
240 def edit(self, setting_id, format='html'):
237 """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
241 """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
238 # url('admin_edit_setting', setting_id=ID)
242 # url('admin_edit_setting', setting_id=ID)
239
243
240
244
241 def my_account(self):
245 def my_account(self):
242 """
246 """
243 GET /_admin/my_account Displays info about my account
247 GET /_admin/my_account Displays info about my account
244 """
248 """
245
249
246 # url('admin_settings_my_account')
250 # url('admin_settings_my_account')
247 c.user = UserModel(self.sa).get(c.rhodecode_user.user_id, cache=False)
251 c.user = UserModel(self.sa).get(c.rhodecode_user.user_id, cache=False)
248 all_repos = self.sa.query(Repository)\
252 all_repos = self.sa.query(Repository)\
249 .filter(Repository.user_id == c.user.user_id)\
253 .filter(Repository.user_id == c.user.user_id)\
250 .order_by(func.lower(Repository.repo_name))\
254 .order_by(func.lower(Repository.repo_name))\
251 .all()
255 .all()
252 c.user_repos = HgModel().get_repos(all_repos)
256 c.user_repos = HgModel().get_repos(all_repos)
253
257
254 if c.user.username == 'default':
258 if c.user.username == 'default':
255 h.flash(_("You can't edit this user since it's"
259 h.flash(_("You can't edit this user since it's"
256 " crucial for entire application"), category='warning')
260 " crucial for entire application"), category='warning')
257 return redirect(url('users'))
261 return redirect(url('users'))
258
262
259 defaults = c.user.__dict__
263 defaults = c.user.__dict__
260 return htmlfill.render(
264 return htmlfill.render(
261 render('admin/users/user_edit_my_account.html'),
265 render('admin/users/user_edit_my_account.html'),
262 defaults=defaults,
266 defaults=defaults,
263 encoding="UTF-8",
267 encoding="UTF-8",
264 force_defaults=False
268 force_defaults=False
265 )
269 )
266
270
267 def my_account_update(self):
271 def my_account_update(self):
268 """PUT /_admin/my_account_update: Update an existing item"""
272 """PUT /_admin/my_account_update: Update an existing item"""
269 # Forms posted to this method should contain a hidden field:
273 # Forms posted to this method should contain a hidden field:
270 # <input type="hidden" name="_method" value="PUT" />
274 # <input type="hidden" name="_method" value="PUT" />
271 # Or using helpers:
275 # Or using helpers:
272 # h.form(url('admin_settings_my_account_update'),
276 # h.form(url('admin_settings_my_account_update'),
273 # method='put')
277 # method='put')
274 # url('admin_settings_my_account_update', id=ID)
278 # url('admin_settings_my_account_update', id=ID)
275 user_model = UserModel()
279 user_model = UserModel()
276 uid = c.rhodecode_user.user_id
280 uid = c.rhodecode_user.user_id
277 _form = UserForm(edit=True, old_data={'user_id':uid,
281 _form = UserForm(edit=True, old_data={'user_id':uid,
278 'email':c.rhodecode_user.email})()
282 'email':c.rhodecode_user.email})()
279 form_result = {}
283 form_result = {}
280 try:
284 try:
281 form_result = _form.to_python(dict(request.POST))
285 form_result = _form.to_python(dict(request.POST))
282 user_model.update_my_account(uid, form_result)
286 user_model.update_my_account(uid, form_result)
283 h.flash(_('Your account was updated succesfully'),
287 h.flash(_('Your account was updated succesfully'),
284 category='success')
288 category='success')
285
289
286 except formencode.Invalid, errors:
290 except formencode.Invalid, errors:
287 c.user = user_model.get(c.rhodecode_user.user_id, cache=False)
291 c.user = user_model.get(c.rhodecode_user.user_id, cache=False)
288 c.user_repos = []
292 c.user_repos = []
289 for repo in c.cached_repo_list.values():
293 for repo in c.cached_repo_list.values():
290 if repo.dbrepo.user.username == c.user.username:
294 if repo.dbrepo.user.username == c.user.username:
291 c.user_repos.append(repo)
295 c.user_repos.append(repo)
292 return htmlfill.render(
296 return htmlfill.render(
293 render('admin/users/user_edit_my_account.html'),
297 render('admin/users/user_edit_my_account.html'),
294 defaults=errors.value,
298 defaults=errors.value,
295 errors=errors.error_dict or {},
299 errors=errors.error_dict or {},
296 prefix_error=False,
300 prefix_error=False,
297 encoding="UTF-8")
301 encoding="UTF-8")
298 except Exception:
302 except Exception:
299 log.error(traceback.format_exc())
303 log.error(traceback.format_exc())
300 h.flash(_('error occured during update of user %s') \
304 h.flash(_('error occured during update of user %s') \
301 % form_result.get('username'), category='error')
305 % form_result.get('username'), category='error')
302
306
303 return redirect(url('my_account'))
307 return redirect(url('my_account'))
304
308
305 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
309 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
306 def create_repository(self):
310 def create_repository(self):
307 """GET /_admin/create_repository: Form to create a new item"""
311 """GET /_admin/create_repository: Form to create a new item"""
308 new_repo = request.GET.get('repo', '')
312 new_repo = request.GET.get('repo', '')
309 c.new_repo = h.repo_name_slug(new_repo)
313 c.new_repo = h.repo_name_slug(new_repo)
310
314
311 return render('admin/repos/repo_add_create_repository.html')
315 return render('admin/repos/repo_add_create_repository.html')
312
316
@@ -1,168 +1,167 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # users controller for pylons
3 # users controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 from rhodecode.lib.utils import action_logger
20 from rhodecode.lib.utils import action_logger
21 """
21 """
22 Created on April 4, 2010
22 Created on April 4, 2010
23 users controller for pylons
23 users controller for pylons
24 @author: marcink
24 @author: marcink
25 """
25 """
26
26
27 from formencode import htmlfill
27 from formencode import htmlfill
28 from pylons import request, session, tmpl_context as c, url
28 from pylons import request, session, tmpl_context as c, url
29 from pylons.controllers.util import abort, redirect
29 from pylons.controllers.util import abort, redirect
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
33 from rhodecode.lib.base import BaseController, render
33 from rhodecode.lib.base import BaseController, render
34 from rhodecode.model.db import User, UserLog
34 from rhodecode.model.db import User, UserLog
35 from rhodecode.model.forms import UserForm
35 from rhodecode.model.forms import UserForm
36 from rhodecode.model.user import UserModel, DefaultUserException
36 from rhodecode.model.user import UserModel, DefaultUserException
37 import formencode
37 import formencode
38 import logging
38 import logging
39 import traceback
39 import traceback
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43 class UsersController(BaseController):
43 class UsersController(BaseController):
44 """REST Controller styled on the Atom Publishing Protocol"""
44 """REST Controller styled on the Atom Publishing Protocol"""
45 # To properly map this controller, ensure your config/routing.py
45 # To properly map this controller, ensure your config/routing.py
46 # file has a resource setup:
46 # file has a resource setup:
47 # map.resource('user', 'users')
47 # map.resource('user', 'users')
48
48
49 @LoginRequired()
49 @LoginRequired()
50 @HasPermissionAllDecorator('hg.admin')
50 @HasPermissionAllDecorator('hg.admin')
51 def __before__(self):
51 def __before__(self):
52 c.admin_user = session.get('admin_user')
52 c.admin_user = session.get('admin_user')
53 c.admin_username = session.get('admin_username')
53 c.admin_username = session.get('admin_username')
54 super(UsersController, self).__before__()
54 super(UsersController, self).__before__()
55
55
56
56
57 def index(self, format='html'):
57 def index(self, format='html'):
58 """GET /users: All items in the collection"""
58 """GET /users: All items in the collection"""
59 # url('users')
59 # url('users')
60
60
61 c.users_list = self.sa.query(User).all()
61 c.users_list = self.sa.query(User).all()
62 return render('admin/users/users.html')
62 return render('admin/users/users.html')
63
63
64 def create(self):
64 def create(self):
65 """POST /users: Create a new item"""
65 """POST /users: Create a new item"""
66 # url('users')
66 # url('users')
67
67
68 user_model = UserModel()
68 user_model = UserModel()
69 login_form = UserForm()()
69 login_form = UserForm()()
70 try:
70 try:
71 form_result = login_form.to_python(dict(request.POST))
71 form_result = login_form.to_python(dict(request.POST))
72 user_model.create(form_result)
72 user_model.create(form_result)
73 h.flash(_('created user %s') % form_result['username'],
73 h.flash(_('created user %s') % form_result['username'],
74 category='success')
74 category='success')
75 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
75 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
76 except formencode.Invalid, errors:
76 except formencode.Invalid, errors:
77 return htmlfill.render(
77 return htmlfill.render(
78 render('admin/users/user_add.html'),
78 render('admin/users/user_add.html'),
79 defaults=errors.value,
79 defaults=errors.value,
80 errors=errors.error_dict or {},
80 errors=errors.error_dict or {},
81 prefix_error=False,
81 prefix_error=False,
82 encoding="UTF-8")
82 encoding="UTF-8")
83 except Exception:
83 except Exception:
84 log.error(traceback.format_exc())
84 log.error(traceback.format_exc())
85 h.flash(_('error occured during creation of user %s') \
85 h.flash(_('error occured during creation of user %s') \
86 % request.POST.get('username'), category='error')
86 % request.POST.get('username'), category='error')
87 return redirect(url('users'))
87 return redirect(url('users'))
88
88
89 def new(self, format='html'):
89 def new(self, format='html'):
90 """GET /users/new: Form to create a new item"""
90 """GET /users/new: Form to create a new item"""
91 # url('new_user')
91 # url('new_user')
92 return render('admin/users/user_add.html')
92 return render('admin/users/user_add.html')
93
93
94 def update(self, id):
94 def update(self, id):
95 """PUT /users/id: Update an existing item"""
95 """PUT /users/id: Update an existing item"""
96 # Forms posted to this method should contain a hidden field:
96 # Forms posted to this method should contain a hidden field:
97 # <input type="hidden" name="_method" value="PUT" />
97 # <input type="hidden" name="_method" value="PUT" />
98 # Or using helpers:
98 # Or using helpers:
99 # h.form(url('user', id=ID),
99 # h.form(url('user', id=ID),
100 # method='put')
100 # method='put')
101 # url('user', id=ID)
101 # url('user', id=ID)
102 user_model = UserModel()
102 user_model = UserModel()
103 c.user = user_model.get(id)
103 c.user = user_model.get(id)
104
104
105 _form = UserForm(edit=True, old_data={'user_id':id,
105 _form = UserForm(edit=True, old_data={'user_id':id,
106 'email':c.user.email})()
106 'email':c.user.email})()
107 form_result = {}
107 form_result = {}
108 try:
108 try:
109 form_result = _form.to_python(dict(request.POST))
109 form_result = _form.to_python(dict(request.POST))
110 user_model.update(id, form_result)
110 user_model.update(id, form_result)
111 h.flash(_('User updated succesfully'), category='success')
111 h.flash(_('User updated succesfully'), category='success')
112
112
113 except formencode.Invalid, errors:
113 except formencode.Invalid, errors:
114 return htmlfill.render(
114 return htmlfill.render(
115 render('admin/users/user_edit.html'),
115 render('admin/users/user_edit.html'),
116 defaults=errors.value,
116 defaults=errors.value,
117 errors=errors.error_dict or {},
117 errors=errors.error_dict or {},
118 prefix_error=False,
118 prefix_error=False,
119 encoding="UTF-8")
119 encoding="UTF-8")
120 except Exception:
120 except Exception:
121 log.error(traceback.format_exc())
121 log.error(traceback.format_exc())
122 h.flash(_('error occured during update of user %s') \
122 h.flash(_('error occured during update of user %s') \
123 % form_result.get('username'), category='error')
123 % form_result.get('username'), category='error')
124
124
125 return redirect(url('users'))
125 return redirect(url('users'))
126
126
127 def delete(self, id):
127 def delete(self, id):
128 """DELETE /users/id: Delete an existing item"""
128 """DELETE /users/id: Delete an existing item"""
129 # Forms posted to this method should contain a hidden field:
129 # Forms posted to this method should contain a hidden field:
130 # <input type="hidden" name="_method" value="DELETE" />
130 # <input type="hidden" name="_method" value="DELETE" />
131 # Or using helpers:
131 # Or using helpers:
132 # h.form(url('user', id=ID),
132 # h.form(url('user', id=ID),
133 # method='delete')
133 # method='delete')
134 # url('user', id=ID)
134 # url('user', id=ID)
135 user_model = UserModel()
135 user_model = UserModel()
136 try:
136 try:
137 user_model.delete(id)
137 user_model.delete(id)
138 h.flash(_('sucessfully deleted user'), category='success')
138 h.flash(_('sucessfully deleted user'), category='success')
139 except DefaultUserException, e:
139 except DefaultUserException, e:
140 h.flash(str(e), category='warning')
140 h.flash(str(e), category='warning')
141 except Exception:
141 except Exception:
142 h.flash(_('An error occured during deletion of user'),
142 h.flash(_('An error occured during deletion of user'),
143 category='error')
143 category='error')
144 return redirect(url('users'))
144 return redirect(url('users'))
145
145
146 def show(self, id, format='html'):
146 def show(self, id, format='html'):
147 """GET /users/id: Show a specific item"""
147 """GET /users/id: Show a specific item"""
148 # url('user', id=ID)
148 # url('user', id=ID)
149
149
150
150
151 def edit(self, id, format='html'):
151 def edit(self, id, format='html'):
152 """GET /users/id/edit: Form to edit an existing item"""
152 """GET /users/id/edit: Form to edit an existing item"""
153 # url('edit_user', id=ID)
153 # url('edit_user', id=ID)
154 c.user = self.sa.query(User).get(id)
154 c.user = self.sa.query(User).get(id)
155 if not c.user:
155 if not c.user:
156 return redirect(url('users'))
156 return redirect(url('users'))
157 if c.user.username == 'default':
157 if c.user.username == 'default':
158 h.flash(_("You can't edit this user since it's"
158 h.flash(_("You can't edit this user"), category='warning')
159 " crucial for entire application"), category='warning')
160 return redirect(url('users'))
159 return redirect(url('users'))
161
160
162 defaults = c.user.__dict__
161 defaults = c.user.__dict__
163 return htmlfill.render(
162 return htmlfill.render(
164 render('admin/users/user_edit.html'),
163 render('admin/users/user_edit.html'),
165 defaults=defaults,
164 defaults=defaults,
166 encoding="UTF-8",
165 encoding="UTF-8",
167 force_defaults=False
166 force_defaults=False
168 )
167 )
@@ -1,144 +1,146 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # login controller for pylons
3 # login controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20
20
21 """
21 """
22 Created on April 22, 2010
22 Created on April 22, 2010
23 login controller for pylons
23 login controller for pylons
24 @author: marcink
24 @author: marcink
25 """
25 """
26 from formencode import htmlfill
26 from formencode import htmlfill
27 from pylons import request, response, session, tmpl_context as c, url
27 from pylons import request, response, session, tmpl_context as c, url
28 from pylons.controllers.util import abort, redirect
28 from pylons.controllers.util import abort, redirect
29 from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator
29 from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator
30 from rhodecode.lib.base import BaseController, render
30 from rhodecode.lib.base import BaseController, render
31 import rhodecode.lib.helpers as h
31 import rhodecode.lib.helpers as h
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm
33 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm
34 from rhodecode.model.user import UserModel
34 from rhodecode.model.user import UserModel
35 import formencode
35 import formencode
36 import logging
36 import logging
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40 class LoginController(BaseController):
40 class LoginController(BaseController):
41
41
42 def __before__(self):
42 def __before__(self):
43 super(LoginController, self).__before__()
43 super(LoginController, self).__before__()
44
44
45 def index(self):
45 def index(self):
46 #redirect if already logged in
46 #redirect if already logged in
47 c.came_from = request.GET.get('came_from', None)
47 c.came_from = request.GET.get('came_from', None)
48
48
49 if c.rhodecode_user.is_authenticated:
49 if c.rhodecode_user.is_authenticated \
50 and c.rhodecode_user.username != 'default':
51
50 return redirect(url('home'))
52 return redirect(url('home'))
51
53
52 if request.POST:
54 if request.POST:
53 #import Login Form validator class
55 #import Login Form validator class
54 login_form = LoginForm()
56 login_form = LoginForm()
55 try:
57 try:
56 c.form_result = login_form.to_python(dict(request.POST))
58 c.form_result = login_form.to_python(dict(request.POST))
57 username = c.form_result['username']
59 username = c.form_result['username']
58 user = UserModel().get_by_username(username)
60 user = UserModel().get_by_username(username)
59 auth_user = AuthUser()
61 auth_user = AuthUser()
60 auth_user.username = user.username
62 auth_user.username = user.username
61 auth_user.is_authenticated = True
63 auth_user.is_authenticated = True
62 auth_user.is_admin = user.admin
64 auth_user.is_admin = user.admin
63 auth_user.user_id = user.user_id
65 auth_user.user_id = user.user_id
64 auth_user.name = user.name
66 auth_user.name = user.name
65 auth_user.lastname = user.lastname
67 auth_user.lastname = user.lastname
66 session['rhodecode_user'] = auth_user
68 session['rhodecode_user'] = auth_user
67 session.save()
69 session.save()
68 log.info('user %s is now authenticated', username)
70 log.info('user %s is now authenticated', username)
69
71
70 user.update_lastlogin()
72 user.update_lastlogin()
71
73
72 if c.came_from:
74 if c.came_from:
73 return redirect(c.came_from)
75 return redirect(c.came_from)
74 else:
76 else:
75 return redirect(url('home'))
77 return redirect(url('home'))
76
78
77 except formencode.Invalid, errors:
79 except formencode.Invalid, errors:
78 return htmlfill.render(
80 return htmlfill.render(
79 render('/login.html'),
81 render('/login.html'),
80 defaults=errors.value,
82 defaults=errors.value,
81 errors=errors.error_dict or {},
83 errors=errors.error_dict or {},
82 prefix_error=False,
84 prefix_error=False,
83 encoding="UTF-8")
85 encoding="UTF-8")
84
86
85 return render('/login.html')
87 return render('/login.html')
86
88
87 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
89 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
88 'hg.register.manual_activate')
90 'hg.register.manual_activate')
89 def register(self):
91 def register(self):
90 user_model = UserModel()
92 user_model = UserModel()
91 c.auto_active = False
93 c.auto_active = False
92 for perm in user_model.get_by_username('default', cache=False).user_perms:
94 for perm in user_model.get_by_username('default', cache=False).user_perms:
93 if perm.permission.permission_name == 'hg.register.auto_activate':
95 if perm.permission.permission_name == 'hg.register.auto_activate':
94 c.auto_active = True
96 c.auto_active = True
95 break
97 break
96
98
97 if request.POST:
99 if request.POST:
98
100
99 register_form = RegisterForm()()
101 register_form = RegisterForm()()
100 try:
102 try:
101 form_result = register_form.to_python(dict(request.POST))
103 form_result = register_form.to_python(dict(request.POST))
102 form_result['active'] = c.auto_active
104 form_result['active'] = c.auto_active
103 user_model.create_registration(form_result)
105 user_model.create_registration(form_result)
104 h.flash(_('You have successfully registered into rhodecode'),
106 h.flash(_('You have successfully registered into rhodecode'),
105 category='success')
107 category='success')
106 return redirect(url('login_home'))
108 return redirect(url('login_home'))
107
109
108 except formencode.Invalid, errors:
110 except formencode.Invalid, errors:
109 return htmlfill.render(
111 return htmlfill.render(
110 render('/register.html'),
112 render('/register.html'),
111 defaults=errors.value,
113 defaults=errors.value,
112 errors=errors.error_dict or {},
114 errors=errors.error_dict or {},
113 prefix_error=False,
115 prefix_error=False,
114 encoding="UTF-8")
116 encoding="UTF-8")
115
117
116 return render('/register.html')
118 return render('/register.html')
117
119
118 def password_reset(self):
120 def password_reset(self):
119 user_model = UserModel()
121 user_model = UserModel()
120 if request.POST:
122 if request.POST:
121
123
122 password_reset_form = PasswordResetForm()()
124 password_reset_form = PasswordResetForm()()
123 try:
125 try:
124 form_result = password_reset_form.to_python(dict(request.POST))
126 form_result = password_reset_form.to_python(dict(request.POST))
125 user_model.reset_password(form_result)
127 user_model.reset_password(form_result)
126 h.flash(_('Your new password was sent'),
128 h.flash(_('Your new password was sent'),
127 category='success')
129 category='success')
128 return redirect(url('login_home'))
130 return redirect(url('login_home'))
129
131
130 except formencode.Invalid, errors:
132 except formencode.Invalid, errors:
131 return htmlfill.render(
133 return htmlfill.render(
132 render('/password_reset.html'),
134 render('/password_reset.html'),
133 defaults=errors.value,
135 defaults=errors.value,
134 errors=errors.error_dict or {},
136 errors=errors.error_dict or {},
135 prefix_error=False,
137 prefix_error=False,
136 encoding="UTF-8")
138 encoding="UTF-8")
137
139
138 return render('/password_reset.html')
140 return render('/password_reset.html')
139
141
140 def logout(self):
142 def logout(self):
141 session['rhodecode_user'] = AuthUser()
143 session['rhodecode_user'] = AuthUser()
142 session.save()
144 session.save()
143 log.info('Logging out and setting user as Empty')
145 log.info('Logging out and setting user as Empty')
144 redirect(url('home'))
146 redirect(url('home'))
@@ -1,486 +1,475 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # authentication and permission libraries
3 # authentication and permission libraries
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 4, 2010
21 Created on April 4, 2010
22
22
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from pylons import config, session, url, request
25 from pylons import config, session, url, request
26 from pylons.controllers.util import abort, redirect
26 from pylons.controllers.util import abort, redirect
27 from rhodecode.lib.utils import get_repo_slug
27 from rhodecode.lib.utils import get_repo_slug
28 from rhodecode.model import meta
28 from rhodecode.model import meta
29 from rhodecode.model.user import UserModel
29 from rhodecode.model.caching_query import FromCache
30 from rhodecode.model.caching_query import FromCache
30 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
31 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
31 UserToPerm
32 UserToPerm
32 import bcrypt
33 import bcrypt
33 from decorator import decorator
34 from decorator import decorator
34 import logging
35 import logging
35 import random
36 import random
36
37
37 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
38
39
39 class PasswordGenerator(object):
40 class PasswordGenerator(object):
40 """This is a simple class for generating password from
41 """This is a simple class for generating password from
41 different sets of characters
42 different sets of characters
42 usage:
43 usage:
43 passwd_gen = PasswordGenerator()
44 passwd_gen = PasswordGenerator()
44 #print 8-letter password containing only big and small letters of alphabet
45 #print 8-letter password containing only big and small letters of alphabet
45 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
46 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
46 """
47 """
47 ALPHABETS_NUM = r'''1234567890'''#[0]
48 ALPHABETS_NUM = r'''1234567890'''#[0]
48 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
49 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
49 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
50 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
50 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
51 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
51 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
52 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
52 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
53 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
53 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
54 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
54 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
55 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
55 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
56 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
56
57
57 def __init__(self, passwd=''):
58 def __init__(self, passwd=''):
58 self.passwd = passwd
59 self.passwd = passwd
59
60
60 def gen_password(self, len, type):
61 def gen_password(self, len, type):
61 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
62 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
62 return self.passwd
63 return self.passwd
63
64
64
65
65 def get_crypt_password(password):
66 def get_crypt_password(password):
66 """Cryptographic function used for password hashing based on sha1
67 """Cryptographic function used for password hashing based on sha1
67 :param password: password to hash
68 :param password: password to hash
68 """
69 """
69 return bcrypt.hashpw(password, bcrypt.gensalt(10))
70 return bcrypt.hashpw(password, bcrypt.gensalt(10))
70
71
71 def check_password(password, hashed):
72 def check_password(password, hashed):
72 return bcrypt.hashpw(password, hashed) == hashed
73 return bcrypt.hashpw(password, hashed) == hashed
73
74
74 def authfunc(environ, username, password):
75 def authfunc(environ, username, password):
75 from rhodecode.model.user import UserModel
76 user = UserModel().get_by_username(username, cache=False)
76 user = UserModel().get_by_username(username, cache=False)
77
77
78 if user:
78 if user:
79 if user.active:
79 if user.active:
80 if user.username == username and check_password(password, user.password):
80 if user.username == username and check_password(password, user.password):
81 log.info('user %s authenticated correctly', username)
81 log.info('user %s authenticated correctly', username)
82 return True
82 return True
83 else:
83 else:
84 log.error('user %s is disabled', username)
84 log.error('user %s is disabled', username)
85
85
86 return False
86 return False
87
87
88 class AuthUser(object):
88 class AuthUser(object):
89 """
89 """
90 A simple object that handles a mercurial username for authentication
90 A simple object that handles a mercurial username for authentication
91 """
91 """
92 def __init__(self):
92 def __init__(self):
93 self.username = 'None'
93 self.username = 'None'
94 self.name = ''
94 self.name = ''
95 self.lastname = ''
95 self.lastname = ''
96 self.email = ''
96 self.email = ''
97 self.user_id = None
97 self.user_id = None
98 self.is_authenticated = False
98 self.is_authenticated = False
99 self.is_admin = False
99 self.is_admin = False
100 self.permissions = {}
100 self.permissions = {}
101
101
102 def __repr__(self):
103 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
102
104
103 def set_available_permissions(config):
105 def set_available_permissions(config):
104 """
106 """
105 This function will propagate pylons globals with all available defined
107 This function will propagate pylons globals with all available defined
106 permission given in db. We don't wannt to check each time from db for new
108 permission given in db. We don't wannt to check each time from db for new
107 permissions since adding a new permission also requires application restart
109 permissions since adding a new permission also requires application restart
108 ie. to decorate new views with the newly created permission
110 ie. to decorate new views with the newly created permission
109 :param config:
111 :param config:
110 """
112 """
111 log.info('getting information about all available permissions')
113 log.info('getting information about all available permissions')
112 try:
114 try:
113 sa = meta.Session()
115 sa = meta.Session()
114 all_perms = sa.query(Permission).all()
116 all_perms = sa.query(Permission).all()
115 except:
117 except:
116 pass
118 pass
117 finally:
119 finally:
118 meta.Session.remove()
120 meta.Session.remove()
119
121
120 config['available_permissions'] = [x.permission_name for x in all_perms]
122 config['available_permissions'] = [x.permission_name for x in all_perms]
121
123
122 def set_base_path(config):
124 def set_base_path(config):
123 config['base_path'] = config['pylons.app_globals'].base_path
125 config['base_path'] = config['pylons.app_globals'].base_path
124
126
125 def fill_data(user):
126 """
127 Fills user data with those from database and log out user if not present
128 in database
129 :param user:
130 """
131 sa = meta.Session()
132 try:
133 dbuser = sa.query(User)\
134 .options(FromCache('sql_cache_short', 'getuser_%s' % user.user_id))\
135 .get(user.user_id)
136 except:
137 pass
138 finally:
139 meta.Session.remove()
140
141 if dbuser:
142 user.username = dbuser.username
143 user.is_admin = dbuser.admin
144 user.name = dbuser.name
145 user.lastname = dbuser.lastname
146 user.email = dbuser.email
147 else:
148 user.is_authenticated = False
149
150
151 return user
152
127
153 def fill_perms(user):
128 def fill_perms(user):
154 """
129 """
155 Fills user permission attribute with permissions taken from database
130 Fills user permission attribute with permissions taken from database
156 :param user:
131 :param user:
157 """
132 """
158
133
159 sa = meta.Session()
134 sa = meta.Session()
160 user.permissions['repositories'] = {}
135 user.permissions['repositories'] = {}
161 user.permissions['global'] = set()
136 user.permissions['global'] = set()
162
137
163 #===========================================================================
138 #===========================================================================
164 # fetch default permissions
139 # fetch default permissions
165 #===========================================================================
140 #===========================================================================
166 default_user = sa.query(User)\
141 default_user = UserModel(sa).get_by_username('default', cache=True)
167 .options(FromCache('sql_cache_short', 'getuser_%s' % 'default'))\
168 .filter(User.username == 'default').scalar()
169
142
170 default_perms = sa.query(RepoToPerm, Repository, Permission)\
143 default_perms = sa.query(RepoToPerm, Repository, Permission)\
171 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
144 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
172 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
145 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
173 .filter(RepoToPerm.user == default_user).all()
146 .filter(RepoToPerm.user == default_user).all()
174
147
175 if user.is_admin:
148 if user.is_admin:
176 #=======================================================================
149 #=======================================================================
177 # #admin have all default rights set to admin
150 # #admin have all default rights set to admin
178 #=======================================================================
151 #=======================================================================
179 user.permissions['global'].add('hg.admin')
152 user.permissions['global'].add('hg.admin')
180
153
181 for perm in default_perms:
154 for perm in default_perms:
182 p = 'repository.admin'
155 p = 'repository.admin'
183 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
156 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
184
157
185 else:
158 else:
186 #=======================================================================
159 #=======================================================================
187 # set default permissions
160 # set default permissions
188 #=======================================================================
161 #=======================================================================
189
162
190 #default global
163 #default global
191 default_global_perms = sa.query(UserToPerm)\
164 default_global_perms = sa.query(UserToPerm)\
192 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
165 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
193 'default').one())
166 'default').one())
194
167
195 for perm in default_global_perms:
168 for perm in default_global_perms:
196 user.permissions['global'].add(perm.permission.permission_name)
169 user.permissions['global'].add(perm.permission.permission_name)
197
170
198 #default repositories
171 #default repositories
199 for perm in default_perms:
172 for perm in default_perms:
200 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
173 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
201 #disable defaults for private repos,
174 #disable defaults for private repos,
202 p = 'repository.none'
175 p = 'repository.none'
203 elif perm.Repository.user_id == user.user_id:
176 elif perm.Repository.user_id == user.user_id:
204 #set admin if owner
177 #set admin if owner
205 p = 'repository.admin'
178 p = 'repository.admin'
206 else:
179 else:
207 p = perm.Permission.permission_name
180 p = perm.Permission.permission_name
208
181
209 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
182 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
210
183
211 #=======================================================================
184 #=======================================================================
212 # #overwrite default with user permissions if any
185 # #overwrite default with user permissions if any
213 #=======================================================================
186 #=======================================================================
214 user_perms = sa.query(RepoToPerm, Permission, Repository)\
187 user_perms = sa.query(RepoToPerm, Permission, Repository)\
215 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
188 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
216 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
189 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
217 .filter(RepoToPerm.user_id == user.user_id).all()
190 .filter(RepoToPerm.user_id == user.user_id).all()
218
191
219 for perm in user_perms:
192 for perm in user_perms:
220 if perm.Repository.user_id == user.user_id:#set admin if owner
193 if perm.Repository.user_id == user.user_id:#set admin if owner
221 p = 'repository.admin'
194 p = 'repository.admin'
222 else:
195 else:
223 p = perm.Permission.permission_name
196 p = perm.Permission.permission_name
224 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
197 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
225 meta.Session.remove()
198 meta.Session.remove()
226 return user
199 return user
227
200
228 def get_user(session):
201 def get_user(session):
229 """
202 """
230 Gets user from session, and wraps permissions into user
203 Gets user from session, and wraps permissions into user
231 :param session:
204 :param session:
232 """
205 """
233 user = session.get('rhodecode_user', AuthUser())
206 user = session.get('rhodecode_user', AuthUser())
207
208
209 #if the user is not logged in we check for anonymous access
210 #if user is logged and it's a default user check if we still have anonymous
211 #access enabled
212 if user.user_id is None or user.username == 'default':
213 anonymous_user = UserModel().get_by_username('default', cache=True)
214 if anonymous_user.active is True:
215 #then we set this user is logged in
216 user.is_authenticated = True
217 else:
218 user.is_authenticated = False
219
234 if user.is_authenticated:
220 if user.is_authenticated:
235 user = fill_data(user)
221 user = UserModel().fill_data(user)
222
236 user = fill_perms(user)
223 user = fill_perms(user)
237 session['rhodecode_user'] = user
224 session['rhodecode_user'] = user
238 session.save()
225 session.save()
239 return user
226 return user
240
227
241 #===============================================================================
228 #===============================================================================
242 # CHECK DECORATORS
229 # CHECK DECORATORS
243 #===============================================================================
230 #===============================================================================
244 class LoginRequired(object):
231 class LoginRequired(object):
245 """Must be logged in to execute this function else redirect to login page"""
232 """Must be logged in to execute this function else redirect to login page"""
246
233
247 def __call__(self, func):
234 def __call__(self, func):
248 return decorator(self.__wrapper, func)
235 return decorator(self.__wrapper, func)
249
236
250 def __wrapper(self, func, *fargs, **fkwargs):
237 def __wrapper(self, func, *fargs, **fkwargs):
251 user = session.get('rhodecode_user', AuthUser())
238 user = session.get('rhodecode_user', AuthUser())
252 log.debug('Checking login required for user:%s', user.username)
239 log.debug('Checking login required for user:%s', user.username)
253 if user.is_authenticated:
240 if user.is_authenticated:
254 log.debug('user %s is authenticated', user.username)
241 log.debug('user %s is authenticated', user.username)
255 return func(*fargs, **fkwargs)
242 return func(*fargs, **fkwargs)
256 else:
243 else:
257 log.warn('user %s not authenticated', user.username)
244 log.warn('user %s not authenticated', user.username)
258
245
259 p = ''
246 p = ''
260 if request.environ.get('SCRIPT_NAME') != '/':
247 if request.environ.get('SCRIPT_NAME') != '/':
261 p += request.environ.get('SCRIPT_NAME')
248 p += request.environ.get('SCRIPT_NAME')
262
249
263 p += request.environ.get('PATH_INFO')
250 p += request.environ.get('PATH_INFO')
264 if request.environ.get('QUERY_STRING'):
251 if request.environ.get('QUERY_STRING'):
265 p += '?' + request.environ.get('QUERY_STRING')
252 p += '?' + request.environ.get('QUERY_STRING')
266
253
267 log.debug('redirecting to login page with %s', p)
254 log.debug('redirecting to login page with %s', p)
268 return redirect(url('login_home', came_from=p))
255 return redirect(url('login_home', came_from=p))
269
256
270 class PermsDecorator(object):
257 class PermsDecorator(object):
271 """Base class for decorators"""
258 """Base class for decorators"""
272
259
273 def __init__(self, *required_perms):
260 def __init__(self, *required_perms):
274 available_perms = config['available_permissions']
261 available_perms = config['available_permissions']
275 for perm in required_perms:
262 for perm in required_perms:
276 if perm not in available_perms:
263 if perm not in available_perms:
277 raise Exception("'%s' permission is not defined" % perm)
264 raise Exception("'%s' permission is not defined" % perm)
278 self.required_perms = set(required_perms)
265 self.required_perms = set(required_perms)
279 self.user_perms = None
266 self.user_perms = None
280
267
281 def __call__(self, func):
268 def __call__(self, func):
282 return decorator(self.__wrapper, func)
269 return decorator(self.__wrapper, func)
283
270
284
271
285 def __wrapper(self, func, *fargs, **fkwargs):
272 def __wrapper(self, func, *fargs, **fkwargs):
286 # _wrapper.__name__ = func.__name__
273 # _wrapper.__name__ = func.__name__
287 # _wrapper.__dict__.update(func.__dict__)
274 # _wrapper.__dict__.update(func.__dict__)
288 # _wrapper.__doc__ = func.__doc__
275 # _wrapper.__doc__ = func.__doc__
289
276 self.user = session.get('rhodecode_user', AuthUser())
290 self.user_perms = session.get('rhodecode_user', AuthUser()).permissions
277 self.user_perms = self.user.permissions
291 log.debug('checking %s permissions %s for %s',
278 log.debug('checking %s permissions %s for %s %s',
292 self.__class__.__name__, self.required_perms, func.__name__)
279 self.__class__.__name__, self.required_perms, func.__name__,
280 self.user)
293
281
294 if self.check_permissions():
282 if self.check_permissions():
295 log.debug('Permission granted for %s', func.__name__)
283 log.debug('Permission granted for %s %s', func.__name__, self.user)
296
284
297 return func(*fargs, **fkwargs)
285 return func(*fargs, **fkwargs)
298
286
299 else:
287 else:
300 log.warning('Permission denied for %s', func.__name__)
288 log.warning('Permission denied for %s %s', func.__name__, self.user)
301 #redirect with forbidden ret code
289 #redirect with forbidden ret code
302 return abort(403)
290 return abort(403)
303
291
304
292
305
293
306 def check_permissions(self):
294 def check_permissions(self):
307 """Dummy function for overriding"""
295 """Dummy function for overriding"""
308 raise Exception('You have to write this function in child class')
296 raise Exception('You have to write this function in child class')
309
297
310 class HasPermissionAllDecorator(PermsDecorator):
298 class HasPermissionAllDecorator(PermsDecorator):
311 """Checks for access permission for all given predicates. All of them
299 """Checks for access permission for all given predicates. All of them
312 have to be meet in order to fulfill the request
300 have to be meet in order to fulfill the request
313 """
301 """
314
302
315 def check_permissions(self):
303 def check_permissions(self):
316 if self.required_perms.issubset(self.user_perms.get('global')):
304 if self.required_perms.issubset(self.user_perms.get('global')):
317 return True
305 return True
318 return False
306 return False
319
307
320
308
321 class HasPermissionAnyDecorator(PermsDecorator):
309 class HasPermissionAnyDecorator(PermsDecorator):
322 """Checks for access permission for any of given predicates. In order to
310 """Checks for access permission for any of given predicates. In order to
323 fulfill the request any of predicates must be meet
311 fulfill the request any of predicates must be meet
324 """
312 """
325
313
326 def check_permissions(self):
314 def check_permissions(self):
327 if self.required_perms.intersection(self.user_perms.get('global')):
315 if self.required_perms.intersection(self.user_perms.get('global')):
328 return True
316 return True
329 return False
317 return False
330
318
331 class HasRepoPermissionAllDecorator(PermsDecorator):
319 class HasRepoPermissionAllDecorator(PermsDecorator):
332 """Checks for access permission for all given predicates for specific
320 """Checks for access permission for all given predicates for specific
333 repository. All of them have to be meet in order to fulfill the request
321 repository. All of them have to be meet in order to fulfill the request
334 """
322 """
335
323
336 def check_permissions(self):
324 def check_permissions(self):
337 repo_name = get_repo_slug(request)
325 repo_name = get_repo_slug(request)
338 try:
326 try:
339 user_perms = set([self.user_perms['repositories'][repo_name]])
327 user_perms = set([self.user_perms['repositories'][repo_name]])
340 except KeyError:
328 except KeyError:
341 return False
329 return False
342 if self.required_perms.issubset(user_perms):
330 if self.required_perms.issubset(user_perms):
343 return True
331 return True
344 return False
332 return False
345
333
346
334
347 class HasRepoPermissionAnyDecorator(PermsDecorator):
335 class HasRepoPermissionAnyDecorator(PermsDecorator):
348 """Checks for access permission for any of given predicates for specific
336 """Checks for access permission for any of given predicates for specific
349 repository. In order to fulfill the request any of predicates must be meet
337 repository. In order to fulfill the request any of predicates must be meet
350 """
338 """
351
339
352 def check_permissions(self):
340 def check_permissions(self):
353 repo_name = get_repo_slug(request)
341 repo_name = get_repo_slug(request)
354
342
355 try:
343 try:
356 user_perms = set([self.user_perms['repositories'][repo_name]])
344 user_perms = set([self.user_perms['repositories'][repo_name]])
357 except KeyError:
345 except KeyError:
358 return False
346 return False
359 if self.required_perms.intersection(user_perms):
347 if self.required_perms.intersection(user_perms):
360 return True
348 return True
361 return False
349 return False
362 #===============================================================================
350 #===============================================================================
363 # CHECK FUNCTIONS
351 # CHECK FUNCTIONS
364 #===============================================================================
352 #===============================================================================
365
353
366 class PermsFunction(object):
354 class PermsFunction(object):
367 """Base function for other check functions"""
355 """Base function for other check functions"""
368
356
369 def __init__(self, *perms):
357 def __init__(self, *perms):
370 available_perms = config['available_permissions']
358 available_perms = config['available_permissions']
371
359
372 for perm in perms:
360 for perm in perms:
373 if perm not in available_perms:
361 if perm not in available_perms:
374 raise Exception("'%s' permission in not defined" % perm)
362 raise Exception("'%s' permission in not defined" % perm)
375 self.required_perms = set(perms)
363 self.required_perms = set(perms)
376 self.user_perms = None
364 self.user_perms = None
377 self.granted_for = ''
365 self.granted_for = ''
378 self.repo_name = None
366 self.repo_name = None
379
367
380 def __call__(self, check_Location=''):
368 def __call__(self, check_Location=''):
381 user = session.get('rhodecode_user', False)
369 user = session.get('rhodecode_user', False)
382 if not user:
370 if not user:
383 return False
371 return False
384 self.user_perms = user.permissions
372 self.user_perms = user.permissions
385 self.granted_for = user.username
373 self.granted_for = user.username
386 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
374 log.debug('checking %s %s %s', self.__class__.__name__,
375 self.required_perms, user)
387
376
388 if self.check_permissions():
377 if self.check_permissions():
389 log.debug('Permission granted for %s @%s', self.granted_for,
378 log.debug('Permission granted for %s @ %s %s', self.granted_for,
390 check_Location)
379 check_Location, user)
391 return True
380 return True
392
381
393 else:
382 else:
394 log.warning('Permission denied for %s @%s', self.granted_for,
383 log.warning('Permission denied for %s @ %s %s', self.granted_for,
395 check_Location)
384 check_Location, user)
396 return False
385 return False
397
386
398 def check_permissions(self):
387 def check_permissions(self):
399 """Dummy function for overriding"""
388 """Dummy function for overriding"""
400 raise Exception('You have to write this function in child class')
389 raise Exception('You have to write this function in child class')
401
390
402 class HasPermissionAll(PermsFunction):
391 class HasPermissionAll(PermsFunction):
403 def check_permissions(self):
392 def check_permissions(self):
404 if self.required_perms.issubset(self.user_perms.get('global')):
393 if self.required_perms.issubset(self.user_perms.get('global')):
405 return True
394 return True
406 return False
395 return False
407
396
408 class HasPermissionAny(PermsFunction):
397 class HasPermissionAny(PermsFunction):
409 def check_permissions(self):
398 def check_permissions(self):
410 if self.required_perms.intersection(self.user_perms.get('global')):
399 if self.required_perms.intersection(self.user_perms.get('global')):
411 return True
400 return True
412 return False
401 return False
413
402
414 class HasRepoPermissionAll(PermsFunction):
403 class HasRepoPermissionAll(PermsFunction):
415
404
416 def __call__(self, repo_name=None, check_Location=''):
405 def __call__(self, repo_name=None, check_Location=''):
417 self.repo_name = repo_name
406 self.repo_name = repo_name
418 return super(HasRepoPermissionAll, self).__call__(check_Location)
407 return super(HasRepoPermissionAll, self).__call__(check_Location)
419
408
420 def check_permissions(self):
409 def check_permissions(self):
421 if not self.repo_name:
410 if not self.repo_name:
422 self.repo_name = get_repo_slug(request)
411 self.repo_name = get_repo_slug(request)
423
412
424 try:
413 try:
425 self.user_perms = set([self.user_perms['repositories']\
414 self.user_perms = set([self.user_perms['repositories']\
426 [self.repo_name]])
415 [self.repo_name]])
427 except KeyError:
416 except KeyError:
428 return False
417 return False
429 self.granted_for = self.repo_name
418 self.granted_for = self.repo_name
430 if self.required_perms.issubset(self.user_perms):
419 if self.required_perms.issubset(self.user_perms):
431 return True
420 return True
432 return False
421 return False
433
422
434 class HasRepoPermissionAny(PermsFunction):
423 class HasRepoPermissionAny(PermsFunction):
435
424
436 def __call__(self, repo_name=None, check_Location=''):
425 def __call__(self, repo_name=None, check_Location=''):
437 self.repo_name = repo_name
426 self.repo_name = repo_name
438 return super(HasRepoPermissionAny, self).__call__(check_Location)
427 return super(HasRepoPermissionAny, self).__call__(check_Location)
439
428
440 def check_permissions(self):
429 def check_permissions(self):
441 if not self.repo_name:
430 if not self.repo_name:
442 self.repo_name = get_repo_slug(request)
431 self.repo_name = get_repo_slug(request)
443
432
444 try:
433 try:
445 self.user_perms = set([self.user_perms['repositories']\
434 self.user_perms = set([self.user_perms['repositories']\
446 [self.repo_name]])
435 [self.repo_name]])
447 except KeyError:
436 except KeyError:
448 return False
437 return False
449 self.granted_for = self.repo_name
438 self.granted_for = self.repo_name
450 if self.required_perms.intersection(self.user_perms):
439 if self.required_perms.intersection(self.user_perms):
451 return True
440 return True
452 return False
441 return False
453
442
454 #===============================================================================
443 #===============================================================================
455 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
444 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
456 #===============================================================================
445 #===============================================================================
457
446
458 class HasPermissionAnyMiddleware(object):
447 class HasPermissionAnyMiddleware(object):
459 def __init__(self, *perms):
448 def __init__(self, *perms):
460 self.required_perms = set(perms)
449 self.required_perms = set(perms)
461
450
462 def __call__(self, user, repo_name):
451 def __call__(self, user, repo_name):
463 usr = AuthUser()
452 usr = AuthUser()
464 usr.user_id = user.user_id
453 usr.user_id = user.user_id
465 usr.username = user.username
454 usr.username = user.username
466 usr.is_admin = user.admin
455 usr.is_admin = user.admin
467
456
468 try:
457 try:
469 self.user_perms = set([fill_perms(usr)\
458 self.user_perms = set([fill_perms(usr)\
470 .permissions['repositories'][repo_name]])
459 .permissions['repositories'][repo_name]])
471 except:
460 except:
472 self.user_perms = set()
461 self.user_perms = set()
473 self.granted_for = ''
462 self.granted_for = ''
474 self.username = user.username
463 self.username = user.username
475 self.repo_name = repo_name
464 self.repo_name = repo_name
476 return self.check_permissions()
465 return self.check_permissions()
477
466
478 def check_permissions(self):
467 def check_permissions(self):
479 log.debug('checking mercurial protocol '
468 log.debug('checking mercurial protocol '
480 'permissions for user:%s repository:%s',
469 'permissions for user:%s repository:%s',
481 self.username, self.repo_name)
470 self.username, self.repo_name)
482 if self.required_perms.intersection(self.user_perms):
471 if self.required_perms.intersection(self.user_perms):
483 log.debug('permission granted')
472 log.debug('permission granted')
484 return True
473 return True
485 log.debug('permission denied')
474 log.debug('permission denied')
486 return False
475 return False
@@ -1,300 +1,300 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # database management for RhodeCode
3 # database management for RhodeCode
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20
20
21 """
21 """
22 Created on April 10, 2010
22 Created on April 10, 2010
23 database management and creation for RhodeCode
23 database management and creation for RhodeCode
24 @author: marcink
24 @author: marcink
25 """
25 """
26
26
27 from os.path import dirname as dn, join as jn
27 from os.path import dirname as dn, join as jn
28 import os
28 import os
29 import sys
29 import sys
30 import uuid
30 import uuid
31
31
32 from rhodecode.lib.auth import get_crypt_password
32 from rhodecode.lib.auth import get_crypt_password
33 from rhodecode.lib.utils import ask_ok
33 from rhodecode.lib.utils import ask_ok
34 from rhodecode.model import init_model
34 from rhodecode.model import init_model
35 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
35 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
36 UserToPerm
36 UserToPerm
37 from rhodecode.model import meta
37 from rhodecode.model import meta
38 from sqlalchemy.engine import create_engine
38 from sqlalchemy.engine import create_engine
39 import logging
39 import logging
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43 class DbManage(object):
43 class DbManage(object):
44 def __init__(self, log_sql, dbname, root, tests=False):
44 def __init__(self, log_sql, dbname, root, tests=False):
45 self.dbname = dbname
45 self.dbname = dbname
46 self.tests = tests
46 self.tests = tests
47 self.root = root
47 self.root = root
48 dburi = 'sqlite:////%s' % jn(self.root, self.dbname)
48 dburi = 'sqlite:////%s' % jn(self.root, self.dbname)
49 engine = create_engine(dburi, echo=log_sql)
49 engine = create_engine(dburi, echo=log_sql)
50 init_model(engine)
50 init_model(engine)
51 self.sa = meta.Session()
51 self.sa = meta.Session()
52 self.db_exists = False
52 self.db_exists = False
53
53
54 def check_for_db(self, override):
54 def check_for_db(self, override):
55 db_path = jn(self.root, self.dbname)
55 db_path = jn(self.root, self.dbname)
56 log.info('checking for existing db in %s', db_path)
56 log.info('checking for existing db in %s', db_path)
57 if os.path.isfile(db_path):
57 if os.path.isfile(db_path):
58 self.db_exists = True
58 self.db_exists = True
59 if not override:
59 if not override:
60 raise Exception('database already exists')
60 raise Exception('database already exists')
61
61
62 def create_tables(self, override=False):
62 def create_tables(self, override=False):
63 """
63 """
64 Create a auth database
64 Create a auth database
65 """
65 """
66 self.check_for_db(override)
66 self.check_for_db(override)
67 if self.db_exists:
67 if self.db_exists:
68 log.info("database exist and it's going to be destroyed")
68 log.info("database exist and it's going to be destroyed")
69 if self.tests:
69 if self.tests:
70 destroy = True
70 destroy = True
71 else:
71 else:
72 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
72 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
73 if not destroy:
73 if not destroy:
74 sys.exit()
74 sys.exit()
75 if self.db_exists and destroy:
75 if self.db_exists and destroy:
76 os.remove(jn(self.root, self.dbname))
76 os.remove(jn(self.root, self.dbname))
77 checkfirst = not override
77 checkfirst = not override
78 meta.Base.metadata.create_all(checkfirst=checkfirst)
78 meta.Base.metadata.create_all(checkfirst=checkfirst)
79 log.info('Created tables for %s', self.dbname)
79 log.info('Created tables for %s', self.dbname)
80
80
81 def admin_prompt(self, second=False):
81 def admin_prompt(self, second=False):
82 if not self.tests:
82 if not self.tests:
83 import getpass
83 import getpass
84
84
85
85
86 def get_password():
86 def get_password():
87 password = getpass.getpass('Specify admin password (min 6 chars):')
87 password = getpass.getpass('Specify admin password (min 6 chars):')
88 confirm = getpass.getpass('Confirm password:')
88 confirm = getpass.getpass('Confirm password:')
89
89
90 if password != confirm:
90 if password != confirm:
91 log.error('passwords mismatch')
91 log.error('passwords mismatch')
92 return False
92 return False
93 if len(password) < 6:
93 if len(password) < 6:
94 log.error('password is to short use at least 6 characters')
94 log.error('password is to short use at least 6 characters')
95 return False
95 return False
96
96
97 return password
97 return password
98
98
99 username = raw_input('Specify admin username:')
99 username = raw_input('Specify admin username:')
100
100
101 password = get_password()
101 password = get_password()
102 if not password:
102 if not password:
103 #second try
103 #second try
104 password = get_password()
104 password = get_password()
105 if not password:
105 if not password:
106 sys.exit()
106 sys.exit()
107
107
108 email = raw_input('Specify admin email:')
108 email = raw_input('Specify admin email:')
109 self.create_user(username, password, email, True)
109 self.create_user(username, password, email, True)
110 else:
110 else:
111 log.info('creating admin and regular test users')
111 log.info('creating admin and regular test users')
112 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
112 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
113 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
113 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
114 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
114 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
115
115
116
116
117
117
118 def config_prompt(self, test_repo_path=''):
118 def config_prompt(self, test_repo_path=''):
119 log.info('Setting up repositories config')
119 log.info('Setting up repositories config')
120
120
121 if not self.tests and not test_repo_path:
121 if not self.tests and not test_repo_path:
122 path = raw_input('Specify valid full path to your repositories'
122 path = raw_input('Specify valid full path to your repositories'
123 ' you can change this later in application settings:')
123 ' you can change this later in application settings:')
124 else:
124 else:
125 path = test_repo_path
125 path = test_repo_path
126
126
127 if not os.path.isdir(path):
127 if not os.path.isdir(path):
128 log.error('You entered wrong path: %s', path)
128 log.error('You entered wrong path: %s', path)
129 sys.exit()
129 sys.exit()
130
130
131 hooks1 = RhodeCodeUi()
131 hooks1 = RhodeCodeUi()
132 hooks1.ui_section = 'hooks'
132 hooks1.ui_section = 'hooks'
133 hooks1.ui_key = 'changegroup.update'
133 hooks1.ui_key = 'changegroup.update'
134 hooks1.ui_value = 'hg update >&2'
134 hooks1.ui_value = 'hg update >&2'
135 hooks1.ui_active = False
135 hooks1.ui_active = False
136
136
137 hooks2 = RhodeCodeUi()
137 hooks2 = RhodeCodeUi()
138 hooks2.ui_section = 'hooks'
138 hooks2.ui_section = 'hooks'
139 hooks2.ui_key = 'changegroup.repo_size'
139 hooks2.ui_key = 'changegroup.repo_size'
140 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
140 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
141
141
142 hooks3 = RhodeCodeUi()
142 hooks3 = RhodeCodeUi()
143 hooks3.ui_section = 'hooks'
143 hooks3.ui_section = 'hooks'
144 hooks3.ui_key = 'pretxnchangegroup.push_logger'
144 hooks3.ui_key = 'pretxnchangegroup.push_logger'
145 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
145 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
146
146
147 hooks4 = RhodeCodeUi()
147 hooks4 = RhodeCodeUi()
148 hooks4.ui_section = 'hooks'
148 hooks4.ui_section = 'hooks'
149 hooks4.ui_key = 'preoutgoing.pull_logger'
149 hooks4.ui_key = 'preoutgoing.pull_logger'
150 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
150 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
151
151
152
152
153 web1 = RhodeCodeUi()
153 web1 = RhodeCodeUi()
154 web1.ui_section = 'web'
154 web1.ui_section = 'web'
155 web1.ui_key = 'push_ssl'
155 web1.ui_key = 'push_ssl'
156 web1.ui_value = 'false'
156 web1.ui_value = 'false'
157
157
158 web2 = RhodeCodeUi()
158 web2 = RhodeCodeUi()
159 web2.ui_section = 'web'
159 web2.ui_section = 'web'
160 web2.ui_key = 'allow_archive'
160 web2.ui_key = 'allow_archive'
161 web2.ui_value = 'gz zip bz2'
161 web2.ui_value = 'gz zip bz2'
162
162
163 web3 = RhodeCodeUi()
163 web3 = RhodeCodeUi()
164 web3.ui_section = 'web'
164 web3.ui_section = 'web'
165 web3.ui_key = 'allow_push'
165 web3.ui_key = 'allow_push'
166 web3.ui_value = '*'
166 web3.ui_value = '*'
167
167
168 web4 = RhodeCodeUi()
168 web4 = RhodeCodeUi()
169 web4.ui_section = 'web'
169 web4.ui_section = 'web'
170 web4.ui_key = 'baseurl'
170 web4.ui_key = 'baseurl'
171 web4.ui_value = '/'
171 web4.ui_value = '/'
172
172
173 paths = RhodeCodeUi()
173 paths = RhodeCodeUi()
174 paths.ui_section = 'paths'
174 paths.ui_section = 'paths'
175 paths.ui_key = '/'
175 paths.ui_key = '/'
176 paths.ui_value = path
176 paths.ui_value = path
177
177
178
178
179 hgsettings1 = RhodeCodeSettings()
179 hgsettings1 = RhodeCodeSettings()
180
180
181 hgsettings1.app_settings_name = 'realm'
181 hgsettings1.app_settings_name = 'realm'
182 hgsettings1.app_settings_value = 'RhodeCode authentication'
182 hgsettings1.app_settings_value = 'RhodeCode authentication'
183
183
184 hgsettings2 = RhodeCodeSettings()
184 hgsettings2 = RhodeCodeSettings()
185 hgsettings2.app_settings_name = 'title'
185 hgsettings2.app_settings_name = 'title'
186 hgsettings2.app_settings_value = 'RhodeCode'
186 hgsettings2.app_settings_value = 'RhodeCode'
187
187
188 try:
188 try:
189 self.sa.add(hooks1)
189 self.sa.add(hooks1)
190 self.sa.add(hooks2)
190 self.sa.add(hooks2)
191 self.sa.add(hooks3)
191 self.sa.add(hooks3)
192 self.sa.add(hooks4)
192 self.sa.add(hooks4)
193 self.sa.add(web1)
193 self.sa.add(web1)
194 self.sa.add(web2)
194 self.sa.add(web2)
195 self.sa.add(web3)
195 self.sa.add(web3)
196 self.sa.add(web4)
196 self.sa.add(web4)
197 self.sa.add(paths)
197 self.sa.add(paths)
198 self.sa.add(hgsettings1)
198 self.sa.add(hgsettings1)
199 self.sa.add(hgsettings2)
199 self.sa.add(hgsettings2)
200 self.sa.commit()
200 self.sa.commit()
201 except:
201 except:
202 self.sa.rollback()
202 self.sa.rollback()
203 raise
203 raise
204 log.info('created ui config')
204 log.info('created ui config')
205
205
206 def create_user(self, username, password, email='', admin=False):
206 def create_user(self, username, password, email='', admin=False):
207 log.info('creating administrator user %s', username)
207 log.info('creating administrator user %s', username)
208 new_user = User()
208 new_user = User()
209 new_user.username = username
209 new_user.username = username
210 new_user.password = get_crypt_password(password)
210 new_user.password = get_crypt_password(password)
211 new_user.name = 'RhodeCode'
211 new_user.name = 'RhodeCode'
212 new_user.lastname = 'Admin'
212 new_user.lastname = 'Admin'
213 new_user.email = email
213 new_user.email = email
214 new_user.admin = admin
214 new_user.admin = admin
215 new_user.active = True
215 new_user.active = True
216
216
217 try:
217 try:
218 self.sa.add(new_user)
218 self.sa.add(new_user)
219 self.sa.commit()
219 self.sa.commit()
220 except:
220 except:
221 self.sa.rollback()
221 self.sa.rollback()
222 raise
222 raise
223
223
224 def create_default_user(self):
224 def create_default_user(self):
225 log.info('creating default user')
225 log.info('creating default user')
226 #create default user for handling default permissions.
226 #create default user for handling default permissions.
227 def_user = User()
227 def_user = User()
228 def_user.username = 'default'
228 def_user.username = 'default'
229 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
229 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
230 def_user.name = 'default'
230 def_user.name = 'Anonymous'
231 def_user.lastname = 'default'
231 def_user.lastname = 'User'
232 def_user.email = 'default@default.com'
232 def_user.email = 'anonymous@rhodecode.org'
233 def_user.admin = False
233 def_user.admin = False
234 def_user.active = False
234 def_user.active = False
235 try:
235 try:
236 self.sa.add(def_user)
236 self.sa.add(def_user)
237 self.sa.commit()
237 self.sa.commit()
238 except:
238 except:
239 self.sa.rollback()
239 self.sa.rollback()
240 raise
240 raise
241
241
242 def create_permissions(self):
242 def create_permissions(self):
243 #module.(access|create|change|delete)_[name]
243 #module.(access|create|change|delete)_[name]
244 #module.(read|write|owner)
244 #module.(read|write|owner)
245 perms = [('repository.none', 'Repository no access'),
245 perms = [('repository.none', 'Repository no access'),
246 ('repository.read', 'Repository read access'),
246 ('repository.read', 'Repository read access'),
247 ('repository.write', 'Repository write access'),
247 ('repository.write', 'Repository write access'),
248 ('repository.admin', 'Repository admin access'),
248 ('repository.admin', 'Repository admin access'),
249 ('hg.admin', 'Hg Administrator'),
249 ('hg.admin', 'Hg Administrator'),
250 ('hg.create.repository', 'Repository create'),
250 ('hg.create.repository', 'Repository create'),
251 ('hg.create.none', 'Repository creation disabled'),
251 ('hg.create.none', 'Repository creation disabled'),
252 ('hg.register.none', 'Register disabled'),
252 ('hg.register.none', 'Register disabled'),
253 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
253 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
254 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
254 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
255 ]
255 ]
256
256
257 for p in perms:
257 for p in perms:
258 new_perm = Permission()
258 new_perm = Permission()
259 new_perm.permission_name = p[0]
259 new_perm.permission_name = p[0]
260 new_perm.permission_longname = p[1]
260 new_perm.permission_longname = p[1]
261 try:
261 try:
262 self.sa.add(new_perm)
262 self.sa.add(new_perm)
263 self.sa.commit()
263 self.sa.commit()
264 except:
264 except:
265 self.sa.rollback()
265 self.sa.rollback()
266 raise
266 raise
267
267
268 def populate_default_permissions(self):
268 def populate_default_permissions(self):
269 log.info('creating default user permissions')
269 log.info('creating default user permissions')
270
270
271 default_user = self.sa.query(User)\
271 default_user = self.sa.query(User)\
272 .filter(User.username == 'default').scalar()
272 .filter(User.username == 'default').scalar()
273
273
274 reg_perm = UserToPerm()
274 reg_perm = UserToPerm()
275 reg_perm.user = default_user
275 reg_perm.user = default_user
276 reg_perm.permission = self.sa.query(Permission)\
276 reg_perm.permission = self.sa.query(Permission)\
277 .filter(Permission.permission_name == 'hg.register.manual_activate')\
277 .filter(Permission.permission_name == 'hg.register.manual_activate')\
278 .scalar()
278 .scalar()
279
279
280 create_repo_perm = UserToPerm()
280 create_repo_perm = UserToPerm()
281 create_repo_perm.user = default_user
281 create_repo_perm.user = default_user
282 create_repo_perm.permission = self.sa.query(Permission)\
282 create_repo_perm.permission = self.sa.query(Permission)\
283 .filter(Permission.permission_name == 'hg.create.repository')\
283 .filter(Permission.permission_name == 'hg.create.repository')\
284 .scalar()
284 .scalar()
285
285
286 default_repo_perm = UserToPerm()
286 default_repo_perm = UserToPerm()
287 default_repo_perm.user = default_user
287 default_repo_perm.user = default_user
288 default_repo_perm.permission = self.sa.query(Permission)\
288 default_repo_perm.permission = self.sa.query(Permission)\
289 .filter(Permission.permission_name == 'repository.read')\
289 .filter(Permission.permission_name == 'repository.read')\
290 .scalar()
290 .scalar()
291
291
292 try:
292 try:
293 self.sa.add(reg_perm)
293 self.sa.add(reg_perm)
294 self.sa.add(create_repo_perm)
294 self.sa.add(create_repo_perm)
295 self.sa.add(default_repo_perm)
295 self.sa.add(default_repo_perm)
296 self.sa.commit()
296 self.sa.commit()
297 except:
297 except:
298 self.sa.rollback()
298 self.sa.rollback()
299 raise
299 raise
300
300
@@ -1,365 +1,366 b''
1 """ this is forms validation classes
1 """ this is forms validation classes
2 http://formencode.org/module-formencode.validators.html
2 http://formencode.org/module-formencode.validators.html
3 for list off all availible validators
3 for list off all availible validators
4
4
5 we can create our own validators
5 we can create our own validators
6
6
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 pre_validators [] These validators will be applied before the schema
8 pre_validators [] These validators will be applied before the schema
9 chained_validators [] These validators will be applied after the schema
9 chained_validators [] These validators will be applied after the schema
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14
14
15
15
16 <name> = formencode.validators.<name of validator>
16 <name> = formencode.validators.<name of validator>
17 <name> must equal form name
17 <name> must equal form name
18 list=[1,2,3,4,5]
18 list=[1,2,3,4,5]
19 for SELECT use formencode.All(OneOf(list), Int())
19 for SELECT use formencode.All(OneOf(list), Int())
20
20
21 """
21 """
22 from formencode import All
22 from formencode import All
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 Email, Bool, StringBoolean
24 Email, Bool, StringBoolean
25 from pylons import session
25 from pylons import session
26 from pylons.i18n.translation import _
26 from pylons.i18n.translation import _
27 from rhodecode.lib.auth import check_password, get_crypt_password
27 from rhodecode.lib.auth import check_password, get_crypt_password
28 from rhodecode.model import meta
28 from rhodecode.model import meta
29 from rhodecode.model.user import UserModel
29 from rhodecode.model.user import UserModel
30 from rhodecode.model.repo import RepoModel
30 from rhodecode.model.repo import RepoModel
31 from rhodecode.model.db import User
31 from rhodecode.model.db import User
32 from webhelpers.pylonslib.secure_form import authentication_token
32 from webhelpers.pylonslib.secure_form import authentication_token
33 from vcs import BACKENDS
33 from vcs import BACKENDS
34 import formencode
34 import formencode
35 import logging
35 import logging
36 import os
36 import os
37 import rhodecode.lib.helpers as h
37 import rhodecode.lib.helpers as h
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41 #this is needed to translate the messages using _() in validators
41 #this is needed to translate the messages using _() in validators
42 class State_obj(object):
42 class State_obj(object):
43 _ = staticmethod(_)
43 _ = staticmethod(_)
44
44
45 #===============================================================================
45 #===============================================================================
46 # VALIDATORS
46 # VALIDATORS
47 #===============================================================================
47 #===============================================================================
48 class ValidAuthToken(formencode.validators.FancyValidator):
48 class ValidAuthToken(formencode.validators.FancyValidator):
49 messages = {'invalid_token':_('Token mismatch')}
49 messages = {'invalid_token':_('Token mismatch')}
50
50
51 def validate_python(self, value, state):
51 def validate_python(self, value, state):
52
52
53 if value != authentication_token():
53 if value != authentication_token():
54 raise formencode.Invalid(self.message('invalid_token', state,
54 raise formencode.Invalid(self.message('invalid_token', state,
55 search_number=value), value, state)
55 search_number=value), value, state)
56
56
57 def ValidUsername(edit, old_data):
57 def ValidUsername(edit, old_data):
58 class _ValidUsername(formencode.validators.FancyValidator):
58 class _ValidUsername(formencode.validators.FancyValidator):
59
59
60 def validate_python(self, value, state):
60 def validate_python(self, value, state):
61 if value in ['default', 'new_user']:
61 if value in ['default', 'new_user']:
62 raise formencode.Invalid(_('Invalid username'), value, state)
62 raise formencode.Invalid(_('Invalid username'), value, state)
63 #check if user is unique
63 #check if user is unique
64 old_un = None
64 old_un = None
65 if edit:
65 if edit:
66 old_un = UserModel().get(old_data.get('user_id')).username
66 old_un = UserModel().get(old_data.get('user_id')).username
67
67
68 if old_un != value or not edit:
68 if old_un != value or not edit:
69 if UserModel().get_by_username(value, cache=False):
69 if UserModel().get_by_username(value, cache=False):
70 raise formencode.Invalid(_('This username already exists') ,
70 raise formencode.Invalid(_('This username already exists') ,
71 value, state)
71 value, state)
72
72
73 return _ValidUsername
73 return _ValidUsername
74
74
75 class ValidPassword(formencode.validators.FancyValidator):
75 class ValidPassword(formencode.validators.FancyValidator):
76
76
77 def to_python(self, value, state):
77 def to_python(self, value, state):
78 if value:
78 if value:
79 return get_crypt_password(value)
79 return get_crypt_password(value)
80
80
81 class ValidAuth(formencode.validators.FancyValidator):
81 class ValidAuth(formencode.validators.FancyValidator):
82 messages = {
82 messages = {
83 'invalid_password':_('invalid password'),
83 'invalid_password':_('invalid password'),
84 'invalid_login':_('invalid user name'),
84 'invalid_login':_('invalid user name'),
85 'disabled_account':_('Your acccount is disabled')
85 'disabled_account':_('Your acccount is disabled')
86
86
87 }
87 }
88 #error mapping
88 #error mapping
89 e_dict = {'username':messages['invalid_login'],
89 e_dict = {'username':messages['invalid_login'],
90 'password':messages['invalid_password']}
90 'password':messages['invalid_password']}
91 e_dict_disable = {'username':messages['disabled_account']}
91 e_dict_disable = {'username':messages['disabled_account']}
92
92
93 def validate_python(self, value, state):
93 def validate_python(self, value, state):
94 password = value['password']
94 password = value['password']
95 username = value['username']
95 username = value['username']
96 user = UserModel().get_by_username(username)
96 user = UserModel().get_by_username(username)
97 if user is None:
97 if user is None:
98 raise formencode.Invalid(self.message('invalid_password',
98 raise formencode.Invalid(self.message('invalid_password',
99 state=State_obj), value, state,
99 state=State_obj), value, state,
100 error_dict=self.e_dict)
100 error_dict=self.e_dict)
101 if user:
101 if user:
102 if user.active:
102 if user.active:
103 if user.username == username and check_password(password,
103 if user.username == username and check_password(password,
104 user.password):
104 user.password):
105 return value
105 return value
106 else:
106 else:
107 log.warning('user %s not authenticated', username)
107 log.warning('user %s not authenticated', username)
108 raise formencode.Invalid(self.message('invalid_password',
108 raise formencode.Invalid(self.message('invalid_password',
109 state=State_obj), value, state,
109 state=State_obj), value, state,
110 error_dict=self.e_dict)
110 error_dict=self.e_dict)
111 else:
111 else:
112 log.warning('user %s is disabled', username)
112 log.warning('user %s is disabled', username)
113 raise formencode.Invalid(self.message('disabled_account',
113 raise formencode.Invalid(self.message('disabled_account',
114 state=State_obj),
114 state=State_obj),
115 value, state,
115 value, state,
116 error_dict=self.e_dict_disable)
116 error_dict=self.e_dict_disable)
117
117
118 class ValidRepoUser(formencode.validators.FancyValidator):
118 class ValidRepoUser(formencode.validators.FancyValidator):
119
119
120 def to_python(self, value, state):
120 def to_python(self, value, state):
121 sa = meta.Session()
121 sa = meta.Session()
122 try:
122 try:
123 self.user_db = sa.query(User)\
123 self.user_db = sa.query(User)\
124 .filter(User.active == True)\
124 .filter(User.active == True)\
125 .filter(User.username == value).one()
125 .filter(User.username == value).one()
126 except Exception:
126 except Exception:
127 raise formencode.Invalid(_('This username is not valid'),
127 raise formencode.Invalid(_('This username is not valid'),
128 value, state)
128 value, state)
129 finally:
129 finally:
130 meta.Session.remove()
130 meta.Session.remove()
131
131
132 return self.user_db.user_id
132 return self.user_db.user_id
133
133
134 def ValidRepoName(edit, old_data):
134 def ValidRepoName(edit, old_data):
135 class _ValidRepoName(formencode.validators.FancyValidator):
135 class _ValidRepoName(formencode.validators.FancyValidator):
136
136
137 def to_python(self, value, state):
137 def to_python(self, value, state):
138 slug = h.repo_name_slug(value)
138 slug = h.repo_name_slug(value)
139 if slug in ['_admin']:
139 if slug in ['_admin']:
140 raise formencode.Invalid(_('This repository name is disallowed'),
140 raise formencode.Invalid(_('This repository name is disallowed'),
141 value, state)
141 value, state)
142 if old_data.get('repo_name') != value or not edit:
142 if old_data.get('repo_name') != value or not edit:
143 if RepoModel().get(slug, cache=False):
143 if RepoModel().get(slug, cache=False):
144 raise formencode.Invalid(_('This repository already exists') ,
144 raise formencode.Invalid(_('This repository already exists') ,
145 value, state)
145 value, state)
146 return slug
146 return slug
147
147
148
148
149 return _ValidRepoName
149 return _ValidRepoName
150
150
151 def ValidForkType(old_data):
151 def ValidForkType(old_data):
152 class _ValidForkType(formencode.validators.FancyValidator):
152 class _ValidForkType(formencode.validators.FancyValidator):
153
153
154 def to_python(self, value, state):
154 def to_python(self, value, state):
155 if old_data['repo_type'] != value:
155 if old_data['repo_type'] != value:
156 raise formencode.Invalid(_('Fork have to be the same type as original'), value, state)
156 raise formencode.Invalid(_('Fork have to be the same type as original'), value, state)
157 return value
157 return value
158 return _ValidForkType
158 return _ValidForkType
159
159
160 class ValidPerms(formencode.validators.FancyValidator):
160 class ValidPerms(formencode.validators.FancyValidator):
161 messages = {'perm_new_user_name':_('This username is not valid')}
161 messages = {'perm_new_user_name':_('This username is not valid')}
162
162
163 def to_python(self, value, state):
163 def to_python(self, value, state):
164 perms_update = []
164 perms_update = []
165 perms_new = []
165 perms_new = []
166 #build a list of permission to update and new permission to create
166 #build a list of permission to update and new permission to create
167 for k, v in value.items():
167 for k, v in value.items():
168 if k.startswith('perm_'):
168 if k.startswith('perm_'):
169 if k.startswith('perm_new_user'):
169 if k.startswith('perm_new_user'):
170 new_perm = value.get('perm_new_user', False)
170 new_perm = value.get('perm_new_user', False)
171 new_user = value.get('perm_new_user_name', False)
171 new_user = value.get('perm_new_user_name', False)
172 if new_user and new_perm:
172 if new_user and new_perm:
173 if (new_user, new_perm) not in perms_new:
173 if (new_user, new_perm) not in perms_new:
174 perms_new.append((new_user, new_perm))
174 perms_new.append((new_user, new_perm))
175 else:
175 else:
176 usr = k[5:]
176 usr = k[5:]
177 if usr == 'default':
177 if usr == 'default':
178 if value['private']:
178 if value['private']:
179 #set none for default when updating to private repo
179 #set none for default when updating to private repo
180 v = 'repository.none'
180 v = 'repository.none'
181 perms_update.append((usr, v))
181 perms_update.append((usr, v))
182 value['perms_updates'] = perms_update
182 value['perms_updates'] = perms_update
183 value['perms_new'] = perms_new
183 value['perms_new'] = perms_new
184 sa = meta.Session
184 sa = meta.Session
185 for k, v in perms_new:
185 for k, v in perms_new:
186 try:
186 try:
187 self.user_db = sa.query(User)\
187 self.user_db = sa.query(User)\
188 .filter(User.active == True)\
188 .filter(User.active == True)\
189 .filter(User.username == k).one()
189 .filter(User.username == k).one()
190 except Exception:
190 except Exception:
191 msg = self.message('perm_new_user_name',
191 msg = self.message('perm_new_user_name',
192 state=State_obj)
192 state=State_obj)
193 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
193 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
194 return value
194 return value
195
195
196 class ValidSettings(formencode.validators.FancyValidator):
196 class ValidSettings(formencode.validators.FancyValidator):
197
197
198 def to_python(self, value, state):
198 def to_python(self, value, state):
199 #settings form can't edit user
199 #settings form can't edit user
200 if value.has_key('user'):
200 if value.has_key('user'):
201 del['value']['user']
201 del['value']['user']
202
202
203 return value
203 return value
204
204
205 class ValidPath(formencode.validators.FancyValidator):
205 class ValidPath(formencode.validators.FancyValidator):
206 def to_python(self, value, state):
206 def to_python(self, value, state):
207
207
208 if not os.path.isdir(value):
208 if not os.path.isdir(value):
209 msg = _('This is not a valid path')
209 msg = _('This is not a valid path')
210 raise formencode.Invalid(msg, value, state,
210 raise formencode.Invalid(msg, value, state,
211 error_dict={'paths_root_path':msg})
211 error_dict={'paths_root_path':msg})
212 return value
212 return value
213
213
214 def UniqSystemEmail(old_data):
214 def UniqSystemEmail(old_data):
215 class _UniqSystemEmail(formencode.validators.FancyValidator):
215 class _UniqSystemEmail(formencode.validators.FancyValidator):
216 def to_python(self, value, state):
216 def to_python(self, value, state):
217 if old_data.get('email') != value:
217 if old_data.get('email') != value:
218 sa = meta.Session()
218 sa = meta.Session()
219 try:
219 try:
220 user = sa.query(User).filter(User.email == value).scalar()
220 user = sa.query(User).filter(User.email == value).scalar()
221 if user:
221 if user:
222 raise formencode.Invalid(_("That e-mail address is already taken") ,
222 raise formencode.Invalid(_("That e-mail address is already taken") ,
223 value, state)
223 value, state)
224 finally:
224 finally:
225 meta.Session.remove()
225 meta.Session.remove()
226
226
227 return value
227 return value
228
228
229 return _UniqSystemEmail
229 return _UniqSystemEmail
230
230
231 class ValidSystemEmail(formencode.validators.FancyValidator):
231 class ValidSystemEmail(formencode.validators.FancyValidator):
232 def to_python(self, value, state):
232 def to_python(self, value, state):
233 sa = meta.Session
233 sa = meta.Session
234 try:
234 try:
235 user = sa.query(User).filter(User.email == value).scalar()
235 user = sa.query(User).filter(User.email == value).scalar()
236 if user is None:
236 if user is None:
237 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
237 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
238 value, state)
238 value, state)
239 finally:
239 finally:
240 meta.Session.remove()
240 meta.Session.remove()
241
241
242 return value
242 return value
243
243
244 #===============================================================================
244 #===============================================================================
245 # FORMS
245 # FORMS
246 #===============================================================================
246 #===============================================================================
247 class LoginForm(formencode.Schema):
247 class LoginForm(formencode.Schema):
248 allow_extra_fields = True
248 allow_extra_fields = True
249 filter_extra_fields = True
249 filter_extra_fields = True
250 username = UnicodeString(
250 username = UnicodeString(
251 strip=True,
251 strip=True,
252 min=1,
252 min=1,
253 not_empty=True,
253 not_empty=True,
254 messages={
254 messages={
255 'empty':_('Please enter a login'),
255 'empty':_('Please enter a login'),
256 'tooShort':_('Enter a value %(min)i characters long or more')}
256 'tooShort':_('Enter a value %(min)i characters long or more')}
257 )
257 )
258
258
259 password = UnicodeString(
259 password = UnicodeString(
260 strip=True,
260 strip=True,
261 min=6,
261 min=6,
262 not_empty=True,
262 not_empty=True,
263 messages={
263 messages={
264 'empty':_('Please enter a password'),
264 'empty':_('Please enter a password'),
265 'tooShort':_('Enter %(min)i characters or more')}
265 'tooShort':_('Enter %(min)i characters or more')}
266 )
266 )
267
267
268
268
269 #chained validators have access to all data
269 #chained validators have access to all data
270 chained_validators = [ValidAuth]
270 chained_validators = [ValidAuth]
271
271
272 def UserForm(edit=False, old_data={}):
272 def UserForm(edit=False, old_data={}):
273 class _UserForm(formencode.Schema):
273 class _UserForm(formencode.Schema):
274 allow_extra_fields = True
274 allow_extra_fields = True
275 filter_extra_fields = True
275 filter_extra_fields = True
276 username = All(UnicodeString(strip=True, min=1, not_empty=True), ValidUsername(edit, old_data))
276 username = All(UnicodeString(strip=True, min=1, not_empty=True), ValidUsername(edit, old_data))
277 if edit:
277 if edit:
278 new_password = All(UnicodeString(strip=True, min=6, not_empty=False), ValidPassword)
278 new_password = All(UnicodeString(strip=True, min=6, not_empty=False), ValidPassword)
279 admin = StringBoolean(if_missing=False)
279 admin = StringBoolean(if_missing=False)
280 else:
280 else:
281 password = All(UnicodeString(strip=True, min=6, not_empty=True), ValidPassword)
281 password = All(UnicodeString(strip=True, min=6, not_empty=True), ValidPassword)
282 active = StringBoolean(if_missing=False)
282 active = StringBoolean(if_missing=False)
283 name = UnicodeString(strip=True, min=1, not_empty=True)
283 name = UnicodeString(strip=True, min=1, not_empty=True)
284 lastname = UnicodeString(strip=True, min=1, not_empty=True)
284 lastname = UnicodeString(strip=True, min=1, not_empty=True)
285 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
285 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
286
286
287 return _UserForm
287 return _UserForm
288
288
289 RegisterForm = UserForm
289 RegisterForm = UserForm
290
290
291 def PasswordResetForm():
291 def PasswordResetForm():
292 class _PasswordResetForm(formencode.Schema):
292 class _PasswordResetForm(formencode.Schema):
293 allow_extra_fields = True
293 allow_extra_fields = True
294 filter_extra_fields = True
294 filter_extra_fields = True
295 email = All(ValidSystemEmail(), Email(not_empty=True))
295 email = All(ValidSystemEmail(), Email(not_empty=True))
296 return _PasswordResetForm
296 return _PasswordResetForm
297
297
298 def RepoForm(edit=False, old_data={}):
298 def RepoForm(edit=False, old_data={}):
299 class _RepoForm(formencode.Schema):
299 class _RepoForm(formencode.Schema):
300 allow_extra_fields = True
300 allow_extra_fields = True
301 filter_extra_fields = False
301 filter_extra_fields = False
302 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
302 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
303 description = UnicodeString(strip=True, min=1, not_empty=True)
303 description = UnicodeString(strip=True, min=1, not_empty=True)
304 private = StringBoolean(if_missing=False)
304 private = StringBoolean(if_missing=False)
305 repo_type = OneOf(BACKENDS.keys())
305 repo_type = OneOf(BACKENDS.keys())
306 if edit:
306 if edit:
307 user = All(Int(not_empty=True), ValidRepoUser)
307 user = All(Int(not_empty=True), ValidRepoUser)
308
308
309 chained_validators = [ValidPerms]
309 chained_validators = [ValidPerms]
310 return _RepoForm
310 return _RepoForm
311
311
312 def RepoForkForm(edit=False, old_data={}):
312 def RepoForkForm(edit=False, old_data={}):
313 class _RepoForkForm(formencode.Schema):
313 class _RepoForkForm(formencode.Schema):
314 allow_extra_fields = True
314 allow_extra_fields = True
315 filter_extra_fields = False
315 filter_extra_fields = False
316 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
316 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
317 description = UnicodeString(strip=True, min=1, not_empty=True)
317 description = UnicodeString(strip=True, min=1, not_empty=True)
318 private = StringBoolean(if_missing=False)
318 private = StringBoolean(if_missing=False)
319 repo_type = All(ValidForkType(old_data), OneOf(BACKENDS.keys()))
319 repo_type = All(ValidForkType(old_data), OneOf(BACKENDS.keys()))
320 return _RepoForkForm
320 return _RepoForkForm
321
321
322 def RepoSettingsForm(edit=False, old_data={}):
322 def RepoSettingsForm(edit=False, old_data={}):
323 class _RepoForm(formencode.Schema):
323 class _RepoForm(formencode.Schema):
324 allow_extra_fields = True
324 allow_extra_fields = True
325 filter_extra_fields = False
325 filter_extra_fields = False
326 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
326 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
327 description = UnicodeString(strip=True, min=1, not_empty=True)
327 description = UnicodeString(strip=True, min=1, not_empty=True)
328 private = StringBoolean(if_missing=False)
328 private = StringBoolean(if_missing=False)
329
329
330 chained_validators = [ValidPerms, ValidSettings]
330 chained_validators = [ValidPerms, ValidSettings]
331 return _RepoForm
331 return _RepoForm
332
332
333
333
334 def ApplicationSettingsForm():
334 def ApplicationSettingsForm():
335 class _ApplicationSettingsForm(formencode.Schema):
335 class _ApplicationSettingsForm(formencode.Schema):
336 allow_extra_fields = True
336 allow_extra_fields = True
337 filter_extra_fields = False
337 filter_extra_fields = False
338 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
338 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
339 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
339 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
340
340
341 return _ApplicationSettingsForm
341 return _ApplicationSettingsForm
342
342
343 def ApplicationUiSettingsForm():
343 def ApplicationUiSettingsForm():
344 class _ApplicationUiSettingsForm(formencode.Schema):
344 class _ApplicationUiSettingsForm(formencode.Schema):
345 allow_extra_fields = True
345 allow_extra_fields = True
346 filter_extra_fields = False
346 filter_extra_fields = False
347 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
347 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
348 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
348 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
349 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
349 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
350 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
350 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
351 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
351 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
352 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
352 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
353
353
354 return _ApplicationUiSettingsForm
354 return _ApplicationUiSettingsForm
355
355
356 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
356 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
357 class _DefaultPermissionsForm(formencode.Schema):
357 class _DefaultPermissionsForm(formencode.Schema):
358 allow_extra_fields = True
358 allow_extra_fields = True
359 filter_extra_fields = True
359 filter_extra_fields = True
360 overwrite_default = OneOf(['true', 'false'], if_missing='false')
360 overwrite_default = OneOf(['true', 'false'], if_missing='false')
361 anonymous = OneOf(['True', 'False'], if_missing=False)
361 default_perm = OneOf(perms_choices)
362 default_perm = OneOf(perms_choices)
362 default_register = OneOf(register_choices)
363 default_register = OneOf(register_choices)
363 default_create = OneOf(create_choices)
364 default_create = OneOf(create_choices)
364
365
365 return _DefaultPermissionsForm
366 return _DefaultPermissionsForm
@@ -1,95 +1,106 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Model for permissions
3 # Model for permissions
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5
5
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on Aug 20, 2010
21 Created on Aug 20, 2010
22 Model for permissions
22 Model for permissions
23 @author: marcink
23 @author: marcink
24 """
24 """
25
25
26 from rhodecode.model.db import User, Permission, UserToPerm, RepoToPerm
26 from rhodecode.model.db import User, Permission, UserToPerm, RepoToPerm
27 from rhodecode.model.caching_query import FromCache
27 from rhodecode.model.caching_query import FromCache
28 from rhodecode.model.meta import Session
28 from rhodecode.model.meta import Session
29 import logging
29 import logging
30 import traceback
30 import traceback
31 log = logging.getLogger(__name__)
31 log = logging.getLogger(__name__)
32
32
33
33
34 class PermissionModel(object):
34 class PermissionModel(object):
35
35
36 def __init__(self, sa=None):
36 def __init__(self, sa=None):
37 if not sa:
37 if not sa:
38 self.sa = Session()
38 self.sa = Session()
39 else:
39 else:
40 self.sa = sa
40 self.sa = sa
41
41
42 def get_permission(self, permission_id, cache=False):
42 def get_permission(self, permission_id, cache=False):
43 perm = self.sa.query(Permission)
43 perm = self.sa.query(Permission)
44 if cache:
44 if cache:
45 perm = perm.options(FromCache("sql_cache_short",
45 perm = perm.options(FromCache("sql_cache_short",
46 "get_permission_%s" % permission_id))
46 "get_permission_%s" % permission_id))
47 return perm.get(permission_id)
47 return perm.get(permission_id)
48
48
49 def get_permission_by_name(self, name, cache=False):
49 def get_permission_by_name(self, name, cache=False):
50 perm = self.sa.query(Permission)\
50 perm = self.sa.query(Permission)\
51 .filter(Permission.permission_name == name)
51 .filter(Permission.permission_name == name)
52 if cache:
52 if cache:
53 perm = perm.options(FromCache("sql_cache_short",
53 perm = perm.options(FromCache("sql_cache_short",
54 "get_permission_%s" % name))
54 "get_permission_%s" % name))
55 return perm.scalar()
55 return perm.scalar()
56
56
57 def update(self, form_result):
57 def update(self, form_result):
58 perm_user = self.sa.query(User)\
58 perm_user = self.sa.query(User)\
59 .filter(User.username == form_result['perm_user_name']).scalar()
59 .filter(User.username == form_result['perm_user_name']).scalar()
60 u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all()
60 u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all()
61 if len(u2p) != 3:
61 if len(u2p) != 3:
62 raise Exception('There is more than 3 defined'
62 raise Exception('Defined: %s should be 3 permissions for default'
63 ' permissions for default user. This should not happen please verify'
63 ' user. This should not happen please verify'
64 ' your database')
64 ' your database' % len(u2p))
65
65
66 try:
66 try:
67 #stage 1 change defaults
67 #stage 1 change defaults
68 for p in u2p:
68 for p in u2p:
69 if p.permission.permission_name.startswith('repository.'):
69 if p.permission.permission_name.startswith('repository.'):
70 p.permission = self.get_permission_by_name(form_result['default_perm'])
70 p.permission = self.get_permission_by_name(
71 form_result['default_perm'])
71 self.sa.add(p)
72 self.sa.add(p)
72
73
73 if p.permission.permission_name.startswith('hg.register.'):
74 if p.permission.permission_name.startswith('hg.register.'):
74 p.permission = self.get_permission_by_name(form_result['default_register'])
75 p.permission = self.get_permission_by_name(
76 form_result['default_register'])
75 self.sa.add(p)
77 self.sa.add(p)
76
78
77 if p.permission.permission_name.startswith('hg.create.'):
79 if p.permission.permission_name.startswith('hg.create.'):
78 p.permission = self.get_permission_by_name(form_result['default_create'])
80 p.permission = self.get_permission_by_name(
81 form_result['default_create'])
79 self.sa.add(p)
82 self.sa.add(p)
80 #stage 2 update all default permissions for repos if checked
83 #stage 2 update all default permissions for repos if checked
81 if form_result['overwrite_default'] == 'true':
84 if form_result['overwrite_default'] == 'true':
82 for r2p in self.sa.query(RepoToPerm).filter(RepoToPerm.user == perm_user).all():
85 for r2p in self.sa.query(RepoToPerm)\
83 r2p.permission = self.get_permission_by_name(form_result['default_perm'])
86 .filter(RepoToPerm.user == perm_user).all():
87 r2p.permission = self.get_permission_by_name(
88 form_result['default_perm'])
84 self.sa.add(r2p)
89 self.sa.add(r2p)
85
90
91 #stage 3 set anonymous access
92 if perm_user.username == 'default':
93 perm_user.active = bool(form_result['anonymous'])
94 self.sa.add(perm_user)
95
96
86 self.sa.commit()
97 self.sa.commit()
87 except:
98 except:
88 log.error(traceback.format_exc())
99 log.error(traceback.format_exc())
89 self.sa.rollback()
100 self.sa.rollback()
90 raise
101 raise
91
102
92
103
93
104
94
105
95
106
@@ -1,145 +1,166 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Model for users
3 # Model for users
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 9, 2010
21 Created on April 9, 2010
22 Model for users
22 Model for users
23 :author: marcink
23 :author: marcink
24 """
24 """
25
25
26 from pylons.i18n.translation import _
26 from pylons.i18n.translation import _
27 from rhodecode.model.caching_query import FromCache
27 from rhodecode.model.caching_query import FromCache
28 from rhodecode.model.db import User
28 from rhodecode.model.db import User
29 from rhodecode.model.meta import Session
29 from rhodecode.model.meta import Session
30 import logging
30 import logging
31 import traceback
31 import traceback
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
35 class DefaultUserException(Exception):pass
35 class DefaultUserException(Exception):pass
36
36
37 class UserModel(object):
37 class UserModel(object):
38
38
39 def __init__(self, sa=None):
39 def __init__(self, sa=None):
40 if not sa:
40 if not sa:
41 self.sa = Session()
41 self.sa = Session()
42 else:
42 else:
43 self.sa = sa
43 self.sa = sa
44
44
45 def get(self, user_id, cache=False):
45 def get(self, user_id, cache=False):
46 user = self.sa.query(User)
46 user = self.sa.query(User)
47 if cache:
47 if cache:
48 user = user.options(FromCache("sql_cache_short",
48 user = user.options(FromCache("sql_cache_short",
49 "get_user_%s" % user_id))
49 "get_user_%s" % user_id))
50 return user.get(user_id)
50 return user.get(user_id)
51
51
52
52
53 def get_by_username(self, username, cache=False):
53 def get_by_username(self, username, cache=False):
54 user = self.sa.query(User)\
54 user = self.sa.query(User)\
55 .filter(User.username == username)
55 .filter(User.username == username)
56 if cache:
56 if cache:
57 user = user.options(FromCache("sql_cache_short",
57 user = user.options(FromCache("sql_cache_short",
58 "get_user_%s" % username))
58 "get_user_%s" % username))
59 return user.scalar()
59 return user.scalar()
60
60
61 def create(self, form_data):
61 def create(self, form_data):
62 try:
62 try:
63 new_user = User()
63 new_user = User()
64 for k, v in form_data.items():
64 for k, v in form_data.items():
65 setattr(new_user, k, v)
65 setattr(new_user, k, v)
66
66
67 self.sa.add(new_user)
67 self.sa.add(new_user)
68 self.sa.commit()
68 self.sa.commit()
69 except:
69 except:
70 log.error(traceback.format_exc())
70 log.error(traceback.format_exc())
71 self.sa.rollback()
71 self.sa.rollback()
72 raise
72 raise
73
73
74 def create_registration(self, form_data):
74 def create_registration(self, form_data):
75 try:
75 try:
76 new_user = User()
76 new_user = User()
77 for k, v in form_data.items():
77 for k, v in form_data.items():
78 if k != 'admin':
78 if k != 'admin':
79 setattr(new_user, k, v)
79 setattr(new_user, k, v)
80
80
81 self.sa.add(new_user)
81 self.sa.add(new_user)
82 self.sa.commit()
82 self.sa.commit()
83 except:
83 except:
84 log.error(traceback.format_exc())
84 log.error(traceback.format_exc())
85 self.sa.rollback()
85 self.sa.rollback()
86 raise
86 raise
87
87
88 def update(self, user_id, form_data):
88 def update(self, user_id, form_data):
89 try:
89 try:
90 new_user = self.get(user_id, cache=False)
90 new_user = self.get(user_id, cache=False)
91 if new_user.username == 'default':
91 if new_user.username == 'default':
92 raise DefaultUserException(
92 raise DefaultUserException(
93 _("You can't Edit this user since it's"
93 _("You can't Edit this user since it's"
94 " crucial for entire application"))
94 " crucial for entire application"))
95 for k, v in form_data.items():
95 for k, v in form_data.items():
96 if k == 'new_password' and v != '':
96 if k == 'new_password' and v != '':
97 new_user.password = v
97 new_user.password = v
98 else:
98 else:
99 setattr(new_user, k, v)
99 setattr(new_user, k, v)
100
100
101 self.sa.add(new_user)
101 self.sa.add(new_user)
102 self.sa.commit()
102 self.sa.commit()
103 except:
103 except:
104 log.error(traceback.format_exc())
104 log.error(traceback.format_exc())
105 self.sa.rollback()
105 self.sa.rollback()
106 raise
106 raise
107
107
108 def update_my_account(self, user_id, form_data):
108 def update_my_account(self, user_id, form_data):
109 try:
109 try:
110 new_user = self.get(user_id, cache=False)
110 new_user = self.get(user_id, cache=False)
111 if new_user.username == 'default':
111 if new_user.username == 'default':
112 raise DefaultUserException(
112 raise DefaultUserException(
113 _("You can't Edit this user since it's"
113 _("You can't Edit this user since it's"
114 " crucial for entire application"))
114 " crucial for entire application"))
115 for k, v in form_data.items():
115 for k, v in form_data.items():
116 if k == 'new_password' and v != '':
116 if k == 'new_password' and v != '':
117 new_user.password = v
117 new_user.password = v
118 else:
118 else:
119 if k not in ['admin', 'active']:
119 if k not in ['admin', 'active']:
120 setattr(new_user, k, v)
120 setattr(new_user, k, v)
121
121
122 self.sa.add(new_user)
122 self.sa.add(new_user)
123 self.sa.commit()
123 self.sa.commit()
124 except:
124 except:
125 log.error(traceback.format_exc())
125 log.error(traceback.format_exc())
126 self.sa.rollback()
126 self.sa.rollback()
127 raise
127 raise
128
128
129 def delete(self, user_id):
129 def delete(self, user_id):
130 try:
130 try:
131 user = self.get(user_id, cache=False)
131 user = self.get(user_id, cache=False)
132 if user.username == 'default':
132 if user.username == 'default':
133 raise DefaultUserException(
133 raise DefaultUserException(
134 _("You can't remove this user since it's"
134 _("You can't remove this user since it's"
135 " crucial for entire application"))
135 " crucial for entire application"))
136 self.sa.delete(user)
136 self.sa.delete(user)
137 self.sa.commit()
137 self.sa.commit()
138 except:
138 except:
139 log.error(traceback.format_exc())
139 log.error(traceback.format_exc())
140 self.sa.rollback()
140 self.sa.rollback()
141 raise
141 raise
142
142
143 def reset_password(self, data):
143 def reset_password(self, data):
144 from rhodecode.lib.celerylib import tasks, run_task
144 from rhodecode.lib.celerylib import tasks, run_task
145 run_task(tasks.reset_user_password, data['email'])
145 run_task(tasks.reset_user_password, data['email'])
146
147
148 def fill_data(self, user):
149 """
150 Fills user data with those from database and log out user if not
151 present in database
152 :param user:
153 """
154 log.debug('filling auth user data')
155 try:
156 dbuser = self.get(user.user_id)
157 user.username = dbuser.username
158 user.is_admin = dbuser.admin
159 user.name = dbuser.name
160 user.lastname = dbuser.lastname
161 user.email = dbuser.email
162 except:
163 log.error(traceback.format_exc())
164 user.is_authenticated = False
165
166 return user
@@ -1,2321 +1,2321 b''
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
2 border:0;
2 border:0;
3 outline:0;
3 outline:0;
4 font-size:100%;
4 font-size:100%;
5 vertical-align:baseline;
5 vertical-align:baseline;
6 background:transparent;
6 background:transparent;
7 margin:0;
7 margin:0;
8 padding:0;
8 padding:0;
9 }
9 }
10
10
11 body {
11 body {
12 line-height:1;
12 line-height:1;
13 height:100%;
13 height:100%;
14 background:url("../images/background.png") repeat scroll 0 0 #B0B0B0;
14 background:url("../images/background.png") repeat scroll 0 0 #B0B0B0;
15 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
15 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
16 font-size:12px;
16 font-size:12px;
17 color:#000;
17 color:#000;
18 margin:0;
18 margin:0;
19 padding:0;
19 padding:0;
20 }
20 }
21
21
22 ol,ul {
22 ol,ul {
23 list-style:none;
23 list-style:none;
24 }
24 }
25
25
26 blockquote,q {
26 blockquote,q {
27 quotes:none;
27 quotes:none;
28 }
28 }
29
29
30 blockquote:before,blockquote:after,q:before,q:after {
30 blockquote:before,blockquote:after,q:before,q:after {
31 content:none;
31 content:none;
32 }
32 }
33
33
34 :focus {
34 :focus {
35 outline:0;
35 outline:0;
36 }
36 }
37
37
38 del {
38 del {
39 text-decoration:line-through;
39 text-decoration:line-through;
40 }
40 }
41
41
42 table {
42 table {
43 border-collapse:collapse;
43 border-collapse:collapse;
44 border-spacing:0;
44 border-spacing:0;
45 }
45 }
46
46
47 html {
47 html {
48 height:100%;
48 height:100%;
49 }
49 }
50
50
51 a {
51 a {
52 color:#003367;
52 color:#003367;
53 text-decoration:none;
53 text-decoration:none;
54 cursor:pointer;
54 cursor:pointer;
55 font-weight:700;
55 font-weight:700;
56 }
56 }
57
57
58 a:hover {
58 a:hover {
59 color:#316293;
59 color:#316293;
60 text-decoration:underline;
60 text-decoration:underline;
61 }
61 }
62
62
63 h1,h2,h3,h4,h5,h6 {
63 h1,h2,h3,h4,h5,h6 {
64 color:#292929;
64 color:#292929;
65 font-weight:700;
65 font-weight:700;
66 }
66 }
67
67
68 h1 {
68 h1 {
69 font-size:22px;
69 font-size:22px;
70 }
70 }
71
71
72 h2 {
72 h2 {
73 font-size:20px;
73 font-size:20px;
74 }
74 }
75
75
76 h3 {
76 h3 {
77 font-size:18px;
77 font-size:18px;
78 }
78 }
79
79
80 h4 {
80 h4 {
81 font-size:16px;
81 font-size:16px;
82 }
82 }
83
83
84 h5 {
84 h5 {
85 font-size:14px;
85 font-size:14px;
86 }
86 }
87
87
88 h6 {
88 h6 {
89 font-size:11px;
89 font-size:11px;
90 }
90 }
91
91
92 ul.circle {
92 ul.circle {
93 list-style-type:circle;
93 list-style-type:circle;
94 }
94 }
95
95
96 ul.disc {
96 ul.disc {
97 list-style-type:disc;
97 list-style-type:disc;
98 }
98 }
99
99
100 ul.square {
100 ul.square {
101 list-style-type:square;
101 list-style-type:square;
102 }
102 }
103
103
104 ol.lower-roman {
104 ol.lower-roman {
105 list-style-type:lower-roman;
105 list-style-type:lower-roman;
106 }
106 }
107
107
108 ol.upper-roman {
108 ol.upper-roman {
109 list-style-type:upper-roman;
109 list-style-type:upper-roman;
110 }
110 }
111
111
112 ol.lower-alpha {
112 ol.lower-alpha {
113 list-style-type:lower-alpha;
113 list-style-type:lower-alpha;
114 }
114 }
115
115
116 ol.upper-alpha {
116 ol.upper-alpha {
117 list-style-type:upper-alpha;
117 list-style-type:upper-alpha;
118 }
118 }
119
119
120 ol.decimal {
120 ol.decimal {
121 list-style-type:decimal;
121 list-style-type:decimal;
122 }
122 }
123
123
124 div.color {
124 div.color {
125 clear:both;
125 clear:both;
126 overflow:hidden;
126 overflow:hidden;
127 position:absolute;
127 position:absolute;
128 background:#FFF;
128 background:#FFF;
129 margin:7px 0 0 60px;
129 margin:7px 0 0 60px;
130 padding:1px 1px 1px 0;
130 padding:1px 1px 1px 0;
131 }
131 }
132
132
133 div.color a {
133 div.color a {
134 width:15px;
134 width:15px;
135 height:15px;
135 height:15px;
136 display:block;
136 display:block;
137 float:left;
137 float:left;
138 margin:0 0 0 1px;
138 margin:0 0 0 1px;
139 padding:0;
139 padding:0;
140 }
140 }
141
141
142 div.options {
142 div.options {
143 clear:both;
143 clear:both;
144 overflow:hidden;
144 overflow:hidden;
145 position:absolute;
145 position:absolute;
146 background:#FFF;
146 background:#FFF;
147 margin:7px 0 0 162px;
147 margin:7px 0 0 162px;
148 padding:0;
148 padding:0;
149 }
149 }
150
150
151 div.options a {
151 div.options a {
152 height:1%;
152 height:1%;
153 display:block;
153 display:block;
154 text-decoration:none;
154 text-decoration:none;
155 margin:0;
155 margin:0;
156 padding:3px 8px;
156 padding:3px 8px;
157 }
157 }
158
158
159 .top-left-rounded-corner {
159 .top-left-rounded-corner {
160 -webkit-border-top-left-radius: 8px;
160 -webkit-border-top-left-radius: 8px;
161 -khtml-border-radius-topleft: 8px;
161 -khtml-border-radius-topleft: 8px;
162 -moz-border-radius-topleft: 8px;
162 -moz-border-radius-topleft: 8px;
163 border-top-left-radius: 8px;
163 border-top-left-radius: 8px;
164 }
164 }
165
165
166 .top-right-rounded-corner {
166 .top-right-rounded-corner {
167 -webkit-border-top-right-radius: 8px;
167 -webkit-border-top-right-radius: 8px;
168 -khtml-border-radius-topright: 8px;
168 -khtml-border-radius-topright: 8px;
169 -moz-border-radius-topright: 8px;
169 -moz-border-radius-topright: 8px;
170 border-top-right-radius: 8px;
170 border-top-right-radius: 8px;
171 }
171 }
172
172
173 .bottom-left-rounded-corner {
173 .bottom-left-rounded-corner {
174 -webkit-border-bottom-left-radius: 8px;
174 -webkit-border-bottom-left-radius: 8px;
175 -khtml-border-radius-bottomleft: 8px;
175 -khtml-border-radius-bottomleft: 8px;
176 -moz-border-radius-bottomleft: 8px;
176 -moz-border-radius-bottomleft: 8px;
177 border-bottom-left-radius: 8px;
177 border-bottom-left-radius: 8px;
178 }
178 }
179
179
180 .bottom-right-rounded-corner {
180 .bottom-right-rounded-corner {
181 -webkit-border-bottom-right-radius: 8px;
181 -webkit-border-bottom-right-radius: 8px;
182 -khtml-border-radius-bottomright: 8px;
182 -khtml-border-radius-bottomright: 8px;
183 -moz-border-radius-bottomright: 8px;
183 -moz-border-radius-bottomright: 8px;
184 border-bottom-right-radius: 8px;
184 border-bottom-right-radius: 8px;
185 }
185 }
186
186
187
187
188 #header {
188 #header {
189 margin:0;
189 margin:0;
190 padding:0 30px;
190 padding:0 30px;
191 }
191 }
192
192
193 #header ul#logged-user li {
193 #header ul#logged-user li {
194 list-style:none;
194 list-style:none;
195 float:left;
195 float:left;
196 border-left:1px solid #bbb;
196 border-left:1px solid #bbb;
197 border-right:1px solid #a5a5a5;
197 border-right:1px solid #a5a5a5;
198 margin:-2px 0 0;
198 margin:-2px 0 0;
199 padding:10px 12px;
199 padding:10px 12px;
200 }
200 }
201
201
202 #header ul#logged-user li.first {
202 #header ul#logged-user li.first {
203 border-left:none;
203 border-left:none;
204 margin:-6px;
204 margin:-6px;
205 }
205 }
206
206
207 #header ul#logged-user li.first div.account {
207 #header ul#logged-user li.first div.account {
208 padding-top:4px;
208 padding-top:4px;
209 float:left;
209 float:left;
210 }
210 }
211
211
212 #header ul#logged-user li.last {
212 #header ul#logged-user li.last {
213 border-right:none;
213 border-right:none;
214 }
214 }
215
215
216 #header ul#logged-user li a {
216 #header ul#logged-user li a {
217 color:#4e4e4e;
217 color:#4e4e4e;
218 font-weight:700;
218 font-weight:700;
219 text-decoration:none;
219 text-decoration:none;
220 }
220 }
221
221
222 #header ul#logged-user li a:hover {
222 #header ul#logged-user li a:hover {
223 color:#376ea6;
223 color:#376ea6;
224 text-decoration:underline;
224 text-decoration:underline;
225 }
225 }
226
226
227 #header ul#logged-user li.highlight a {
227 #header ul#logged-user li.highlight a {
228 color:#fff;
228 color:#fff;
229 }
229 }
230
230
231 #header ul#logged-user li.highlight a:hover {
231 #header ul#logged-user li.highlight a:hover {
232 color:#376ea6;
232 color:#376ea6;
233 }
233 }
234
234
235 #header #header-inner {
235 #header #header-inner {
236 height:40px;
236 height:40px;
237 clear:both;
237 clear:both;
238 position:relative;
238 position:relative;
239 background:#003367 url("../images/header_inner.png") repeat-x;
239 background:#003367 url("../images/header_inner.png") repeat-x;
240 border-bottom:2px solid #fff;
240 border-bottom:2px solid #fff;
241 margin:0;
241 margin:0;
242 padding:0;
242 padding:0;
243 }
243 }
244
244
245 #header #header-inner #home a {
245 #header #header-inner #home a {
246 height:40px;
246 height:40px;
247 width:46px;
247 width:46px;
248 display:block;
248 display:block;
249 background:url("../images/button_home.png");
249 background:url("../images/button_home.png");
250 background-position:0 0;
250 background-position:0 0;
251 margin:0;
251 margin:0;
252 padding:0;
252 padding:0;
253 }
253 }
254
254
255 #header #header-inner #home a:hover {
255 #header #header-inner #home a:hover {
256 background-position:0 -40px;
256 background-position:0 -40px;
257 }
257 }
258
258
259 #header #header-inner #logo h1 {
259 #header #header-inner #logo h1 {
260 color:#FFF;
260 color:#FFF;
261 font-size:14px;
261 font-size:14px;
262 margin:13px 0 0 13px;
262 margin:13px 0 0 13px;
263 padding:0;
263 padding:0;
264 }
264 }
265
265
266 #header #header-inner #logo a {
266 #header #header-inner #logo a {
267 color:#fff;
267 color:#fff;
268 text-decoration:none;
268 text-decoration:none;
269 }
269 }
270
270
271 #header #header-inner #logo a:hover {
271 #header #header-inner #logo a:hover {
272 color:#bfe3ff;
272 color:#bfe3ff;
273 }
273 }
274
274
275 #header #header-inner #quick,#header #header-inner #quick ul {
275 #header #header-inner #quick,#header #header-inner #quick ul {
276 position:relative;
276 position:relative;
277 float:right;
277 float:right;
278 list-style-type:none;
278 list-style-type:none;
279 list-style-position:outside;
279 list-style-position:outside;
280 margin:10px 5px 0 0;
280 margin:10px 5px 0 0;
281 padding:0;
281 padding:0;
282 }
282 }
283
283
284 #header #header-inner #quick li {
284 #header #header-inner #quick li {
285 position:relative;
285 position:relative;
286 float:left;
286 float:left;
287 margin:0 5px 0 0;
287 margin:0 5px 0 0;
288 padding:0;
288 padding:0;
289 }
289 }
290
290
291 #header #header-inner #quick li a {
291 #header #header-inner #quick li a {
292 top:0;
292 top:0;
293 left:0;
293 left:0;
294 height:1%;
294 height:1%;
295 display:block;
295 display:block;
296 clear:both;
296 clear:both;
297 overflow:hidden;
297 overflow:hidden;
298 color:#FFF;
298 color:#FFF;
299 font-weight:700;
299 font-weight:700;
300 text-decoration:none;
300 text-decoration:none;
301 background:#369 url("../../images/quick_l.png") no-repeat top left;
301 background:#369 url("../../images/quick_l.png") no-repeat top left;
302 padding:0;
302 padding:0;
303 }
303 }
304
304
305 #header #header-inner #quick li span {
305 #header #header-inner #quick li span {
306 top:0;
306 top:0;
307 right:0;
307 right:0;
308 height:1%;
308 height:1%;
309 display:block;
309 display:block;
310 float:left;
310 float:left;
311 background:url("../../images/quick_r.png") no-repeat top right;
311 background:url("../../images/quick_r.png") no-repeat top right;
312 border-left:1px solid #3f6f9f;
312 border-left:1px solid #3f6f9f;
313 margin:0;
313 margin:0;
314 padding:10px 12px 8px 10px;
314 padding:10px 12px 8px 10px;
315 }
315 }
316
316
317 #header #header-inner #quick li span.normal {
317 #header #header-inner #quick li span.normal {
318 border:none;
318 border:none;
319 padding:10px 12px 8px;
319 padding:10px 12px 8px;
320 }
320 }
321
321
322 #header #header-inner #quick li span.icon {
322 #header #header-inner #quick li span.icon {
323 top:0;
323 top:0;
324 left:0;
324 left:0;
325 border-left:none;
325 border-left:none;
326 background:url("../../images/quick_l.png") no-repeat top left;
326 background:url("../../images/quick_l.png") no-repeat top left;
327 border-right:1px solid #2e5c89;
327 border-right:1px solid #2e5c89;
328 padding:8px 8px 4px;
328 padding:8px 8px 4px;
329 }
329 }
330
330
331 #header #header-inner #quick li a:hover {
331 #header #header-inner #quick li a:hover {
332 background:#4e4e4e url("../../images/quick_l_selected.png") no-repeat top left;
332 background:#4e4e4e url("../../images/quick_l_selected.png") no-repeat top left;
333 }
333 }
334
334
335 #header #header-inner #quick li a:hover span {
335 #header #header-inner #quick li a:hover span {
336 border-left:1px solid #545454;
336 border-left:1px solid #545454;
337 background:url("../../images/quick_r_selected.png") no-repeat top right;
337 background:url("../../images/quick_r_selected.png") no-repeat top right;
338 }
338 }
339
339
340 #header #header-inner #quick li a:hover span.icon {
340 #header #header-inner #quick li a:hover span.icon {
341 border-left:none;
341 border-left:none;
342 border-right:1px solid #464646;
342 border-right:1px solid #464646;
343 background:url("../../images/quick_l_selected.png") no-repeat top left;
343 background:url("../../images/quick_l_selected.png") no-repeat top left;
344 }
344 }
345
345
346 #header #header-inner #quick ul {
346 #header #header-inner #quick ul {
347 top:29px;
347 top:29px;
348 right:0;
348 right:0;
349 min-width:200px;
349 min-width:200px;
350 display:none;
350 display:none;
351 position:absolute;
351 position:absolute;
352 background:#FFF;
352 background:#FFF;
353 border:1px solid #666;
353 border:1px solid #666;
354 border-top:1px solid #003367;
354 border-top:1px solid #003367;
355 z-index:100;
355 z-index:100;
356 margin:0;
356 margin:0;
357 padding:0;
357 padding:0;
358 }
358 }
359
359
360 #header #header-inner #quick ul.repo_switcher {
360 #header #header-inner #quick ul.repo_switcher {
361 max-height:275px;
361 max-height:275px;
362 overflow-x:hidden;
362 overflow-x:hidden;
363 overflow-y:auto;
363 overflow-y:auto;
364 }
364 }
365
365
366 #header #header-inner #quick li ul li {
366 #header #header-inner #quick li ul li {
367 border-bottom:1px solid #ddd;
367 border-bottom:1px solid #ddd;
368 }
368 }
369
369
370 #header #header-inner #quick li ul li a {
370 #header #header-inner #quick li ul li a {
371 width:182px;
371 width:182px;
372 height:auto;
372 height:auto;
373 display:block;
373 display:block;
374 float:left;
374 float:left;
375 background:#FFF;
375 background:#FFF;
376 color:#003367;
376 color:#003367;
377 font-weight:400;
377 font-weight:400;
378 margin:0;
378 margin:0;
379 padding:7px 9px;
379 padding:7px 9px;
380 }
380 }
381
381
382 #header #header-inner #quick li ul li a:hover {
382 #header #header-inner #quick li ul li a:hover {
383 color:#000;
383 color:#000;
384 background:#FFF;
384 background:#FFF;
385 }
385 }
386
386
387 #header #header-inner #quick ul ul {
387 #header #header-inner #quick ul ul {
388 top:auto;
388 top:auto;
389 }
389 }
390
390
391 #header #header-inner #quick li ul ul {
391 #header #header-inner #quick li ul ul {
392 right:200px;
392 right:200px;
393 max-height:275px;
393 max-height:275px;
394 overflow:auto;
394 overflow:auto;
395 overflow-x:hidden;
395 overflow-x:hidden;
396 white-space:nowrap;
396 white-space:nowrap;
397 }
397 }
398
398
399 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
399 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
400 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
400 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
401 width:167px;
401 width:167px;
402 margin:0;
402 margin:0;
403 padding:12px 9px 7px 24px;
403 padding:12px 9px 7px 24px;
404 }
404 }
405
405
406 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
406 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
407 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
407 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
408 min-width:167px;
408 min-width:167px;
409 margin:0;
409 margin:0;
410 padding:12px 9px 7px 24px;
410 padding:12px 9px 7px 24px;
411 }
411 }
412
412
413 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
413 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
414 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
414 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
415 min-width:167px;
415 min-width:167px;
416 margin:0;
416 margin:0;
417 padding:12px 9px 7px 24px;
417 padding:12px 9px 7px 24px;
418 }
418 }
419
419
420 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
420 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
421 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
421 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
422 width:167px;
422 width:167px;
423 margin:0;
423 margin:0;
424 padding:12px 9px 7px 24px;
424 padding:12px 9px 7px 24px;
425 }
425 }
426
426
427 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
427 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
428 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
428 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
429 width:167px;
429 width:167px;
430 margin:0;
430 margin:0;
431 padding:12px 9px 7px 24px;
431 padding:12px 9px 7px 24px;
432 }
432 }
433
433
434 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
434 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
435 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
435 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
436 width:167px;
436 width:167px;
437 margin:0;
437 margin:0;
438 padding:12px 9px 7px 24px;
438 padding:12px 9px 7px 24px;
439 }
439 }
440
440
441 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
441 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
442 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
442 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
443 width:167px;
443 width:167px;
444 margin:0;
444 margin:0;
445 padding:12px 9px 7px 24px;
445 padding:12px 9px 7px 24px;
446 }
446 }
447
447
448 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
448 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
449 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
449 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
450 width:167px;
450 width:167px;
451 margin:0;
451 margin:0;
452 padding:12px 9px 7px 24px;
452 padding:12px 9px 7px 24px;
453 }
453 }
454
454
455 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
455 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
456 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
456 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
457 width:167px;
457 width:167px;
458 margin:0;
458 margin:0;
459 padding:12px 9px 7px 24px;
459 padding:12px 9px 7px 24px;
460 }
460 }
461
461
462 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
462 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
463 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
463 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
464 width:167px;
464 width:167px;
465 margin:0;
465 margin:0;
466 padding:12px 9px 7px 24px;
466 padding:12px 9px 7px 24px;
467 }
467 }
468
468
469 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
469 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
470 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
470 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
471 width:167px;
471 width:167px;
472 margin:0;
472 margin:0;
473 padding:12px 9px 7px 24px;
473 padding:12px 9px 7px 24px;
474 }
474 }
475
475
476 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
476 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
477 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
477 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
478 width:167px;
478 width:167px;
479 margin:0;
479 margin:0;
480 padding:12px 9px 7px 24px;
480 padding:12px 9px 7px 24px;
481 }
481 }
482
482
483 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
483 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
484 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
484 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
485 width:167px;
485 width:167px;
486 margin:0;
486 margin:0;
487 padding:12px 9px 7px 24px;
487 padding:12px 9px 7px 24px;
488 }
488 }
489
489
490 #content #left {
490 #content #left {
491 left:0;
491 left:0;
492 width:280px;
492 width:280px;
493 position:absolute;
493 position:absolute;
494 }
494 }
495
495
496 #content #right {
496 #content #right {
497 margin:0 60px 10px 290px;
497 margin:0 60px 10px 290px;
498 }
498 }
499
499
500 #content div.box {
500 #content div.box {
501 clear:both;
501 clear:both;
502 overflow:hidden;
502 overflow:hidden;
503 background:#fff;
503 background:#fff;
504 margin:0 0 10px;
504 margin:0 0 10px;
505 padding:0 0 10px;
505 padding:0 0 10px;
506 }
506 }
507
507
508 #content div.box-left {
508 #content div.box-left {
509 width:49%;
509 width:49%;
510 clear:none;
510 clear:none;
511 float:left;
511 float:left;
512 margin:0 0 10px;
512 margin:0 0 10px;
513 }
513 }
514
514
515 #content div.box-right {
515 #content div.box-right {
516 width:49%;
516 width:49%;
517 clear:none;
517 clear:none;
518 float:right;
518 float:right;
519 margin:0 0 10px;
519 margin:0 0 10px;
520 }
520 }
521
521
522 #content div.box div.title {
522 #content div.box div.title {
523 clear:both;
523 clear:both;
524 overflow:hidden;
524 overflow:hidden;
525 background:#369 url("../images/header_inner.png") repeat-x;
525 background:#369 url("../images/header_inner.png") repeat-x;
526 margin:0 0 20px;
526 margin:0 0 20px;
527 padding:0;
527 padding:0;
528 }
528 }
529
529
530 #content div.box div.title h5 {
530 #content div.box div.title h5 {
531 float:left;
531 float:left;
532 border:none;
532 border:none;
533 color:#fff;
533 color:#fff;
534 text-transform:uppercase;
534 text-transform:uppercase;
535 margin:0;
535 margin:0;
536 padding:11px 0 11px 10px;
536 padding:11px 0 11px 10px;
537 }
537 }
538
538
539 #content div.box div.title ul.links li {
539 #content div.box div.title ul.links li {
540 list-style:none;
540 list-style:none;
541 float:left;
541 float:left;
542 margin:0;
542 margin:0;
543 padding:0;
543 padding:0;
544 }
544 }
545
545
546 #content div.box div.title ul.links li a {
546 #content div.box div.title ul.links li a {
547 height:1%;
547 height:1%;
548 display:block;
548 display:block;
549 float:left;
549 float:left;
550 border-left:1px solid #316293;
550 border-left:1px solid #316293;
551 color:#fff;
551 color:#fff;
552 font-size:11px;
552 font-size:11px;
553 font-weight:700;
553 font-weight:700;
554 text-decoration:none;
554 text-decoration:none;
555 margin:0;
555 margin:0;
556 padding:13px 16px 12px;
556 padding:13px 16px 12px;
557 }
557 }
558
558
559 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
559 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
560 clear:both;
560 clear:both;
561 overflow:hidden;
561 overflow:hidden;
562 border-bottom:1px solid #DDD;
562 border-bottom:1px solid #DDD;
563 margin:10px 20px;
563 margin:10px 20px;
564 padding:0 0 15px;
564 padding:0 0 15px;
565 }
565 }
566
566
567 #content div.box p {
567 #content div.box p {
568 color:#5f5f5f;
568 color:#5f5f5f;
569 font-size:12px;
569 font-size:12px;
570 line-height:150%;
570 line-height:150%;
571 margin:0 24px 10px;
571 margin:0 24px 10px;
572 padding:0;
572 padding:0;
573 }
573 }
574
574
575 #content div.box blockquote {
575 #content div.box blockquote {
576 border-left:4px solid #DDD;
576 border-left:4px solid #DDD;
577 color:#5f5f5f;
577 color:#5f5f5f;
578 font-size:11px;
578 font-size:11px;
579 line-height:150%;
579 line-height:150%;
580 margin:0 34px;
580 margin:0 34px;
581 padding:0 0 0 14px;
581 padding:0 0 0 14px;
582 }
582 }
583
583
584 #content div.box blockquote p {
584 #content div.box blockquote p {
585 margin:10px 0;
585 margin:10px 0;
586 padding:0;
586 padding:0;
587 }
587 }
588
588
589 #content div.box dl {
589 #content div.box dl {
590 margin:10px 24px;
590 margin:10px 24px;
591 }
591 }
592
592
593 #content div.box dt {
593 #content div.box dt {
594 font-size:12px;
594 font-size:12px;
595 margin:0;
595 margin:0;
596 }
596 }
597
597
598 #content div.box dd {
598 #content div.box dd {
599 font-size:12px;
599 font-size:12px;
600 margin:0;
600 margin:0;
601 padding:8px 0 8px 15px;
601 padding:8px 0 8px 15px;
602 }
602 }
603
603
604 #content div.box li {
604 #content div.box li {
605 font-size:12px;
605 font-size:12px;
606 padding:4px 0;
606 padding:4px 0;
607 }
607 }
608
608
609 #content div.box ul.disc,#content div.box ul.circle {
609 #content div.box ul.disc,#content div.box ul.circle {
610 margin:10px 24px 10px 38px;
610 margin:10px 24px 10px 38px;
611 }
611 }
612
612
613 #content div.box ul.square {
613 #content div.box ul.square {
614 margin:10px 24px 10px 40px;
614 margin:10px 24px 10px 40px;
615 }
615 }
616
616
617 #content div.box img.left {
617 #content div.box img.left {
618 border:none;
618 border:none;
619 float:left;
619 float:left;
620 margin:10px 10px 10px 0;
620 margin:10px 10px 10px 0;
621 }
621 }
622
622
623 #content div.box img.right {
623 #content div.box img.right {
624 border:none;
624 border:none;
625 float:right;
625 float:right;
626 margin:10px 0 10px 10px;
626 margin:10px 0 10px 10px;
627 }
627 }
628
628
629 #content div.box div.messages {
629 #content div.box div.messages {
630 clear:both;
630 clear:both;
631 overflow:hidden;
631 overflow:hidden;
632 margin:0 20px;
632 margin:0 20px;
633 padding:0;
633 padding:0;
634 }
634 }
635
635
636 #content div.box div.message {
636 #content div.box div.message {
637 clear:both;
637 clear:both;
638 overflow:hidden;
638 overflow:hidden;
639 margin:0;
639 margin:0;
640 padding:10px 0;
640 padding:10px 0;
641 }
641 }
642
642
643 #content div.box div.message a {
643 #content div.box div.message a {
644 font-weight:400 !important;
644 font-weight:400 !important;
645 }
645 }
646
646
647 #content div.box div.message div.image {
647 #content div.box div.message div.image {
648 float:left;
648 float:left;
649 margin:9px 0 0 5px;
649 margin:9px 0 0 5px;
650 padding:6px;
650 padding:6px;
651 }
651 }
652
652
653 #content div.box div.message div.image img {
653 #content div.box div.message div.image img {
654 vertical-align:middle;
654 vertical-align:middle;
655 margin:0;
655 margin:0;
656 }
656 }
657
657
658 #content div.box div.message div.text {
658 #content div.box div.message div.text {
659 float:left;
659 float:left;
660 margin:0;
660 margin:0;
661 padding:9px 6px;
661 padding:9px 6px;
662 }
662 }
663
663
664 #content div.box div.message div.dismiss a {
664 #content div.box div.message div.dismiss a {
665 height:16px;
665 height:16px;
666 width:16px;
666 width:16px;
667 display:block;
667 display:block;
668 background:url("../images/icons/cross.png") no-repeat;
668 background:url("../images/icons/cross.png") no-repeat;
669 margin:15px 14px 0 0;
669 margin:15px 14px 0 0;
670 padding:0;
670 padding:0;
671 }
671 }
672
672
673 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 {
673 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 {
674 border:none;
674 border:none;
675 margin:0;
675 margin:0;
676 padding:0;
676 padding:0;
677 }
677 }
678
678
679 #content div.box div.message div.text span {
679 #content div.box div.message div.text span {
680 height:1%;
680 height:1%;
681 display:block;
681 display:block;
682 margin:0;
682 margin:0;
683 padding:5px 0 0;
683 padding:5px 0 0;
684 }
684 }
685
685
686 #content div.box div.message-error {
686 #content div.box div.message-error {
687 height:1%;
687 height:1%;
688 clear:both;
688 clear:both;
689 overflow:hidden;
689 overflow:hidden;
690 background:#FBE3E4;
690 background:#FBE3E4;
691 border:1px solid #FBC2C4;
691 border:1px solid #FBC2C4;
692 color:#860006;
692 color:#860006;
693 }
693 }
694
694
695 #content div.box div.message-error h6 {
695 #content div.box div.message-error h6 {
696 color:#860006;
696 color:#860006;
697 }
697 }
698
698
699 #content div.box div.message-warning {
699 #content div.box div.message-warning {
700 height:1%;
700 height:1%;
701 clear:both;
701 clear:both;
702 overflow:hidden;
702 overflow:hidden;
703 background:#FFF6BF;
703 background:#FFF6BF;
704 border:1px solid #FFD324;
704 border:1px solid #FFD324;
705 color:#5f5200;
705 color:#5f5200;
706 }
706 }
707
707
708 #content div.box div.message-warning h6 {
708 #content div.box div.message-warning h6 {
709 color:#5f5200;
709 color:#5f5200;
710 }
710 }
711
711
712 #content div.box div.message-notice {
712 #content div.box div.message-notice {
713 height:1%;
713 height:1%;
714 clear:both;
714 clear:both;
715 overflow:hidden;
715 overflow:hidden;
716 background:#8FBDE0;
716 background:#8FBDE0;
717 border:1px solid #6BACDE;
717 border:1px solid #6BACDE;
718 color:#003863;
718 color:#003863;
719 }
719 }
720
720
721 #content div.box div.message-notice h6 {
721 #content div.box div.message-notice h6 {
722 color:#003863;
722 color:#003863;
723 }
723 }
724
724
725 #content div.box div.message-success {
725 #content div.box div.message-success {
726 height:1%;
726 height:1%;
727 clear:both;
727 clear:both;
728 overflow:hidden;
728 overflow:hidden;
729 background:#E6EFC2;
729 background:#E6EFC2;
730 border:1px solid #C6D880;
730 border:1px solid #C6D880;
731 color:#4e6100;
731 color:#4e6100;
732 }
732 }
733
733
734 #content div.box div.message-success h6 {
734 #content div.box div.message-success h6 {
735 color:#4e6100;
735 color:#4e6100;
736 }
736 }
737
737
738 #content div.box div.form div.fields div.field {
738 #content div.box div.form div.fields div.field {
739 height:1%;
739 height:1%;
740 border-bottom:1px solid #DDD;
740 border-bottom:1px solid #DDD;
741 clear:both;
741 clear:both;
742 margin:0;
742 margin:0;
743 padding:10px 0;
743 padding:10px 0;
744 }
744 }
745
745
746 #content div.box div.form div.fields div.field-first {
746 #content div.box div.form div.fields div.field-first {
747 padding:0 0 10px;
747 padding:0 0 10px;
748 }
748 }
749
749
750 #content div.box div.form div.fields div.field-noborder {
750 #content div.box div.form div.fields div.field-noborder {
751 border-bottom:0 !important;
751 border-bottom:0 !important;
752 }
752 }
753
753
754 #content div.box div.form div.fields div.field span.error-message {
754 #content div.box div.form div.fields div.field span.error-message {
755 height:1%;
755 height:1%;
756 display:inline-block;
756 display:inline-block;
757 color:red;
757 color:red;
758 margin:8px 0 0 4px;
758 margin:8px 0 0 4px;
759 padding:0;
759 padding:0;
760 }
760 }
761
761
762 #content div.box div.form div.fields div.field span.success {
762 #content div.box div.form div.fields div.field span.success {
763 height:1%;
763 height:1%;
764 display:block;
764 display:block;
765 color:#316309;
765 color:#316309;
766 margin:8px 0 0;
766 margin:8px 0 0;
767 padding:0;
767 padding:0;
768 }
768 }
769
769
770 #content div.box div.form div.fields div.field div.label {
770 #content div.box div.form div.fields div.field div.label {
771 left:80px;
771 left:80px;
772 width:auto;
772 width:auto;
773 position:absolute;
773 position:absolute;
774 margin:0;
774 margin:0;
775 padding:8px 0 0 5px;
775 padding:8px 0 0 5px;
776 }
776 }
777
777
778 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
778 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
779 clear:both;
779 clear:both;
780 overflow:hidden;
780 overflow:hidden;
781 left:0;
781 left:0;
782 width:auto;
782 width:auto;
783 position:relative;
783 position:relative;
784 margin:0;
784 margin:0;
785 padding:0 0 8px;
785 padding:0 0 8px;
786 }
786 }
787
787
788 #content div.box div.form div.fields div.field div.label-select {
788 #content div.box div.form div.fields div.field div.label-select {
789 padding:2px 0 0 5px;
789 padding:2px 0 0 5px;
790 }
790 }
791
791
792 #content div.box-left div.form div.fields div.field div.label-select,#content div.box-right div.form div.fields div.field div.label-select {
792 #content div.box-left div.form div.fields div.field div.label-select,#content div.box-right div.form div.fields div.field div.label-select {
793 padding:0 0 8px;
793 padding:0 0 8px;
794 }
794 }
795
795
796 #content div.box-left div.form div.fields div.field div.label-textarea,#content div.box-right div.form div.fields div.field div.label-textarea {
796 #content div.box-left div.form div.fields div.field div.label-textarea,#content div.box-right div.form div.fields div.field div.label-textarea {
797 padding:0 0 8px !important;
797 padding:0 0 8px !important;
798 }
798 }
799
799
800 #content div.box div.form div.fields div.field div.label label {
800 #content div.box div.form div.fields div.field div.label label {
801 color:#393939;
801 color:#393939;
802 font-weight:700;
802 font-weight:700;
803 }
803 }
804
804
805 #content div.box div.form div.fields div.field div.input {
805 #content div.box div.form div.fields div.field div.input {
806 margin:0 0 0 200px;
806 margin:0 0 0 200px;
807 }
807 }
808
808
809 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
809 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
810 clear:both;
810 clear:both;
811 overflow:hidden;
811 overflow:hidden;
812 border-top:1px solid #b3b3b3;
812 border-top:1px solid #b3b3b3;
813 border-left:1px solid #b3b3b3;
813 border-left:1px solid #b3b3b3;
814 border-right:1px solid #eaeaea;
814 border-right:1px solid #eaeaea;
815 border-bottom:1px solid #eaeaea;
815 border-bottom:1px solid #eaeaea;
816 margin:0;
816 margin:0;
817 padding:7px 7px 6px;
817 padding:7px 7px 6px;
818 }
818 }
819
819
820 #content div.box div.form div.fields div.field div.input input {
820 #content div.box div.form div.fields div.field div.input input {
821 background:#FFF;
821 background:#FFF;
822 border-top:1px solid #b3b3b3;
822 border-top:1px solid #b3b3b3;
823 border-left:1px solid #b3b3b3;
823 border-left:1px solid #b3b3b3;
824 border-right:1px solid #eaeaea;
824 border-right:1px solid #eaeaea;
825 border-bottom:1px solid #eaeaea;
825 border-bottom:1px solid #eaeaea;
826 color:#000;
826 color:#000;
827 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
827 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
828 font-size:11px;
828 font-size:11px;
829 margin:0;
829 margin:0;
830 padding:7px 7px 6px;
830 padding:7px 7px 6px;
831 }
831 }
832
832
833 #content div.box-left div.form div.fields div.field div.input input,#content div.box-right div.form div.fields div.field div.input input {
833 #content div.box-left div.form div.fields div.field div.input input,#content div.box-right div.form div.fields div.field div.input input {
834 width:100%;
834 width:100%;
835 border:none;
835 border:none;
836 padding:0;
836 padding:0;
837 }
837 }
838
838
839 #content div.box div.form div.fields div.field div.input input.small {
839 #content div.box div.form div.fields div.field div.input input.small {
840 width:30%;
840 width:30%;
841 }
841 }
842
842
843 #content div.box div.form div.fields div.field div.input input.medium {
843 #content div.box div.form div.fields div.field div.input input.medium {
844 width:55%;
844 width:55%;
845 }
845 }
846
846
847 #content div.box div.form div.fields div.field div.input input.large {
847 #content div.box div.form div.fields div.field div.input input.large {
848 width:85%;
848 width:85%;
849 }
849 }
850
850
851 #content div.box div.form div.fields div.field div.input input.date {
851 #content div.box div.form div.fields div.field div.input input.date {
852 width:177px;
852 width:177px;
853 }
853 }
854
854
855 #content div.box div.form div.fields div.field div.input input.button {
855 #content div.box div.form div.fields div.field div.input input.button {
856 background:#D4D0C8;
856 background:#D4D0C8;
857 border-top:1px solid #FFF;
857 border-top:1px solid #FFF;
858 border-left:1px solid #FFF;
858 border-left:1px solid #FFF;
859 border-right:1px solid #404040;
859 border-right:1px solid #404040;
860 border-bottom:1px solid #404040;
860 border-bottom:1px solid #404040;
861 color:#000;
861 color:#000;
862 margin:0;
862 margin:0;
863 padding:4px 8px;
863 padding:4px 8px;
864 }
864 }
865
865
866 #content div.box div.form div.fields div.field div.input a.ui-input-file {
866 #content div.box div.form div.fields div.field div.input a.ui-input-file {
867 width:28px;
867 width:28px;
868 height:28px;
868 height:28px;
869 display:inline;
869 display:inline;
870 position:absolute;
870 position:absolute;
871 overflow:hidden;
871 overflow:hidden;
872 cursor:pointer;
872 cursor:pointer;
873 background:#e5e3e3 url("../images/button_browse.png") no-repeat;
873 background:#e5e3e3 url("../images/button_browse.png") no-repeat;
874 border:none;
874 border:none;
875 text-decoration:none;
875 text-decoration:none;
876 margin:0 0 0 6px;
876 margin:0 0 0 6px;
877 padding:0;
877 padding:0;
878 }
878 }
879
879
880 #content div.box div.form div.fields div.field div.textarea {
880 #content div.box div.form div.fields div.field div.textarea {
881 border-top:1px solid #b3b3b3;
881 border-top:1px solid #b3b3b3;
882 border-left:1px solid #b3b3b3;
882 border-left:1px solid #b3b3b3;
883 border-right:1px solid #eaeaea;
883 border-right:1px solid #eaeaea;
884 border-bottom:1px solid #eaeaea;
884 border-bottom:1px solid #eaeaea;
885 margin:0 0 0 200px;
885 margin:0 0 0 200px;
886 padding:10px;
886 padding:10px;
887 }
887 }
888
888
889 #content div.box div.form div.fields div.field div.textarea-editor {
889 #content div.box div.form div.fields div.field div.textarea-editor {
890 border:1px solid #ddd;
890 border:1px solid #ddd;
891 padding:0;
891 padding:0;
892 }
892 }
893
893
894 #content div.box div.form div.fields div.field div.textarea textarea {
894 #content div.box div.form div.fields div.field div.textarea textarea {
895 width:100%;
895 width:100%;
896 height:220px;
896 height:220px;
897 overflow:hidden;
897 overflow:hidden;
898 background:#FFF;
898 background:#FFF;
899 color:#000;
899 color:#000;
900 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
900 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
901 font-size:11px;
901 font-size:11px;
902 outline:none;
902 outline:none;
903 border-width:0;
903 border-width:0;
904 margin:0;
904 margin:0;
905 padding:0;
905 padding:0;
906 }
906 }
907
907
908 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea {
908 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea {
909 width:100%;
909 width:100%;
910 height:100px;
910 height:100px;
911 }
911 }
912
912
913 #content div.box div.form div.fields div.field div.textarea table {
913 #content div.box div.form div.fields div.field div.textarea table {
914 width:100%;
914 width:100%;
915 border:none;
915 border:none;
916 margin:0;
916 margin:0;
917 padding:0;
917 padding:0;
918 }
918 }
919
919
920 #content div.box div.form div.fields div.field div.textarea table td {
920 #content div.box div.form div.fields div.field div.textarea table td {
921 background:#DDD;
921 background:#DDD;
922 border:none;
922 border:none;
923 padding:0;
923 padding:0;
924 }
924 }
925
925
926 #content div.box div.form div.fields div.field div.textarea table td table {
926 #content div.box div.form div.fields div.field div.textarea table td table {
927 width:auto;
927 width:auto;
928 border:none;
928 border:none;
929 margin:0;
929 margin:0;
930 padding:0;
930 padding:0;
931 }
931 }
932
932
933 #content div.box div.form div.fields div.field div.textarea table td table td {
933 #content div.box div.form div.fields div.field div.textarea table td table td {
934 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
934 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
935 font-size:11px;
935 font-size:11px;
936 padding:5px 5px 5px 0;
936 padding:5px 5px 5px 0;
937 }
937 }
938
938
939 #content div.box div.form div.fields div.field div.textarea table td table td a.mceButtonActive {
939 #content div.box div.form div.fields div.field div.textarea table td table td a.mceButtonActive {
940 background:#b1b1b1;
940 background:#b1b1b1;
941 }
941 }
942
942
943 #content div.box div.form div.fields div.field div.select a.ui-selectmenu {
943 #content div.box div.form div.fields div.field div.select a.ui-selectmenu {
944 color:#565656;
944 color:#565656;
945 text-decoration:none;
945 text-decoration:none;
946 }
946 }
947
947
948 #content div.box div.form div.fields div.field input[type=text]:focus,#content div.box div.form div.fields div.field input[type=password]:focus,#content div.box div.form div.fields div.field input[type=file]:focus,#content div.box div.form div.fields div.field textarea:focus,#content div.box div.form div.fields div.field select:focus {
948 #content div.box div.form div.fields div.field input[type=text]:focus,#content div.box div.form div.fields div.field input[type=password]:focus,#content div.box div.form div.fields div.field input[type=file]:focus,#content div.box div.form div.fields div.field textarea:focus,#content div.box div.form div.fields div.field select:focus {
949 background:#f6f6f6;
949 background:#f6f6f6;
950 border-color:#666;
950 border-color:#666;
951 }
951 }
952
952
953 div.form div.fields div.field div.button {
953 div.form div.fields div.field div.button {
954 margin:0;
954 margin:0;
955 padding:0 0 0 8px;
955 padding:0 0 0 8px;
956 }
956 }
957
957
958 div.form div.fields div.field div.highlight .ui-state-default {
958 div.form div.fields div.field div.highlight .ui-state-default {
959 background:#4e85bb url("../images/button_highlight.png") repeat-x;
959 background:#4e85bb url("../images/button_highlight.png") repeat-x;
960 border-top:1px solid #5c91a4;
960 border-top:1px solid #5c91a4;
961 border-left:1px solid #2a6f89;
961 border-left:1px solid #2a6f89;
962 border-right:1px solid #2b7089;
962 border-right:1px solid #2b7089;
963 border-bottom:1px solid #1a6480;
963 border-bottom:1px solid #1a6480;
964 color:#FFF;
964 color:#FFF;
965 margin:0;
965 margin:0;
966 padding:6px 12px;
966 padding:6px 12px;
967 }
967 }
968
968
969 div.form div.fields div.field div.highlight .ui-state-hover {
969 div.form div.fields div.field div.highlight .ui-state-hover {
970 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
970 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
971 border-top:1px solid #78acbf;
971 border-top:1px solid #78acbf;
972 border-left:1px solid #34819e;
972 border-left:1px solid #34819e;
973 border-right:1px solid #35829f;
973 border-right:1px solid #35829f;
974 border-bottom:1px solid #257897;
974 border-bottom:1px solid #257897;
975 color:#FFF;
975 color:#FFF;
976 margin:0;
976 margin:0;
977 padding:6px 12px;
977 padding:6px 12px;
978 }
978 }
979
979
980 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-default {
980 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-default {
981 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
981 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
982 border-top:1px solid #5c91a4;
982 border-top:1px solid #5c91a4;
983 border-left:1px solid #2a6f89;
983 border-left:1px solid #2a6f89;
984 border-right:1px solid #2b7089;
984 border-right:1px solid #2b7089;
985 border-bottom:1px solid #1a6480;
985 border-bottom:1px solid #1a6480;
986 color:#fff;
986 color:#fff;
987 margin:0;
987 margin:0;
988 padding:6px 12px;
988 padding:6px 12px;
989 }
989 }
990
990
991 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
991 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
992 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
992 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
993 border-top:1px solid #78acbf;
993 border-top:1px solid #78acbf;
994 border-left:1px solid #34819e;
994 border-left:1px solid #34819e;
995 border-right:1px solid #35829f;
995 border-right:1px solid #35829f;
996 border-bottom:1px solid #257897;
996 border-bottom:1px solid #257897;
997 color:#fff;
997 color:#fff;
998 margin:0;
998 margin:0;
999 padding:6px 12px;
999 padding:6px 12px;
1000 }
1000 }
1001
1001
1002 #content div.box table {
1002 #content div.box table {
1003 width:100%;
1003 width:100%;
1004 border-collapse:collapse;
1004 border-collapse:collapse;
1005 margin:0;
1005 margin:0;
1006 padding:0;
1006 padding:0;
1007 }
1007 }
1008
1008
1009 #content div.box table th {
1009 #content div.box table th {
1010 background:#eee;
1010 background:#eee;
1011 border-bottom:1px solid #ddd;
1011 border-bottom:1px solid #ddd;
1012 padding:5px 0px 5px 5px;
1012 padding:5px 0px 5px 5px;
1013 }
1013 }
1014
1014
1015 #content div.box table th.left {
1015 #content div.box table th.left {
1016 text-align:left;
1016 text-align:left;
1017 }
1017 }
1018
1018
1019 #content div.box table th.right {
1019 #content div.box table th.right {
1020 text-align:right;
1020 text-align:right;
1021 }
1021 }
1022
1022
1023 #content div.box table th.center {
1023 #content div.box table th.center {
1024 text-align:center;
1024 text-align:center;
1025 }
1025 }
1026
1026
1027 #content div.box table th.selected {
1027 #content div.box table th.selected {
1028 vertical-align:middle;
1028 vertical-align:middle;
1029 padding:0;
1029 padding:0;
1030 }
1030 }
1031
1031
1032 #content div.box table td {
1032 #content div.box table td {
1033 background:#fff;
1033 background:#fff;
1034 border-bottom:1px solid #cdcdcd;
1034 border-bottom:1px solid #cdcdcd;
1035 vertical-align:middle;
1035 vertical-align:middle;
1036 padding:5px;
1036 padding:5px;
1037 }
1037 }
1038
1038
1039 #content div.box table tr.selected td {
1039 #content div.box table tr.selected td {
1040 background:#FFC;
1040 background:#FFC;
1041 }
1041 }
1042
1042
1043 #content div.box table td.selected {
1043 #content div.box table td.selected {
1044 width:3%;
1044 width:3%;
1045 text-align:center;
1045 text-align:center;
1046 vertical-align:middle;
1046 vertical-align:middle;
1047 padding:0;
1047 padding:0;
1048 }
1048 }
1049
1049
1050 #content div.box table td.action {
1050 #content div.box table td.action {
1051 width:45%;
1051 width:45%;
1052 text-align:left;
1052 text-align:left;
1053 }
1053 }
1054
1054
1055 #content div.box table td.date {
1055 #content div.box table td.date {
1056 width:33%;
1056 width:33%;
1057 text-align:center;
1057 text-align:center;
1058 }
1058 }
1059
1059
1060 #content div.box div.action {
1060 #content div.box div.action {
1061 float:right;
1061 float:right;
1062 background:#FFF;
1062 background:#FFF;
1063 text-align:right;
1063 text-align:right;
1064 margin:10px 0 0;
1064 margin:10px 0 0;
1065 padding:0;
1065 padding:0;
1066 }
1066 }
1067
1067
1068 #content div.box div.action select {
1068 #content div.box div.action select {
1069 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1069 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1070 font-size:11px;
1070 font-size:11px;
1071 margin:0;
1071 margin:0;
1072 }
1072 }
1073
1073
1074 #content div.box div.action .ui-selectmenu {
1074 #content div.box div.action .ui-selectmenu {
1075 margin:0;
1075 margin:0;
1076 padding:0;
1076 padding:0;
1077 }
1077 }
1078
1078
1079 #content div.box div.pagination {
1079 #content div.box div.pagination {
1080 height:1%;
1080 height:1%;
1081 clear:both;
1081 clear:both;
1082 overflow:hidden;
1082 overflow:hidden;
1083 margin:10px 0 0;
1083 margin:10px 0 0;
1084 padding:0;
1084 padding:0;
1085 }
1085 }
1086
1086
1087 #content div.box div.pagination ul.pager {
1087 #content div.box div.pagination ul.pager {
1088 float:right;
1088 float:right;
1089 text-align:right;
1089 text-align:right;
1090 margin:0;
1090 margin:0;
1091 padding:0;
1091 padding:0;
1092 }
1092 }
1093
1093
1094 #content div.box div.pagination ul.pager li {
1094 #content div.box div.pagination ul.pager li {
1095 height:1%;
1095 height:1%;
1096 float:left;
1096 float:left;
1097 list-style:none;
1097 list-style:none;
1098 background:#ebebeb url("../images/pager.png") repeat-x;
1098 background:#ebebeb url("../images/pager.png") repeat-x;
1099 border-top:1px solid #dedede;
1099 border-top:1px solid #dedede;
1100 border-left:1px solid #cfcfcf;
1100 border-left:1px solid #cfcfcf;
1101 border-right:1px solid #c4c4c4;
1101 border-right:1px solid #c4c4c4;
1102 border-bottom:1px solid #c4c4c4;
1102 border-bottom:1px solid #c4c4c4;
1103 color:#4A4A4A;
1103 color:#4A4A4A;
1104 font-weight:700;
1104 font-weight:700;
1105 margin:0 0 0 4px;
1105 margin:0 0 0 4px;
1106 padding:0;
1106 padding:0;
1107 }
1107 }
1108
1108
1109 #content div.box div.pagination ul.pager li.separator {
1109 #content div.box div.pagination ul.pager li.separator {
1110 padding:6px;
1110 padding:6px;
1111 }
1111 }
1112
1112
1113 #content div.box div.pagination ul.pager li.current {
1113 #content div.box div.pagination ul.pager li.current {
1114 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1114 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1115 border-top:1px solid #ccc;
1115 border-top:1px solid #ccc;
1116 border-left:1px solid #bebebe;
1116 border-left:1px solid #bebebe;
1117 border-right:1px solid #b1b1b1;
1117 border-right:1px solid #b1b1b1;
1118 border-bottom:1px solid #afafaf;
1118 border-bottom:1px solid #afafaf;
1119 color:#515151;
1119 color:#515151;
1120 padding:6px;
1120 padding:6px;
1121 }
1121 }
1122
1122
1123 #content div.box div.pagination ul.pager li a {
1123 #content div.box div.pagination ul.pager li a {
1124 height:1%;
1124 height:1%;
1125 display:block;
1125 display:block;
1126 float:left;
1126 float:left;
1127 color:#515151;
1127 color:#515151;
1128 text-decoration:none;
1128 text-decoration:none;
1129 margin:0;
1129 margin:0;
1130 padding:6px;
1130 padding:6px;
1131 }
1131 }
1132
1132
1133 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1133 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1134 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1134 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1135 border-top:1px solid #ccc;
1135 border-top:1px solid #ccc;
1136 border-left:1px solid #bebebe;
1136 border-left:1px solid #bebebe;
1137 border-right:1px solid #b1b1b1;
1137 border-right:1px solid #b1b1b1;
1138 border-bottom:1px solid #afafaf;
1138 border-bottom:1px solid #afafaf;
1139 margin:-1px;
1139 margin:-1px;
1140 }
1140 }
1141
1141
1142 #content div.box div.pagination-wh {
1142 #content div.box div.pagination-wh {
1143 height:1%;
1143 height:1%;
1144 clear:both;
1144 clear:both;
1145 overflow:hidden;
1145 overflow:hidden;
1146 text-align:right;
1146 text-align:right;
1147 margin:10px 0 0;
1147 margin:10px 0 0;
1148 padding:0;
1148 padding:0;
1149 }
1149 }
1150
1150
1151 #content div.box div.pagination-right {
1151 #content div.box div.pagination-right {
1152 float:right;
1152 float:right;
1153 }
1153 }
1154
1154
1155 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1155 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1156 height:1%;
1156 height:1%;
1157 float:left;
1157 float:left;
1158 background:#ebebeb url("../images/pager.png") repeat-x;
1158 background:#ebebeb url("../images/pager.png") repeat-x;
1159 border-top:1px solid #dedede;
1159 border-top:1px solid #dedede;
1160 border-left:1px solid #cfcfcf;
1160 border-left:1px solid #cfcfcf;
1161 border-right:1px solid #c4c4c4;
1161 border-right:1px solid #c4c4c4;
1162 border-bottom:1px solid #c4c4c4;
1162 border-bottom:1px solid #c4c4c4;
1163 color:#4A4A4A;
1163 color:#4A4A4A;
1164 font-weight:700;
1164 font-weight:700;
1165 margin:0 0 0 4px;
1165 margin:0 0 0 4px;
1166 padding:6px;
1166 padding:6px;
1167 }
1167 }
1168
1168
1169 #content div.box div.pagination-wh span.pager_curpage {
1169 #content div.box div.pagination-wh span.pager_curpage {
1170 height:1%;
1170 height:1%;
1171 float:left;
1171 float:left;
1172 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1172 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1173 border-top:1px solid #ccc;
1173 border-top:1px solid #ccc;
1174 border-left:1px solid #bebebe;
1174 border-left:1px solid #bebebe;
1175 border-right:1px solid #b1b1b1;
1175 border-right:1px solid #b1b1b1;
1176 border-bottom:1px solid #afafaf;
1176 border-bottom:1px solid #afafaf;
1177 color:#515151;
1177 color:#515151;
1178 font-weight:700;
1178 font-weight:700;
1179 margin:0 0 0 4px;
1179 margin:0 0 0 4px;
1180 padding:6px;
1180 padding:6px;
1181 }
1181 }
1182
1182
1183 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1183 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1184 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1184 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1185 border-top:1px solid #ccc;
1185 border-top:1px solid #ccc;
1186 border-left:1px solid #bebebe;
1186 border-left:1px solid #bebebe;
1187 border-right:1px solid #b1b1b1;
1187 border-right:1px solid #b1b1b1;
1188 border-bottom:1px solid #afafaf;
1188 border-bottom:1px solid #afafaf;
1189 text-decoration:none;
1189 text-decoration:none;
1190 }
1190 }
1191
1191
1192 #content div.box div.traffic div.legend {
1192 #content div.box div.traffic div.legend {
1193 clear:both;
1193 clear:both;
1194 overflow:hidden;
1194 overflow:hidden;
1195 border-bottom:1px solid #ddd;
1195 border-bottom:1px solid #ddd;
1196 margin:0 0 10px;
1196 margin:0 0 10px;
1197 padding:0 0 10px;
1197 padding:0 0 10px;
1198 }
1198 }
1199
1199
1200 #content div.box div.traffic div.legend h6 {
1200 #content div.box div.traffic div.legend h6 {
1201 float:left;
1201 float:left;
1202 border:none;
1202 border:none;
1203 margin:0;
1203 margin:0;
1204 padding:0;
1204 padding:0;
1205 }
1205 }
1206
1206
1207 #content div.box div.traffic div.legend li {
1207 #content div.box div.traffic div.legend li {
1208 list-style:none;
1208 list-style:none;
1209 float:left;
1209 float:left;
1210 font-size:11px;
1210 font-size:11px;
1211 margin:0;
1211 margin:0;
1212 padding:0 8px 0 4px;
1212 padding:0 8px 0 4px;
1213 }
1213 }
1214
1214
1215 #content div.box div.traffic div.legend li.visits {
1215 #content div.box div.traffic div.legend li.visits {
1216 border-left:12px solid #edc240;
1216 border-left:12px solid #edc240;
1217 }
1217 }
1218
1218
1219 #content div.box div.traffic div.legend li.pageviews {
1219 #content div.box div.traffic div.legend li.pageviews {
1220 border-left:12px solid #afd8f8;
1220 border-left:12px solid #afd8f8;
1221 }
1221 }
1222
1222
1223 #content div.box div.traffic table {
1223 #content div.box div.traffic table {
1224 width:auto;
1224 width:auto;
1225 }
1225 }
1226
1226
1227 #content div.box div.traffic table td {
1227 #content div.box div.traffic table td {
1228 background:transparent;
1228 background:transparent;
1229 border:none;
1229 border:none;
1230 padding:2px 3px 3px;
1230 padding:2px 3px 3px;
1231 }
1231 }
1232
1232
1233 #content div.box div.traffic table td.legendLabel {
1233 #content div.box div.traffic table td.legendLabel {
1234 padding:0 3px 2px;
1234 padding:0 3px 2px;
1235 }
1235 }
1236
1236
1237 #footer {
1237 #footer {
1238 clear:both;
1238 clear:both;
1239 overflow:hidden;
1239 overflow:hidden;
1240 text-align:right;
1240 text-align:right;
1241 margin:0;
1241 margin:0;
1242 padding:0 30px 4px;
1242 padding:0 30px 4px;
1243 margin:-10px 0 0;
1243 margin:-10px 0 0;
1244 }
1244 }
1245
1245
1246 #footer div#footer-inner {
1246 #footer div#footer-inner {
1247 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1247 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1248 border-top:2px solid #FFFFFF;
1248 border-top:2px solid #FFFFFF;
1249 }
1249 }
1250
1250
1251 #footer div#footer-inner p {
1251 #footer div#footer-inner p {
1252 padding:15px 25px 15px 0;
1252 padding:15px 25px 15px 0;
1253 color:#FFF;
1253 color:#FFF;
1254 font-weight:700;
1254 font-weight:700;
1255 }
1255 }
1256 #footer div#footer-inner .footer-link {
1256 #footer div#footer-inner .footer-link {
1257 float:left;
1257 float:left;
1258 padding-left:10px;
1258 padding-left:10px;
1259 }
1259 }
1260 #footer div#footer-inner .footer-link a {
1260 #footer div#footer-inner .footer-link a {
1261 color:#FFF;
1261 color:#FFF;
1262 }
1262 }
1263
1263
1264 #login div.title {
1264 #login div.title {
1265 width:420px;
1265 width:420px;
1266 clear:both;
1266 clear:both;
1267 overflow:hidden;
1267 overflow:hidden;
1268 position:relative;
1268 position:relative;
1269 background:#003367 url("../../images/header_inner.png") repeat-x;
1269 background:#003367 url("../../images/header_inner.png") repeat-x;
1270 margin:0 auto;
1270 margin:0 auto;
1271 padding:0;
1271 padding:0;
1272 }
1272 }
1273
1273
1274 #login div.inner {
1274 #login div.inner {
1275 width:380px;
1275 width:380px;
1276 background:#FFF url("../images/login.png") no-repeat top left;
1276 background:#FFF url("../images/login.png") no-repeat top left;
1277 border-top:none;
1277 border-top:none;
1278 border-bottom:none;
1278 border-bottom:none;
1279 margin:0 auto;
1279 margin:0 auto;
1280 padding:20px;
1280 padding:20px;
1281 }
1281 }
1282
1282
1283 #login div.form div.fields div.field div.label {
1283 #login div.form div.fields div.field div.label {
1284 width:173px;
1284 width:173px;
1285 float:left;
1285 float:left;
1286 text-align:right;
1286 text-align:right;
1287 margin:2px 10px 0 0;
1287 margin:2px 10px 0 0;
1288 padding:5px 0 0 5px;
1288 padding:5px 0 0 5px;
1289 }
1289 }
1290
1290
1291 #login div.form div.fields div.field div.input input {
1291 #login div.form div.fields div.field div.input input {
1292 width:176px;
1292 width:176px;
1293 background:#FFF;
1293 background:#FFF;
1294 border-top:1px solid #b3b3b3;
1294 border-top:1px solid #b3b3b3;
1295 border-left:1px solid #b3b3b3;
1295 border-left:1px solid #b3b3b3;
1296 border-right:1px solid #eaeaea;
1296 border-right:1px solid #eaeaea;
1297 border-bottom:1px solid #eaeaea;
1297 border-bottom:1px solid #eaeaea;
1298 color:#000;
1298 color:#000;
1299 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1299 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1300 font-size:11px;
1300 font-size:11px;
1301 margin:0;
1301 margin:0;
1302 padding:7px 7px 6px;
1302 padding:7px 7px 6px;
1303 }
1303 }
1304
1304
1305 #login div.form div.fields div.buttons {
1305 #login div.form div.fields div.buttons {
1306 clear:both;
1306 clear:both;
1307 overflow:hidden;
1307 overflow:hidden;
1308 border-top:1px solid #DDD;
1308 border-top:1px solid #DDD;
1309 text-align:right;
1309 text-align:right;
1310 margin:0;
1310 margin:0;
1311 padding:10px 0 0;
1311 padding:10px 0 0;
1312 }
1312 }
1313
1313
1314 #login div.form div.links {
1314 #login div.form div.links {
1315 clear:both;
1315 clear:both;
1316 overflow:hidden;
1316 overflow:hidden;
1317 margin:10px 0 0;
1317 margin:10px 0 0;
1318 padding:0 0 2px;
1318 padding:0 0 2px;
1319 }
1319 }
1320
1320
1321 #register div.title {
1321 #register div.title {
1322 width:420px;
1322 width:420px;
1323 clear:both;
1323 clear:both;
1324 overflow:hidden;
1324 overflow:hidden;
1325 position:relative;
1325 position:relative;
1326 background:#003367 url("../images/header_inner.png") repeat-x;
1326 background:#003367 url("../images/header_inner.png") repeat-x;
1327 margin:0 auto;
1327 margin:0 auto;
1328 padding:0;
1328 padding:0;
1329 }
1329 }
1330
1330
1331 #register div.inner {
1331 #register div.inner {
1332 width:380px;
1332 width:380px;
1333 background:#FFF;
1333 background:#FFF;
1334 border-top:none;
1334 border-top:none;
1335 border-bottom:none;
1335 border-bottom:none;
1336 margin:0 auto;
1336 margin:0 auto;
1337 padding:20px;
1337 padding:20px;
1338 }
1338 }
1339
1339
1340 #register div.form div.fields div.field div.label {
1340 #register div.form div.fields div.field div.label {
1341 width:100px;
1341 width:100px;
1342 float:left;
1342 float:left;
1343 text-align:right;
1343 text-align:right;
1344 margin:2px 10px 0 0;
1344 margin:2px 10px 0 0;
1345 padding:5px 0 0 5px;
1345 padding:5px 0 0 5px;
1346 }
1346 }
1347
1347
1348 #register div.form div.fields div.field div.input input {
1348 #register div.form div.fields div.field div.input input {
1349 width:245px;
1349 width:245px;
1350 background:#FFF;
1350 background:#FFF;
1351 border-top:1px solid #b3b3b3;
1351 border-top:1px solid #b3b3b3;
1352 border-left:1px solid #b3b3b3;
1352 border-left:1px solid #b3b3b3;
1353 border-right:1px solid #eaeaea;
1353 border-right:1px solid #eaeaea;
1354 border-bottom:1px solid #eaeaea;
1354 border-bottom:1px solid #eaeaea;
1355 color:#000;
1355 color:#000;
1356 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1356 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1357 font-size:11px;
1357 font-size:11px;
1358 margin:0;
1358 margin:0;
1359 padding:7px 7px 6px;
1359 padding:7px 7px 6px;
1360 }
1360 }
1361
1361
1362 #register div.form div.fields div.buttons {
1362 #register div.form div.fields div.buttons {
1363 clear:both;
1363 clear:both;
1364 overflow:hidden;
1364 overflow:hidden;
1365 border-top:1px solid #DDD;
1365 border-top:1px solid #DDD;
1366 text-align:left;
1366 text-align:left;
1367 margin:0;
1367 margin:0;
1368 padding:10px 0 0 114px;
1368 padding:10px 0 0 114px;
1369 }
1369 }
1370
1370
1371 #register div.form div.fields div.buttons div.highlight input.ui-state-default {
1371 #register div.form div.fields div.buttons div.highlight input.ui-state-default {
1372 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1372 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1373 color:#FFF;
1373 color:#FFF;
1374 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1374 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1375 border-style:solid;
1375 border-style:solid;
1376 border-width:1px;
1376 border-width:1px;
1377 }
1377 }
1378
1378
1379 #register div.form div.activation_msg {
1379 #register div.form div.activation_msg {
1380 padding-top:4px;
1380 padding-top:4px;
1381 padding-bottom:4px;
1381 padding-bottom:4px;
1382 }
1382 }
1383
1383
1384 .trending_language_tbl,.trending_language_tbl td {
1384 .trending_language_tbl,.trending_language_tbl td {
1385 border:0 !important;
1385 border:0 !important;
1386 margin:0 !important;
1386 margin:0 !important;
1387 padding:0 !important;
1387 padding:0 !important;
1388 }
1388 }
1389
1389
1390 .trending_language {
1390 .trending_language {
1391 background-color:#003367;
1391 background-color:#003367;
1392 color:#FFF;
1392 color:#FFF;
1393 display:block;
1393 display:block;
1394 min-width:20px;
1394 min-width:20px;
1395 text-decoration:none;
1395 text-decoration:none;
1396 height:12px;
1396 height:12px;
1397 margin-bottom:4px;
1397 margin-bottom:4px;
1398 margin-left:5px;
1398 margin-left:5px;
1399 white-space:pre;
1399 white-space:pre;
1400 padding:3px;
1400 padding:3px;
1401 }
1401 }
1402
1402
1403 h3.files_location {
1403 h3.files_location {
1404 font-size:1.8em;
1404 font-size:1.8em;
1405 font-weight:700;
1405 font-weight:700;
1406 border-bottom:none !important;
1406 border-bottom:none !important;
1407 margin:10px 0 !important;
1407 margin:10px 0 !important;
1408 }
1408 }
1409
1409
1410 #files_data dl dt {
1410 #files_data dl dt {
1411 float:left;
1411 float:left;
1412 width:115px;
1412 width:115px;
1413 margin:0 !important;
1413 margin:0 !important;
1414 padding:5px;
1414 padding:5px;
1415 }
1415 }
1416
1416
1417 #files_data dl dd {
1417 #files_data dl dd {
1418 margin:0 !important;
1418 margin:0 !important;
1419 padding:5px !important;
1419 padding:5px !important;
1420 }
1420 }
1421
1421
1422 #changeset_content {
1422 #changeset_content {
1423 border:1px solid #CCC;
1423 border:1px solid #CCC;
1424 padding:5px;
1424 padding:5px;
1425 }
1425 }
1426
1426
1427 #changeset_content .container {
1427 #changeset_content .container {
1428 min-height:120px;
1428 min-height:120px;
1429 font-size:1.2em;
1429 font-size:1.2em;
1430 overflow:hidden;
1430 overflow:hidden;
1431 }
1431 }
1432
1432
1433 #changeset_content .container .right {
1433 #changeset_content .container .right {
1434 float:right;
1434 float:right;
1435 width:25%;
1435 width:25%;
1436 text-align:right;
1436 text-align:right;
1437 }
1437 }
1438
1438
1439 #changeset_content .container .left .message {
1439 #changeset_content .container .left .message {
1440 font-style:italic;
1440 font-style:italic;
1441 color:#556CB5;
1441 color:#556CB5;
1442 white-space:pre-wrap;
1442 white-space:pre-wrap;
1443 }
1443 }
1444
1444
1445 .cs_files .cs_added {
1445 .cs_files .cs_added {
1446 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1446 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1447 height:16px;
1447 height:16px;
1448 padding-left:20px;
1448 padding-left:20px;
1449 margin-top:7px;
1449 margin-top:7px;
1450 text-align:left;
1450 text-align:left;
1451 }
1451 }
1452
1452
1453 .cs_files .cs_changed {
1453 .cs_files .cs_changed {
1454 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1454 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1455 height:16px;
1455 height:16px;
1456 padding-left:20px;
1456 padding-left:20px;
1457 margin-top:7px;
1457 margin-top:7px;
1458 text-align:left;
1458 text-align:left;
1459 }
1459 }
1460
1460
1461 .cs_files .cs_removed {
1461 .cs_files .cs_removed {
1462 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1462 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1463 height:16px;
1463 height:16px;
1464 padding-left:20px;
1464 padding-left:20px;
1465 margin-top:7px;
1465 margin-top:7px;
1466 text-align:left;
1466 text-align:left;
1467 }
1467 }
1468
1468
1469 #graph {
1469 #graph {
1470 overflow:hidden;
1470 overflow:hidden;
1471 }
1471 }
1472
1472
1473 #graph_nodes {
1473 #graph_nodes {
1474 width:160px;
1474 width:160px;
1475 float:left;
1475 float:left;
1476 margin-left:-50px;
1476 margin-left:-50px;
1477 margin-top:5px;
1477 margin-top:5px;
1478 }
1478 }
1479
1479
1480 #graph_content {
1480 #graph_content {
1481 width:800px;
1481 width:800px;
1482 float:left;
1482 float:left;
1483 }
1483 }
1484
1484
1485 #graph_content .container_header {
1485 #graph_content .container_header {
1486 border:1px solid #CCC;
1486 border:1px solid #CCC;
1487 padding:10px;
1487 padding:10px;
1488 }
1488 }
1489
1489
1490 #graph_content .container {
1490 #graph_content .container {
1491 border-bottom:1px solid #CCC;
1491 border-bottom:1px solid #CCC;
1492 border-left:1px solid #CCC;
1492 border-left:1px solid #CCC;
1493 border-right:1px solid #CCC;
1493 border-right:1px solid #CCC;
1494 min-height:80px;
1494 min-height:80px;
1495 overflow:hidden;
1495 overflow:hidden;
1496 font-size:1.2em;
1496 font-size:1.2em;
1497 }
1497 }
1498
1498
1499 #graph_content .container .right {
1499 #graph_content .container .right {
1500 float:right;
1500 float:right;
1501 width:28%;
1501 width:28%;
1502 text-align:right;
1502 text-align:right;
1503 padding-bottom:5px;
1503 padding-bottom:5px;
1504 }
1504 }
1505
1505
1506 #graph_content .container .left .date {
1506 #graph_content .container .left .date {
1507 font-weight:700;
1507 font-weight:700;
1508 padding-bottom:5px;
1508 padding-bottom:5px;
1509 }
1509 }
1510
1510
1511 #graph_content .container .left .message {
1511 #graph_content .container .left .message {
1512 font-size:100%;
1512 font-size:100%;
1513 padding-top:3px;
1513 padding-top:3px;
1514 white-space:pre-wrap;
1514 white-space:pre-wrap;
1515 }
1515 }
1516
1516
1517 .right div {
1517 .right div {
1518 clear:both;
1518 clear:both;
1519 }
1519 }
1520
1520
1521 .right .changes .added,.changed,.removed {
1521 .right .changes .added,.changed,.removed {
1522 border:1px solid #DDD;
1522 border:1px solid #DDD;
1523 display:block;
1523 display:block;
1524 float:right;
1524 float:right;
1525 text-align:center;
1525 text-align:center;
1526 min-width:15px;
1526 min-width:15px;
1527 }
1527 }
1528
1528
1529 .right .changes .added {
1529 .right .changes .added {
1530 background:#BFB;
1530 background:#BFB;
1531 }
1531 }
1532
1532
1533 .right .changes .changed {
1533 .right .changes .changed {
1534 background:#FD8;
1534 background:#FD8;
1535 }
1535 }
1536
1536
1537 .right .changes .removed {
1537 .right .changes .removed {
1538 background:#F88;
1538 background:#F88;
1539 }
1539 }
1540
1540
1541 .right .merge {
1541 .right .merge {
1542 vertical-align:top;
1542 vertical-align:top;
1543 font-size:0.75em;
1543 font-size:0.75em;
1544 font-weight:700;
1544 font-weight:700;
1545 }
1545 }
1546
1546
1547 .right .parent {
1547 .right .parent {
1548 font-size:90%;
1548 font-size:90%;
1549 font-family:monospace;
1549 font-family:monospace;
1550 }
1550 }
1551
1551
1552 .right .logtags .branchtag {
1552 .right .logtags .branchtag {
1553 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1553 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1554 display:block;
1554 display:block;
1555 font-size:0.8em;
1555 font-size:0.8em;
1556 padding:11px 16px 0 0;
1556 padding:11px 16px 0 0;
1557 }
1557 }
1558
1558
1559 .right .logtags .tagtag {
1559 .right .logtags .tagtag {
1560 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1560 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1561 display:block;
1561 display:block;
1562 font-size:0.8em;
1562 font-size:0.8em;
1563 padding:11px 16px 0 0;
1563 padding:11px 16px 0 0;
1564 }
1564 }
1565
1565
1566 div.browserblock {
1566 div.browserblock {
1567 overflow:hidden;
1567 overflow:hidden;
1568 border:1px solid #ccc;
1568 border:1px solid #ccc;
1569 background:#f8f8f8;
1569 background:#f8f8f8;
1570 font-size:100%;
1570 font-size:100%;
1571 line-height:125%;
1571 line-height:125%;
1572 padding:0;
1572 padding:0;
1573 }
1573 }
1574
1574
1575 div.browserblock .browser-header {
1575 div.browserblock .browser-header {
1576 border-bottom:1px solid #CCC;
1576 border-bottom:1px solid #CCC;
1577 background:#FFF;
1577 background:#FFF;
1578 color:blue;
1578 color:blue;
1579 padding:10px 0;
1579 padding:10px 0;
1580 }
1580 }
1581
1581
1582 div.browserblock .browser-header span {
1582 div.browserblock .browser-header span {
1583 margin-left:25px;
1583 margin-left:25px;
1584 font-weight:700;
1584 font-weight:700;
1585 }
1585 }
1586
1586
1587 div.browserblock .browser-body {
1587 div.browserblock .browser-body {
1588 background:#EEE;
1588 background:#EEE;
1589 }
1589 }
1590
1590
1591 table.code-browser {
1591 table.code-browser {
1592 border-collapse:collapse;
1592 border-collapse:collapse;
1593 width:100%;
1593 width:100%;
1594 }
1594 }
1595
1595
1596 table.code-browser tr {
1596 table.code-browser tr {
1597 margin:3px;
1597 margin:3px;
1598 }
1598 }
1599
1599
1600 table.code-browser thead th {
1600 table.code-browser thead th {
1601 background-color:#EEE;
1601 background-color:#EEE;
1602 height:20px;
1602 height:20px;
1603 font-size:1.1em;
1603 font-size:1.1em;
1604 font-weight:700;
1604 font-weight:700;
1605 text-align:left;
1605 text-align:left;
1606 padding-left:10px;
1606 padding-left:10px;
1607 }
1607 }
1608
1608
1609 table.code-browser tbody td {
1609 table.code-browser tbody td {
1610 padding-left:10px;
1610 padding-left:10px;
1611 height:20px;
1611 height:20px;
1612 }
1612 }
1613
1613
1614 table.code-browser .browser-file {
1614 table.code-browser .browser-file {
1615 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1615 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1616 height:16px;
1616 height:16px;
1617 padding-left:20px;
1617 padding-left:20px;
1618 text-align:left;
1618 text-align:left;
1619 }
1619 }
1620
1620
1621 table.code-browser .browser-dir {
1621 table.code-browser .browser-dir {
1622 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1622 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1623 height:16px;
1623 height:16px;
1624 padding-left:20px;
1624 padding-left:20px;
1625 text-align:left;
1625 text-align:left;
1626 }
1626 }
1627
1627
1628 .box .search {
1628 .box .search {
1629 clear:both;
1629 clear:both;
1630 overflow:hidden;
1630 overflow:hidden;
1631 margin:0;
1631 margin:0;
1632 padding:0 20px 10px;
1632 padding:0 20px 10px;
1633 }
1633 }
1634
1634
1635 .box .search div.search_path {
1635 .box .search div.search_path {
1636 background:none repeat scroll 0 0 #EEE;
1636 background:none repeat scroll 0 0 #EEE;
1637 border:1px solid #CCC;
1637 border:1px solid #CCC;
1638 color:blue;
1638 color:blue;
1639 margin-bottom:10px;
1639 margin-bottom:10px;
1640 padding:10px 0;
1640 padding:10px 0;
1641 }
1641 }
1642
1642
1643 .box .search div.search_path div.link {
1643 .box .search div.search_path div.link {
1644 font-weight:700;
1644 font-weight:700;
1645 margin-left:25px;
1645 margin-left:25px;
1646 }
1646 }
1647
1647
1648 .box .search div.search_path div.link a {
1648 .box .search div.search_path div.link a {
1649 color:#003367;
1649 color:#003367;
1650 cursor:pointer;
1650 cursor:pointer;
1651 text-decoration:none;
1651 text-decoration:none;
1652 }
1652 }
1653
1653
1654 #path_unlock {
1654 #path_unlock {
1655 color:red;
1655 color:red;
1656 font-size:1.2em;
1656 font-size:1.2em;
1657 padding-left:4px;
1657 padding-left:4px;
1658 }
1658 }
1659
1659
1660 .info_box * {
1660 .info_box * {
1661 background:url("../../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1661 background:url("../../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1662 color:#4A4A4A;
1662 color:#4A4A4A;
1663 font-weight:700;
1663 font-weight:700;
1664 height:1%;
1664 height:1%;
1665 display:inline;
1665 display:inline;
1666 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1666 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1667 border-style:solid;
1667 border-style:solid;
1668 border-width:1px;
1668 border-width:1px;
1669 padding:4px 6px;
1669 padding:4px 6px;
1670 }
1670 }
1671
1671
1672 .info_box span {
1672 .info_box span {
1673 margin-left:3px;
1673 margin-left:3px;
1674 margin-right:3px;
1674 margin-right:3px;
1675 }
1675 }
1676
1676
1677 .info_box input#at_rev {
1677 .info_box input#at_rev {
1678 text-align:center;
1678 text-align:center;
1679 padding:5px 3px 3px 2px;
1679 padding:5px 3px 3px 2px;
1680 }
1680 }
1681
1681
1682 .info_box input#view {
1682 .info_box input#view {
1683 text-align:center;
1683 text-align:center;
1684 padding:4px 3px 2px 2px;
1684 padding:4px 3px 2px 2px;
1685 }
1685 }
1686
1686
1687 .yui-overlay,.yui-panel-container {
1687 .yui-overlay,.yui-panel-container {
1688 visibility:hidden;
1688 visibility:hidden;
1689 position:absolute;
1689 position:absolute;
1690 z-index:2;
1690 z-index:2;
1691 }
1691 }
1692
1692
1693 .yui-tt {
1693 .yui-tt {
1694 visibility:hidden;
1694 visibility:hidden;
1695 position:absolute;
1695 position:absolute;
1696 color:#666;
1696 color:#666;
1697 background-color:#FFF;
1697 background-color:#FFF;
1698 font-family:arial, helvetica, verdana, sans-serif;
1698 font-family:arial, helvetica, verdana, sans-serif;
1699 border:2px solid #003367;
1699 border:2px solid #003367;
1700 font:100% sans-serif;
1700 font:100% sans-serif;
1701 width:auto;
1701 width:auto;
1702 opacity:1px;
1702 opacity:1px;
1703 padding:8px;
1703 padding:8px;
1704 white-space: pre;
1704 white-space: pre;
1705 }
1705 }
1706
1706
1707 .ac {
1707 .ac {
1708 vertical-align:top;
1708 vertical-align:top;
1709 }
1709 }
1710
1710
1711 .ac .yui-ac {
1711 .ac .yui-ac {
1712 position:relative;
1712 position:relative;
1713 font-family:arial;
1713 font-family:arial;
1714 font-size:100%;
1714 font-size:100%;
1715 }
1715 }
1716
1716
1717 .ac .perm_ac {
1717 .ac .perm_ac {
1718 width:15em;
1718 width:15em;
1719 }
1719 }
1720
1720
1721 .ac .yui-ac-input {
1721 .ac .yui-ac-input {
1722 width:100%;
1722 width:100%;
1723 }
1723 }
1724
1724
1725 .ac .yui-ac-container {
1725 .ac .yui-ac-container {
1726 position:absolute;
1726 position:absolute;
1727 top:1.6em;
1727 top:1.6em;
1728 width:100%;
1728 width:100%;
1729 }
1729 }
1730
1730
1731 .ac .yui-ac-content {
1731 .ac .yui-ac-content {
1732 position:absolute;
1732 position:absolute;
1733 width:100%;
1733 width:100%;
1734 border:1px solid gray;
1734 border:1px solid gray;
1735 background:#fff;
1735 background:#fff;
1736 overflow:hidden;
1736 overflow:hidden;
1737 z-index:9050;
1737 z-index:9050;
1738 }
1738 }
1739
1739
1740 .ac .yui-ac-shadow {
1740 .ac .yui-ac-shadow {
1741 position:absolute;
1741 position:absolute;
1742 width:100%;
1742 width:100%;
1743 background:#000;
1743 background:#000;
1744 -moz-opacity:0.1px;
1744 -moz-opacity:0.1px;
1745 opacity:.10;
1745 opacity:.10;
1746 filter:alpha(opacity = 10);
1746 filter:alpha(opacity = 10);
1747 z-index:9049;
1747 z-index:9049;
1748 margin:.3em;
1748 margin:.3em;
1749 }
1749 }
1750
1750
1751 .ac .yui-ac-content ul {
1751 .ac .yui-ac-content ul {
1752 width:100%;
1752 width:100%;
1753 margin:0;
1753 margin:0;
1754 padding:0;
1754 padding:0;
1755 }
1755 }
1756
1756
1757 .ac .yui-ac-content li {
1757 .ac .yui-ac-content li {
1758 cursor:default;
1758 cursor:default;
1759 white-space:nowrap;
1759 white-space:nowrap;
1760 margin:0;
1760 margin:0;
1761 padding:2px 5px;
1761 padding:2px 5px;
1762 }
1762 }
1763
1763
1764 .ac .yui-ac-content li.yui-ac-prehighlight {
1764 .ac .yui-ac-content li.yui-ac-prehighlight {
1765 background:#B3D4FF;
1765 background:#B3D4FF;
1766 }
1766 }
1767
1767
1768 .ac .yui-ac-content li.yui-ac-highlight {
1768 .ac .yui-ac-content li.yui-ac-highlight {
1769 background:#556CB5;
1769 background:#556CB5;
1770 color:#FFF;
1770 color:#FFF;
1771 }
1771 }
1772
1772
1773 .add_icon {
1773 .add_icon {
1774 background:url("../images/icons/add.png") no-repeat scroll 3px;
1774 background:url("../images/icons/add.png") no-repeat scroll 3px;
1775 height:16px;
1775 height:16px;
1776 padding-left:20px;
1776 padding-left:20px;
1777 padding-top:1px;
1777 padding-top:1px;
1778 text-align:left;
1778 text-align:left;
1779 }
1779 }
1780
1780
1781 .edit_icon {
1781 .edit_icon {
1782 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1782 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1783 height:16px;
1783 height:16px;
1784 padding-left:20px;
1784 padding-left:20px;
1785 padding-top:1px;
1785 padding-top:1px;
1786 text-align:left;
1786 text-align:left;
1787 }
1787 }
1788
1788
1789 .delete_icon {
1789 .delete_icon {
1790 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1790 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1791 height:16px;
1791 height:16px;
1792 padding-left:20px;
1792 padding-left:20px;
1793 padding-top:1px;
1793 padding-top:1px;
1794 text-align:left;
1794 text-align:left;
1795 }
1795 }
1796
1796
1797 .rss_icon {
1797 .rss_icon {
1798 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1798 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1799 height:16px;
1799 height:16px;
1800 padding-left:20px;
1800 padding-left:20px;
1801 padding-top:1px;
1801 padding-top:1px;
1802 text-align:left;
1802 text-align:left;
1803 }
1803 }
1804
1804
1805 .atom_icon {
1805 .atom_icon {
1806 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1806 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1807 height:16px;
1807 height:16px;
1808 padding-left:20px;
1808 padding-left:20px;
1809 padding-top:1px;
1809 padding-top:1px;
1810 text-align:left;
1810 text-align:left;
1811 }
1811 }
1812
1812
1813 .archive_icon {
1813 .archive_icon {
1814 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1814 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1815 height:16px;
1815 height:16px;
1816 padding-left:20px;
1816 padding-left:20px;
1817 text-align:left;
1817 text-align:left;
1818 padding-top:1px;
1818 padding-top:1px;
1819 }
1819 }
1820
1820
1821 .action_button {
1821 .action_button {
1822 border:0;
1822 border:0;
1823 display:block;
1823 display:block;
1824 }
1824 }
1825
1825
1826 .action_button:hover {
1826 .action_button:hover {
1827 border:0;
1827 border:0;
1828 text-decoration:underline;
1828 text-decoration:underline;
1829 cursor:pointer;
1829 cursor:pointer;
1830 }
1830 }
1831
1831
1832 #switch_repos {
1832 #switch_repos {
1833 position:absolute;
1833 position:absolute;
1834 height:25px;
1834 height:25px;
1835 z-index:1;
1835 z-index:1;
1836 }
1836 }
1837
1837
1838 #switch_repos select {
1838 #switch_repos select {
1839 min-width:150px;
1839 min-width:150px;
1840 max-height:250px;
1840 max-height:250px;
1841 z-index:1;
1841 z-index:1;
1842 }
1842 }
1843
1843
1844 .breadcrumbs {
1844 .breadcrumbs {
1845 border:medium none;
1845 border:medium none;
1846 color:#FFF;
1846 color:#FFF;
1847 float:left;
1847 float:left;
1848 text-transform:uppercase;
1848 text-transform:uppercase;
1849 font-weight:700;
1849 font-weight:700;
1850 font-size:14px;
1850 font-size:14px;
1851 margin:0;
1851 margin:0;
1852 padding:11px 0 11px 10px;
1852 padding:11px 0 11px 10px;
1853 }
1853 }
1854
1854
1855 .breadcrumbs a {
1855 .breadcrumbs a {
1856 color:#FFF;
1856 color:#FFF;
1857 }
1857 }
1858
1858
1859 .flash_msg ul {
1859 .flash_msg ul {
1860 margin:0;
1860 margin:0;
1861 padding:0 0 10px;
1861 padding:0 0 10px;
1862 }
1862 }
1863
1863
1864 .error_msg {
1864 .error_msg {
1865 background-color:#FFCFCF;
1865 background-color:#FFCFCF;
1866 background-image:url("../../images/icons/error_msg.png");
1866 background-image:url("../../images/icons/error_msg.png");
1867 border:1px solid #FF9595;
1867 border:1px solid #FF9595;
1868 color:#C30;
1868 color:#C30;
1869 }
1869 }
1870
1870
1871 .warning_msg {
1871 .warning_msg {
1872 background-color:#FFFBCC;
1872 background-color:#FFFBCC;
1873 background-image:url("../../images/icons/warning_msg.png");
1873 background-image:url("../../images/icons/warning_msg.png");
1874 border:1px solid #FFF35E;
1874 border:1px solid #FFF35E;
1875 color:#C69E00;
1875 color:#C69E00;
1876 }
1876 }
1877
1877
1878 .success_msg {
1878 .success_msg {
1879 background-color:#D5FFCF;
1879 background-color:#D5FFCF;
1880 background-image:url("../../images/icons/success_msg.png");
1880 background-image:url("../../images/icons/success_msg.png");
1881 border:1px solid #97FF88;
1881 border:1px solid #97FF88;
1882 color:#090;
1882 color:#090;
1883 }
1883 }
1884
1884
1885 .notice_msg {
1885 .notice_msg {
1886 background-color:#DCE3FF;
1886 background-color:#DCE3FF;
1887 background-image:url("../../images/icons/notice_msg.png");
1887 background-image:url("../../images/icons/notice_msg.png");
1888 border:1px solid #93A8FF;
1888 border:1px solid #93A8FF;
1889 color:#556CB5;
1889 color:#556CB5;
1890 }
1890 }
1891
1891
1892 .success_msg,.error_msg,.notice_msg,.warning_msg {
1892 .success_msg,.error_msg,.notice_msg,.warning_msg {
1893 background-position:10px center;
1893 background-position:10px center;
1894 background-repeat:no-repeat;
1894 background-repeat:no-repeat;
1895 font-size:12px;
1895 font-size:12px;
1896 font-weight:700;
1896 font-weight:700;
1897 min-height:14px;
1897 min-height:14px;
1898 line-height:14px;
1898 line-height:14px;
1899 margin-bottom:0;
1899 margin-bottom:0;
1900 margin-top:0;
1900 margin-top:0;
1901 display:block;
1901 display:block;
1902 overflow:auto;
1902 overflow:auto;
1903 padding:6px 10px 6px 40px;
1903 padding:6px 10px 6px 40px;
1904 }
1904 }
1905
1905
1906 #msg_close {
1906 #msg_close {
1907 background:transparent url("../../icons/cross_grey_small.png") no-repeat scroll 0 0;
1907 background:transparent url("../../icons/cross_grey_small.png") no-repeat scroll 0 0;
1908 cursor:pointer;
1908 cursor:pointer;
1909 height:16px;
1909 height:16px;
1910 position:absolute;
1910 position:absolute;
1911 right:5px;
1911 right:5px;
1912 top:5px;
1912 top:5px;
1913 width:16px;
1913 width:16px;
1914 }
1914 }
1915
1915
1916 div#legend_container table,div#legend_choices table {
1916 div#legend_container table,div#legend_choices table {
1917 width:auto !important;
1917 width:auto !important;
1918 }
1918 }
1919
1919
1920 table#permissions_manage {
1920 table#permissions_manage {
1921 width:0 !important;
1921 width:0 !important;
1922 }
1922 }
1923
1923
1924 table#permissions_manage span.private_repo_msg {
1924 table#permissions_manage span.private_repo_msg {
1925 font-size:0.8em;
1925 font-size:0.8em;
1926 opacity:0.6px;
1926 opacity:0.6px;
1927 }
1927 }
1928
1928
1929 table#permissions_manage td.private_repo_msg {
1929 table#permissions_manage td.private_repo_msg {
1930 font-size:0.8em;
1930 font-size:0.8em;
1931 }
1931 }
1932
1932
1933 table#permissions_manage tr#add_perm_input td {
1933 table#permissions_manage tr#add_perm_input td {
1934 vertical-align:middle;
1934 vertical-align:middle;
1935 }
1935 }
1936
1936
1937 div.gravatar {
1937 div.gravatar {
1938 background-color:#FFF;
1938 background-color:#FFF;
1939 border:1px solid #D0D0D0;
1939 border:1px solid #D0D0D0;
1940 float:left;
1940 float:left;
1941 margin-right:0.7em;
1941 margin-right:0.7em;
1942 padding:2px 2px 0;
1942 padding:2px 2px 0;
1943 }
1943 }
1944
1944
1945 #header,#content,#footer {
1945 #header,#content,#footer {
1946 min-width:1024px;
1946 min-width:1024px;
1947 }
1947 }
1948
1948
1949 #content {
1949 #content {
1950 min-height:100%;
1950 min-height:100%;
1951 clear:both;
1951 clear:both;
1952 overflow:hidden;
1952 overflow:hidden;
1953 padding:14px 30px;
1953 padding:14px 30px;
1954 }
1954 }
1955
1955
1956 #content div.box div.title div.search {
1956 #content div.box div.title div.search {
1957 background:url("../../images/title_link.png") no-repeat top left;
1957 background:url("../../images/title_link.png") no-repeat top left;
1958 border-left:1px solid #316293;
1958 border-left:1px solid #316293;
1959 }
1959 }
1960
1960
1961 #content div.box div.title div.search div.input input {
1961 #content div.box div.title div.search div.input input {
1962 border:1px solid #316293;
1962 border:1px solid #316293;
1963 }
1963 }
1964
1964
1965 #content div.box div.title div.search div.button input.ui-state-default {
1965 #content div.box div.title div.search div.button input.ui-state-default {
1966 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
1966 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
1967 border:1px solid #316293;
1967 border:1px solid #316293;
1968 border-left:none;
1968 border-left:none;
1969 color:#FFF;
1969 color:#FFF;
1970 }
1970 }
1971
1971
1972 #content div.box div.title div.search div.button input.ui-state-hover {
1972 #content div.box div.title div.search div.button input.ui-state-hover {
1973 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1973 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1974 border:1px solid #316293;
1974 border:1px solid #316293;
1975 border-left:none;
1975 border-left:none;
1976 color:#FFF;
1976 color:#FFF;
1977 }
1977 }
1978
1978
1979 #content div.box div.form div.fields div.field div.highlight .ui-state-default {
1979 #content div.box div.form div.fields div.field div.highlight .ui-state-default {
1980 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
1980 background:#4e85bb url("../../images/button_highlight.png") repeat-x;
1981 border-top:1px solid #5c91a4;
1981 border-top:1px solid #5c91a4;
1982 border-left:1px solid #2a6f89;
1982 border-left:1px solid #2a6f89;
1983 border-right:1px solid #2b7089;
1983 border-right:1px solid #2b7089;
1984 border-bottom:1px solid #1a6480;
1984 border-bottom:1px solid #1a6480;
1985 color:#fff;
1985 color:#fff;
1986 }
1986 }
1987
1987
1988 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
1988 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
1989 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1989 background:#46a0c1 url("../../images/button_highlight_selected.png") repeat-x;
1990 border-top:1px solid #78acbf;
1990 border-top:1px solid #78acbf;
1991 border-left:1px solid #34819e;
1991 border-left:1px solid #34819e;
1992 border-right:1px solid #35829f;
1992 border-right:1px solid #35829f;
1993 border-bottom:1px solid #257897;
1993 border-bottom:1px solid #257897;
1994 color:#fff;
1994 color:#fff;
1995 }
1995 }
1996
1996
1997 ins,div.options a:hover {
1997 ins,div.options a:hover {
1998 text-decoration:none;
1998 text-decoration:none;
1999 }
1999 }
2000
2000
2001 img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
2001 img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
2002 border:none;
2002 border:none;
2003 }
2003 }
2004
2004
2005 img.icon,.right .merge img {
2005 img.icon,.right .merge img {
2006 vertical-align:bottom;
2006 vertical-align:bottom;
2007 }
2007 }
2008
2008
2009 #header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
2009 #header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
2010 float:right;
2010 float:right;
2011 margin:0;
2011 margin:0;
2012 padding:0;
2012 padding:0;
2013 }
2013 }
2014
2014
2015 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
2015 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
2016 float:left;
2016 float:left;
2017 }
2017 }
2018
2018
2019 #header #header-inner #quick li:hover ul ul,#header #header-inner #quick li:hover ul ul ul,#header #header-inner #quick li:hover ul ul ul ul,#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow {
2019 #header #header-inner #quick li:hover ul ul,#header #header-inner #quick li:hover ul ul ul,#header #header-inner #quick li:hover ul ul ul ul,#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow {
2020 display:none;
2020 display:none;
2021 }
2021 }
2022
2022
2023 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded {
2023 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded {
2024 display:block;
2024 display:block;
2025 }
2025 }
2026
2026
2027 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2027 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2028 color:#bfe3ff;
2028 color:#bfe3ff;
2029 }
2029 }
2030
2030
2031 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal {
2031 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal {
2032 margin:10px 24px 10px 44px;
2032 margin:10px 24px 10px 44px;
2033 }
2033 }
2034
2034
2035 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2035 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2036 clear:both;
2036 clear:both;
2037 overflow:hidden;
2037 overflow:hidden;
2038 margin:0;
2038 margin:0;
2039 padding:0 20px 10px;
2039 padding:0 20px 10px;
2040 }
2040 }
2041
2041
2042 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2042 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2043 clear:both;
2043 clear:both;
2044 overflow:hidden;
2044 overflow:hidden;
2045 margin:0;
2045 margin:0;
2046 padding:0;
2046 padding:0;
2047 }
2047 }
2048
2048
2049 #content div.box div.form div.fields div.field div.label-checkbox,#content div.box div.form div.fields div.field div.label-radio,#content div.box div.form div.fields div.field div.label-textarea {
2049 #content div.box div.form div.fields div.field div.label-checkbox,#content div.box div.form div.fields div.field div.label-radio,#content div.box div.form div.fields div.field div.label-textarea {
2050 padding:0 0 0 5px !important;
2050 padding:0 0 0 5px !important;
2051 }
2051 }
2052
2052
2053 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span {
2053 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span {
2054 height:1%;
2054 height:1%;
2055 display:block;
2055 display:block;
2056 color:#363636;
2056 color:#363636;
2057 margin:0;
2057 margin:0;
2058 padding:2px 0 0;
2058 padding:2px 0 0;
2059 }
2059 }
2060
2060
2061 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error {
2061 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error {
2062 background:#FBE3E4;
2062 background:#FBE3E4;
2063 border-top:1px solid #e1b2b3;
2063 border-top:1px solid #e1b2b3;
2064 border-left:1px solid #e1b2b3;
2064 border-left:1px solid #e1b2b3;
2065 border-right:1px solid #FBC2C4;
2065 border-right:1px solid #FBC2C4;
2066 border-bottom:1px solid #FBC2C4;
2066 border-bottom:1px solid #FBC2C4;
2067 }
2067 }
2068
2068
2069 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success {
2069 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success {
2070 background:#E6EFC2;
2070 background:#E6EFC2;
2071 border-top:1px solid #cebb98;
2071 border-top:1px solid #cebb98;
2072 border-left:1px solid #cebb98;
2072 border-left:1px solid #cebb98;
2073 border-right:1px solid #c6d880;
2073 border-right:1px solid #c6d880;
2074 border-bottom:1px solid #c6d880;
2074 border-bottom:1px solid #c6d880;
2075 }
2075 }
2076
2076
2077 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input {
2077 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input {
2078 margin:0;
2078 margin:0;
2079 }
2079 }
2080
2080
2081 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios {
2081 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios {
2082 margin:0 0 0 200px;
2082 margin:0 0 0 200px;
2083 padding:0;
2083 padding:0;
2084 }
2084 }
2085
2085
2086 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover {
2086 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover {
2087 color:#000;
2087 color:#000;
2088 text-decoration:none;
2088 text-decoration:none;
2089 }
2089 }
2090
2090
2091 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2091 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2092 border:1px solid #666;
2092 border:1px solid #666;
2093 }
2093 }
2094
2094
2095 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio {
2095 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio {
2096 clear:both;
2096 clear:both;
2097 overflow:hidden;
2097 overflow:hidden;
2098 margin:0;
2098 margin:0;
2099 padding:2px 0;
2099 padding:2px 2px;
2100 }
2100 }
2101
2101
2102 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
2102 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
2103 float:left;
2103 float:left;
2104 margin:0;
2104 margin:0;
2105 }
2105 }
2106
2106
2107 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label {
2107 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label {
2108 height:1%;
2108 height:1%;
2109 display:block;
2109 display:block;
2110 float:left;
2110 float:left;
2111 margin:3px 0 0 4px;
2111 margin:3px 0 0 4px;
2112 }
2112 }
2113
2113
2114 div.form div.fields div.field div.button input,#content div.box div.form div.fields div.buttons input,div.form div.fields div.buttons input,#content div.box div.action div.button input {
2114 div.form div.fields div.field div.button input,#content div.box div.form div.fields div.buttons input,div.form div.fields div.buttons input,#content div.box div.action div.button input {
2115 color:#000;
2115 color:#000;
2116 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2116 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2117 font-size:11px;
2117 font-size:11px;
2118 font-weight:700;
2118 font-weight:700;
2119 margin:0;
2119 margin:0;
2120 }
2120 }
2121
2121
2122 div.form div.fields div.field div.button .ui-state-default,#content div.box div.form div.fields div.buttons input.ui-state-default {
2122 div.form div.fields div.field div.button .ui-state-default,#content div.box div.form div.fields div.buttons input.ui-state-default {
2123 background:#e5e3e3 url("../images/button.png") repeat-x;
2123 background:#e5e3e3 url("../images/button.png") repeat-x;
2124 border-top:1px solid #DDD;
2124 border-top:1px solid #DDD;
2125 border-left:1px solid #c6c6c6;
2125 border-left:1px solid #c6c6c6;
2126 border-right:1px solid #DDD;
2126 border-right:1px solid #DDD;
2127 border-bottom:1px solid #c6c6c6;
2127 border-bottom:1px solid #c6c6c6;
2128 color:#515151;
2128 color:#515151;
2129 outline:none;
2129 outline:none;
2130 margin:0;
2130 margin:0;
2131 padding:6px 12px;
2131 padding:6px 12px;
2132 }
2132 }
2133
2133
2134 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2134 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2135 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2135 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2136 border-top:1px solid #ccc;
2136 border-top:1px solid #ccc;
2137 border-left:1px solid #bebebe;
2137 border-left:1px solid #bebebe;
2138 border-right:1px solid #b1b1b1;
2138 border-right:1px solid #b1b1b1;
2139 border-bottom:1px solid #afafaf;
2139 border-bottom:1px solid #afafaf;
2140 color:#515151;
2140 color:#515151;
2141 outline:none;
2141 outline:none;
2142 margin:0;
2142 margin:0;
2143 padding:6px 12px;
2143 padding:6px 12px;
2144 }
2144 }
2145
2145
2146 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2146 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2147 display:inline;
2147 display:inline;
2148 }
2148 }
2149
2149
2150 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2150 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2151 margin:10px 0 0 200px;
2151 margin:10px 0 0 200px;
2152 padding:0;
2152 padding:0;
2153 }
2153 }
2154
2154
2155 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons {
2155 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons {
2156 margin:10px 0 0;
2156 margin:10px 0 0;
2157 }
2157 }
2158
2158
2159 #content div.box table td.user,#content div.box table td.address {
2159 #content div.box table td.user,#content div.box table td.address {
2160 width:10%;
2160 width:10%;
2161 text-align:center;
2161 text-align:center;
2162 }
2162 }
2163
2163
2164 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link {
2164 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link {
2165 text-align:right;
2165 text-align:right;
2166 margin:6px 0 0;
2166 margin:6px 0 0;
2167 padding:0;
2167 padding:0;
2168 }
2168 }
2169
2169
2170 #content div.box div.action div.button input.ui-state-default,#login div.form div.fields div.buttons input.ui-state-default,#register div.form div.fields div.buttons input.ui-state-default {
2170 #content div.box div.action div.button input.ui-state-default,#login div.form div.fields div.buttons input.ui-state-default,#register div.form div.fields div.buttons input.ui-state-default {
2171 background:#e5e3e3 url("../images/button.png") repeat-x;
2171 background:#e5e3e3 url("../images/button.png") repeat-x;
2172 border-top:1px solid #DDD;
2172 border-top:1px solid #DDD;
2173 border-left:1px solid #c6c6c6;
2173 border-left:1px solid #c6c6c6;
2174 border-right:1px solid #DDD;
2174 border-right:1px solid #DDD;
2175 border-bottom:1px solid #c6c6c6;
2175 border-bottom:1px solid #c6c6c6;
2176 color:#515151;
2176 color:#515151;
2177 margin:0;
2177 margin:0;
2178 padding:6px 12px;
2178 padding:6px 12px;
2179 }
2179 }
2180
2180
2181 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
2181 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
2182 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2182 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2183 border-top:1px solid #ccc;
2183 border-top:1px solid #ccc;
2184 border-left:1px solid #bebebe;
2184 border-left:1px solid #bebebe;
2185 border-right:1px solid #b1b1b1;
2185 border-right:1px solid #b1b1b1;
2186 border-bottom:1px solid #afafaf;
2186 border-bottom:1px solid #afafaf;
2187 color:#515151;
2187 color:#515151;
2188 margin:0;
2188 margin:0;
2189 padding:6px 12px;
2189 padding:6px 12px;
2190 }
2190 }
2191
2191
2192 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2192 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2193 text-align:left;
2193 text-align:left;
2194 float:left;
2194 float:left;
2195 margin:0;
2195 margin:0;
2196 padding:0;
2196 padding:0;
2197 }
2197 }
2198
2198
2199 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2199 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2200 height:1%;
2200 height:1%;
2201 display:block;
2201 display:block;
2202 float:left;
2202 float:left;
2203 background:#ebebeb url("../images/pager.png") repeat-x;
2203 background:#ebebeb url("../images/pager.png") repeat-x;
2204 border-top:1px solid #dedede;
2204 border-top:1px solid #dedede;
2205 border-left:1px solid #cfcfcf;
2205 border-left:1px solid #cfcfcf;
2206 border-right:1px solid #c4c4c4;
2206 border-right:1px solid #c4c4c4;
2207 border-bottom:1px solid #c4c4c4;
2207 border-bottom:1px solid #c4c4c4;
2208 color:#4A4A4A;
2208 color:#4A4A4A;
2209 font-weight:700;
2209 font-weight:700;
2210 margin:0;
2210 margin:0;
2211 padding:6px 8px;
2211 padding:6px 8px;
2212 }
2212 }
2213
2213
2214 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2214 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2215 color:#B4B4B4;
2215 color:#B4B4B4;
2216 padding:6px;
2216 padding:6px;
2217 }
2217 }
2218
2218
2219 #login,#register {
2219 #login,#register {
2220 width:420px;
2220 width:420px;
2221 margin:10% auto 0;
2221 margin:10% auto 0;
2222 padding:0;
2222 padding:0;
2223 }
2223 }
2224
2224
2225 #login div.color,#register div.color {
2225 #login div.color,#register div.color {
2226 clear:both;
2226 clear:both;
2227 overflow:hidden;
2227 overflow:hidden;
2228 background:#FFF;
2228 background:#FFF;
2229 margin:10px auto 0;
2229 margin:10px auto 0;
2230 padding:3px 3px 3px 0;
2230 padding:3px 3px 3px 0;
2231 }
2231 }
2232
2232
2233 #login div.color a,#register div.color a {
2233 #login div.color a,#register div.color a {
2234 width:20px;
2234 width:20px;
2235 height:20px;
2235 height:20px;
2236 display:block;
2236 display:block;
2237 float:left;
2237 float:left;
2238 margin:0 0 0 3px;
2238 margin:0 0 0 3px;
2239 padding:0;
2239 padding:0;
2240 }
2240 }
2241
2241
2242 #login div.title h5,#register div.title h5 {
2242 #login div.title h5,#register div.title h5 {
2243 color:#fff;
2243 color:#fff;
2244 margin:10px;
2244 margin:10px;
2245 padding:0;
2245 padding:0;
2246 }
2246 }
2247
2247
2248 #login div.form div.fields div.field,#register div.form div.fields div.field {
2248 #login div.form div.fields div.field,#register div.form div.fields div.field {
2249 clear:both;
2249 clear:both;
2250 overflow:hidden;
2250 overflow:hidden;
2251 margin:0;
2251 margin:0;
2252 padding:0 0 10px;
2252 padding:0 0 10px;
2253 }
2253 }
2254
2254
2255 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2255 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2256 height:1%;
2256 height:1%;
2257 display:block;
2257 display:block;
2258 color:red;
2258 color:red;
2259 margin:8px 0 0;
2259 margin:8px 0 0;
2260 padding:0;
2260 padding:0;
2261 }
2261 }
2262
2262
2263 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2263 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2264 color:#000;
2264 color:#000;
2265 font-weight:700;
2265 font-weight:700;
2266 }
2266 }
2267
2267
2268 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2268 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2269 float:left;
2269 float:left;
2270 margin:0;
2270 margin:0;
2271 padding:0;
2271 padding:0;
2272 }
2272 }
2273
2273
2274 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2274 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2275 margin:0 0 0 184px;
2275 margin:0 0 0 184px;
2276 padding:0;
2276 padding:0;
2277 }
2277 }
2278
2278
2279 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2279 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2280 color:#565656;
2280 color:#565656;
2281 font-weight:700;
2281 font-weight:700;
2282 }
2282 }
2283
2283
2284 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2284 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2285 color:#000;
2285 color:#000;
2286 font-size:1em;
2286 font-size:1em;
2287 font-weight:700;
2287 font-weight:700;
2288 font-family:Verdana, Helvetica, Sans-Serif;
2288 font-family:Verdana, Helvetica, Sans-Serif;
2289 margin:0;
2289 margin:0;
2290 }
2290 }
2291
2291
2292 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2292 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2293 width:600px;
2293 width:600px;
2294 }
2294 }
2295
2295
2296 #changeset_content .container .left,#graph_content .container .left {
2296 #changeset_content .container .left,#graph_content .container .left {
2297 float:left;
2297 float:left;
2298 width:70%;
2298 width:70%;
2299 padding-left:5px;
2299 padding-left:5px;
2300 }
2300 }
2301
2301
2302 #changeset_content .container .left .date,.ac .match {
2302 #changeset_content .container .left .date,.ac .match {
2303 font-weight:700;
2303 font-weight:700;
2304 padding-top: 5px;
2304 padding-top: 5px;
2305 padding-bottom:5px;
2305 padding-bottom:5px;
2306 }
2306 }
2307
2307
2308 div#legend_container table td,div#legend_choices table td {
2308 div#legend_container table td,div#legend_choices table td {
2309 border:none !important;
2309 border:none !important;
2310 height:20px !important;
2310 height:20px !important;
2311 padding:0 !important;
2311 padding:0 !important;
2312 }
2312 }
2313
2313
2314 #q_filter{
2314 #q_filter{
2315 border:0 none;
2315 border:0 none;
2316 color:#AAAAAA;
2316 color:#AAAAAA;
2317 margin-bottom:-4px;
2317 margin-bottom:-4px;
2318 margin-top:-4px;
2318 margin-top:-4px;
2319 padding-left:3px;
2319 padding-left:3px;
2320 }
2320 }
2321
2321
@@ -1,68 +1,77 b''
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 ${_('Permissions administration')} - ${c.rhodecode_name}
5 ${_('Permissions 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'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${_('Permissions')}
11 ${_('Permissions')}
12 </%def>
12 </%def>
13
13
14 <%def name="page_nav()">
14 <%def name="page_nav()">
15 ${self.menu('admin')}
15 ${self.menu('admin')}
16 </%def>
16 </%def>
17
17
18 <%def name="main()">
18 <%def name="main()">
19 <div class="box">
19 <div class="box">
20 <!-- box / title -->
20 <!-- box / title -->
21 <div class="title">
21 <div class="title">
22 ${self.breadcrumbs()}
22 ${self.breadcrumbs()}
23 </div>
23 </div>
24 <h3>${_('Default permissions')}</h3>
24 <h3>${_('Default permissions')}</h3>
25 ${h.form(url('permission', id='default'),method='put')}
25 ${h.form(url('permission', id='default'),method='put')}
26 <div class="form">
26 <div class="form">
27 <!-- fields -->
27 <!-- fields -->
28 <div class="fields">
28 <div class="fields">
29
29 <div class="field">
30 <div class="label label-checkbox">
31 <label for="anonymous">${_('Anonymous access')}:</label>
32 </div>
33 <div class="checkboxes">
34 <div class="checkbox">
35 ${h.checkbox('anonymous',True)}
36 </div>
37 </div>
38 </div>
30 <div class="field">
39 <div class="field">
31 <div class="label">
40 <div class="label">
32 <label for="default_perm">${_('Repository permission')}:</label>
41 <label for="default_perm">${_('Repository permission')}:</label>
33 </div>
42 </div>
34 <div class="select">
43 <div class="select">
35 ${h.select('default_perm','',c.perms_choices)}
44 ${h.select('default_perm','',c.perms_choices)}
36
45
37 ${h.checkbox('overwrite_default','true')}
46 ${h.checkbox('overwrite_default','true')}
38 <label for="overwrite_default">
47 <label for="overwrite_default">
39 <span class="tooltip"
48 <span class="tooltip"
40 tooltip_title="${h.tooltip(_('All default permissions on each repository will be reset to choosen permission, note that all custom default permission on repositories will be lost'))}">
49 tooltip_title="${h.tooltip(_('All default permissions on each repository will be reset to choosen permission, note that all custom default permission on repositories will be lost'))}">
41 ${_('overwrite existing settings')}</span> </label>
50 ${_('overwrite existing settings')}</span> </label>
42 </div>
51 </div>
43 </div>
52 </div>
44 <div class="field">
53 <div class="field">
45 <div class="label">
54 <div class="label">
46 <label for="default_register">${_('Registration')}:</label>
55 <label for="default_register">${_('Registration')}:</label>
47 </div>
56 </div>
48 <div class="select">
57 <div class="select">
49 ${h.select('default_register','',c.register_choices)}
58 ${h.select('default_register','',c.register_choices)}
50 </div>
59 </div>
51 </div>
60 </div>
52 <div class="field">
61 <div class="field">
53 <div class="label">
62 <div class="label">
54 <label for="default_create">${_('Repository creation')}:</label>
63 <label for="default_create">${_('Repository creation')}:</label>
55 </div>
64 </div>
56 <div class="select">
65 <div class="select">
57 ${h.select('default_create','',c.create_choices)}
66 ${h.select('default_create','',c.create_choices)}
58 </div>
67 </div>
59 </div>
68 </div>
60
69
61 <div class="buttons">
70 <div class="buttons">
62 ${h.submit('set','set',class_="ui-button ui-widget ui-state-default ui-corner-all")}
71 ${h.submit('set','set',class_="ui-button ui-widget ui-state-default ui-corner-all")}
63 </div>
72 </div>
64 </div>
73 </div>
65 </div>
74 </div>
66 ${h.end_form()}
75 ${h.end_form()}
67 </div>
76 </div>
68 </%def>
77 </%def>
@@ -1,286 +1,296 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
4 <head>
4 <head>
5 <title>${next.title()}</title>
5 <title>${next.title()}</title>
6 <link rel="icon" href="/images/hgicon.png" type="image/png" />
6 <link rel="icon" href="/images/hgicon.png" type="image/png" />
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 <meta name="robots" content="index, nofollow"/>
8 <meta name="robots" content="index, nofollow"/>
9 <!-- stylesheets -->
9 <!-- stylesheets -->
10 ${self.css()}
10 ${self.css()}
11 <!-- scripts -->
11 <!-- scripts -->
12 ${self.js()}
12 ${self.js()}
13 </head>
13 </head>
14 <body>
14 <body>
15 <!-- header -->
15 <!-- header -->
16 <div id="header">
16 <div id="header">
17 <!-- user -->
17 <!-- user -->
18 <ul id="logged-user">
18 <ul id="logged-user">
19 <li class="first">
19 <li class="first">
20 <div class="gravatar">
20 <div class="gravatar">
21 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,24)}" />
21 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,24)}" />
22 </div>
22 </div>
23 %if c.rhodecode_user.username == 'default':
24 <div class="account">
25 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('#'))}<br/>
26 ${h.link_to(c.rhodecode_user.username,h.url('#'))}
27 </div>
28 </li>
29 <li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
30 %else:
31
23 <div class="account">
32 <div class="account">
24 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('admin_settings_my_account'))}<br/>
33 ${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('admin_settings_my_account'))}<br/>
25 ${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'))}
34 ${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'))}
26 </div>
35 </div>
27 </li>
36 </li>
28 <li class="last highlight">${h.link_to(u'Logout',h.url('logout_home'))}</li>
37 <li class="last highlight">${h.link_to(u'Logout',h.url('logout_home'))}</li>
38 %endif
29 </ul>
39 </ul>
30 <!-- end user -->
40 <!-- end user -->
31 <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
41 <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
32 <!-- logo -->
42 <!-- logo -->
33 <div id="logo">
43 <div id="logo">
34 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
44 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
35 </div>
45 </div>
36 <!-- end logo -->
46 <!-- end logo -->
37 <!-- menu -->
47 <!-- menu -->
38 ${self.page_nav()}
48 ${self.page_nav()}
39 <!-- quick -->
49 <!-- quick -->
40 </div>
50 </div>
41 </div>
51 </div>
42 <!-- end header -->
52 <!-- end header -->
43
53
44 <!-- CONTENT -->
54 <!-- CONTENT -->
45 <div id="content">
55 <div id="content">
46 <div class="flash_msg">
56 <div class="flash_msg">
47 <% messages = h.flash.pop_messages() %>
57 <% messages = h.flash.pop_messages() %>
48 % if messages:
58 % if messages:
49 <ul id="flash-messages">
59 <ul id="flash-messages">
50 % for message in messages:
60 % for message in messages:
51 <li class="${message.category}_msg">${message}</li>
61 <li class="${message.category}_msg">${message}</li>
52 % endfor
62 % endfor
53 </ul>
63 </ul>
54 % endif
64 % endif
55 </div>
65 </div>
56 <div id="main">
66 <div id="main">
57 ${next.main()}
67 ${next.main()}
58 </div>
68 </div>
59 </div>
69 </div>
60 <!-- END CONTENT -->
70 <!-- END CONTENT -->
61
71
62 <!-- footer -->
72 <!-- footer -->
63 <div id="footer">
73 <div id="footer">
64 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
74 <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
65 <div>
75 <div>
66 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
76 <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
67 <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
77 <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
68 <p>RhodeCode ${c.rhodecode_version} &copy; 2010 by Marcin Kuzminski</p>
78 <p>RhodeCode ${c.rhodecode_version} &copy; 2010 by Marcin Kuzminski</p>
69 </div>
79 </div>
70 </div>
80 </div>
71 <script type="text/javascript">${h.tooltip.activate()}</script>
81 <script type="text/javascript">${h.tooltip.activate()}</script>
72 </div>
82 </div>
73 <!-- end footer -->
83 <!-- end footer -->
74 </body>
84 </body>
75
85
76 </html>
86 </html>
77
87
78 ### MAKO DEFS ###
88 ### MAKO DEFS ###
79 <%def name="page_nav()">
89 <%def name="page_nav()">
80 ${self.menu()}
90 ${self.menu()}
81 </%def>
91 </%def>
82
92
83 <%def name="menu(current=None)">
93 <%def name="menu(current=None)">
84 <%
94 <%
85 def is_current(selected):
95 def is_current(selected):
86 if selected == current:
96 if selected == current:
87 return h.literal('class="current"')
97 return h.literal('class="current"')
88 %>
98 %>
89 %if current not in ['home','admin']:
99 %if current not in ['home','admin']:
90 ##REGULAR MENU
100 ##REGULAR MENU
91 <ul id="quick">
101 <ul id="quick">
92 <!-- repo switcher -->
102 <!-- repo switcher -->
93 <li>
103 <li>
94 <a id="repo_switcher" title="${_('Switch repository')}" href="#">
104 <a id="repo_switcher" title="${_('Switch repository')}" href="#">
95 <span class="icon">
105 <span class="icon">
96 <img src="/images/icons/database.png" alt="${_('Products')}" />
106 <img src="/images/icons/database.png" alt="${_('Products')}" />
97 </span>
107 </span>
98 <span>&darr;</span>
108 <span>&darr;</span>
99 </a>
109 </a>
100 <ul class="repo_switcher">
110 <ul class="repo_switcher">
101 %for repo in c.cached_repo_list:
111 %for repo in c.cached_repo_list:
102
112
103 %if repo['repo'].dbrepo.private:
113 %if repo['repo'].dbrepo.private:
104 <li>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="private_repo %s" % repo['repo'].dbrepo.repo_type)}</li>
114 <li>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="private_repo %s" % repo['repo'].dbrepo.repo_type)}</li>
105 %else:
115 %else:
106 <li>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="public_repo %s" % repo['repo'].dbrepo.repo_type)}</li>
116 <li>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="public_repo %s" % repo['repo'].dbrepo.repo_type)}</li>
107 %endif
117 %endif
108 %endfor
118 %endfor
109 </ul>
119 </ul>
110 </li>
120 </li>
111
121
112 <li ${is_current('summary')}>
122 <li ${is_current('summary')}>
113 <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
123 <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
114 <span class="icon">
124 <span class="icon">
115 <img src="/images/icons/clipboard_16.png" alt="${_('Summary')}" />
125 <img src="/images/icons/clipboard_16.png" alt="${_('Summary')}" />
116 </span>
126 </span>
117 <span>${_('Summary')}</span>
127 <span>${_('Summary')}</span>
118 </a>
128 </a>
119 </li>
129 </li>
120 ##<li ${is_current('shortlog')}>
130 ##<li ${is_current('shortlog')}>
121 ## <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
131 ## <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
122 ## <span class="icon">
132 ## <span class="icon">
123 ## <img src="/images/icons/application_view_list.png" alt="${_('Shortlog')}" />
133 ## <img src="/images/icons/application_view_list.png" alt="${_('Shortlog')}" />
124 ## </span>
134 ## </span>
125 ## <span>${_('Shortlog')}</span>
135 ## <span>${_('Shortlog')}</span>
126 ## </a>
136 ## </a>
127 ##</li>
137 ##</li>
128 <li ${is_current('changelog')}>
138 <li ${is_current('changelog')}>
129 <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
139 <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
130 <span class="icon">
140 <span class="icon">
131 <img src="/images/icons/time.png" alt="${_('Changelog')}" />
141 <img src="/images/icons/time.png" alt="${_('Changelog')}" />
132 </span>
142 </span>
133 <span>${_('Changelog')}</span>
143 <span>${_('Changelog')}</span>
134 </a>
144 </a>
135 </li>
145 </li>
136
146
137 <li ${is_current('switch_to')}>
147 <li ${is_current('switch_to')}>
138 <a title="${_('Switch to')}" href="#">
148 <a title="${_('Switch to')}" href="#">
139 <span class="icon">
149 <span class="icon">
140 <img src="/images/icons/arrow_switch.png" alt="${_('Switch to')}" />
150 <img src="/images/icons/arrow_switch.png" alt="${_('Switch to')}" />
141 </span>
151 </span>
142 <span>${_('Switch to')}</span>
152 <span>${_('Switch to')}</span>
143 </a>
153 </a>
144 <ul>
154 <ul>
145 <li>
155 <li>
146 ${h.link_to('%s (%s)' % (_('branches'),len(c.repository_branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
156 ${h.link_to('%s (%s)' % (_('branches'),len(c.repository_branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
147 <ul>
157 <ul>
148 %if c.repository_branches.values():
158 %if c.repository_branches.values():
149 %for cnt,branch in enumerate(c.repository_branches.items()):
159 %for cnt,branch in enumerate(c.repository_branches.items()):
150 <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
160 <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
151 %endfor
161 %endfor
152 %else:
162 %else:
153 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
163 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
154 %endif
164 %endif
155 </ul>
165 </ul>
156 </li>
166 </li>
157 <li>
167 <li>
158 ${h.link_to('%s (%s)' % (_('tags'),len(c.repository_tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
168 ${h.link_to('%s (%s)' % (_('tags'),len(c.repository_tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
159 <ul>
169 <ul>
160 %if c.repository_tags.values():
170 %if c.repository_tags.values():
161 %for cnt,tag in enumerate(c.repository_tags.items()):
171 %for cnt,tag in enumerate(c.repository_tags.items()):
162 <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
172 <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
163 %endfor
173 %endfor
164 %else:
174 %else:
165 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
175 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
166 %endif
176 %endif
167 </ul>
177 </ul>
168 </li>
178 </li>
169 </ul>
179 </ul>
170 </li>
180 </li>
171 <li ${is_current('files')}>
181 <li ${is_current('files')}>
172 <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
182 <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
173 <span class="icon">
183 <span class="icon">
174 <img src="/images/icons/file.png" alt="${_('Files')}" />
184 <img src="/images/icons/file.png" alt="${_('Files')}" />
175 </span>
185 </span>
176 <span>${_('Files')}</span>
186 <span>${_('Files')}</span>
177 </a>
187 </a>
178 </li>
188 </li>
179
189
180 <li ${is_current('options')}>
190 <li ${is_current('options')}>
181 <a title="${_('Options')}" href="#">
191 <a title="${_('Options')}" href="#">
182 <span class="icon">
192 <span class="icon">
183 <img src="/images/icons/table_gear.png" alt="${_('Admin')}" />
193 <img src="/images/icons/table_gear.png" alt="${_('Admin')}" />
184 </span>
194 </span>
185 <span>${_('Options')}</span>
195 <span>${_('Options')}</span>
186 </a>
196 </a>
187 <ul>
197 <ul>
188 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
198 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
189 <li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
199 <li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
190 %endif
200 %endif
191 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
201 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
192 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
202 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
193
203
194 %if h.HasPermissionAll('hg.admin')('access admin main page'):
204 %if h.HasPermissionAll('hg.admin')('access admin main page'):
195 <li>
205 <li>
196 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
206 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
197 <ul>
207 <ul>
198 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
208 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
199 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
209 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
200 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
210 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
201 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
211 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
202 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
212 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
203 </ul>
213 </ul>
204 </li>
214 </li>
205 %endif
215 %endif
206
216
207
217
208 ## %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
218 ## %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
209 ## <li class="last">
219 ## <li class="last">
210 ## ${h.link_to(_('delete'),'#',class_='delete')}
220 ## ${h.link_to(_('delete'),'#',class_='delete')}
211 ## ${h.form(url('repo_settings_delete', repo_name=c.repo_name),method='delete')}
221 ## ${h.form(url('repo_settings_delete', repo_name=c.repo_name),method='delete')}
212 ## ${h.submit('remove_%s' % c.repo_name,'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
222 ## ${h.submit('remove_%s' % c.repo_name,'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
213 ## ${h.end_form()}
223 ## ${h.end_form()}
214 ## </li>
224 ## </li>
215 ## %endif
225 ## %endif
216 </ul>
226 </ul>
217 </li>
227 </li>
218 </ul>
228 </ul>
219 %else:
229 %else:
220 ##ROOT MENU
230 ##ROOT MENU
221 <ul id="quick">
231 <ul id="quick">
222 <li>
232 <li>
223 <a title="${_('Home')}" href="${h.url('home')}">
233 <a title="${_('Home')}" href="${h.url('home')}">
224 <span class="icon">
234 <span class="icon">
225 <img src="/images/icons/home_16.png" alt="${_('Home')}" />
235 <img src="/images/icons/home_16.png" alt="${_('Home')}" />
226 </span>
236 </span>
227 <span>${_('Home')}</span>
237 <span>${_('Home')}</span>
228 </a>
238 </a>
229 </li>
239 </li>
230
240
231 <li>
241 <li>
232 <a title="${_('Search')}" href="${h.url('search')}">
242 <a title="${_('Search')}" href="${h.url('search')}">
233 <span class="icon">
243 <span class="icon">
234 <img src="/images/icons/search_16.png" alt="${_('Search')}" />
244 <img src="/images/icons/search_16.png" alt="${_('Search')}" />
235 </span>
245 </span>
236 <span>${_('Search')}</span>
246 <span>${_('Search')}</span>
237 </a>
247 </a>
238 </li>
248 </li>
239
249
240 %if h.HasPermissionAll('hg.admin')('access admin main page'):
250 %if h.HasPermissionAll('hg.admin')('access admin main page'):
241 <li ${is_current('admin')}>
251 <li ${is_current('admin')}>
242 <a title="${_('Admin')}" href="${h.url('admin_home')}">
252 <a title="${_('Admin')}" href="${h.url('admin_home')}">
243 <span class="icon">
253 <span class="icon">
244 <img src="/images/icons/cog_edit.png" alt="${_('Admin')}" />
254 <img src="/images/icons/cog_edit.png" alt="${_('Admin')}" />
245 </span>
255 </span>
246 <span>${_('Admin')}</span>
256 <span>${_('Admin')}</span>
247 </a>
257 </a>
248 <ul>
258 <ul>
249 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
259 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
250 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
260 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
251 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
261 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
252 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
262 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
253 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
263 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
254 </ul>
264 </ul>
255 </li>
265 </li>
256 %endif
266 %endif
257
267
258 </ul>
268 </ul>
259 %endif
269 %endif
260 </%def>
270 </%def>
261
271
262
272
263 <%def name="css()">
273 <%def name="css()">
264 <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
274 <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
265 <link rel="stylesheet" type="text/css" href="/css/pygments.css" />
275 <link rel="stylesheet" type="text/css" href="/css/pygments.css" />
266 <link rel="stylesheet" type="text/css" href="/css/diff.css" />
276 <link rel="stylesheet" type="text/css" href="/css/diff.css" />
267 </%def>
277 </%def>
268
278
269 <%def name="js()">
279 <%def name="js()">
270 ##<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
280 ##<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
271 ##<script type="text/javascript" src="/js/yui/container/container.js"></script>
281 ##<script type="text/javascript" src="/js/yui/container/container.js"></script>
272 ##<script type="text/javascript" src="/js/yui/datasource/datasource.js"></script>
282 ##<script type="text/javascript" src="/js/yui/datasource/datasource.js"></script>
273 ##<script type="text/javascript" src="/js/yui/autocomplete/autocomplete.js"></script>
283 ##<script type="text/javascript" src="/js/yui/autocomplete/autocomplete.js"></script>
274 ##<script type="text/javascript" src="/js/yui/selector/selector-min.js"></script>
284 ##<script type="text/javascript" src="/js/yui/selector/selector-min.js"></script>
275
285
276 <script type="text/javascript" src="/js/yui2.js"></script>
286 <script type="text/javascript" src="/js/yui2.js"></script>
277 <script type="text/javascript" src="/js/yui/selector/selector-min.js"></script>
287 <script type="text/javascript" src="/js/yui/selector/selector-min.js"></script>
278 <!--[if IE]><script language="javascript" type="text/javascript" src="/js/excanvas.min.js"></script><![endif]-->
288 <!--[if IE]><script language="javascript" type="text/javascript" src="/js/excanvas.min.js"></script><![endif]-->
279 <script type="text/javascript" src="/js/yui.flot.js"></script>
289 <script type="text/javascript" src="/js/yui.flot.js"></script>
280 </%def>
290 </%def>
281
291
282 <%def name="breadcrumbs()">
292 <%def name="breadcrumbs()">
283 <div class="breadcrumbs">
293 <div class="breadcrumbs">
284 ${self.breadcrumbs_links()}
294 ${self.breadcrumbs_links()}
285 </div>
295 </div>
286 </%def> No newline at end of file
296 </%def>
General Comments 0
You need to be logged in to leave comments. Login now