##// END OF EJS Templates
started working on issue #56
marcink -
r956:83d35d71 beta
parent child Browse files
Show More
@@ -0,0 +1,101 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.controllers.admin.users_groups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 Users Groups crud controller for pylons
7
8 :created_on: Jan 25, 2011
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
27
28 import logging
29 import traceback
30 import formencode
31
32 from formencode import htmlfill
33 from pylons import request, session, tmpl_context as c, url, config
34 from pylons.controllers.util import abort, redirect
35 from pylons.i18n.translation import _
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 fill_perms
41 from rhodecode.lib.base import BaseController, render
42
43 from rhodecode.model.db import User, UsersGroup
44 from rhodecode.model.forms import UserForm
45 from rhodecode.model.user import UserModel
46
47 log = logging.getLogger(__name__)
48
49 class UsersGroupsController(BaseController):
50 """REST Controller styled on the Atom Publishing Protocol"""
51 # To properly map this controller, ensure your config/routing.py
52 # file has a resource setup:
53 # map.resource('users_group', 'users_groups')
54
55 @LoginRequired()
56 @HasPermissionAllDecorator('hg.admin')
57 def __before__(self):
58 c.admin_user = session.get('admin_user')
59 c.admin_username = session.get('admin_username')
60 super(UsersGroupsController, self).__before__()
61 c.available_permissions = config['available_permissions']
62
63 def index(self, format='html'):
64 """GET /users_groups: All items in the collection"""
65 # url('users_groups')
66 c.users_groups_list = []
67 return render('admin/users_groups/users_groups.html')
68
69 def create(self):
70 """POST /users_groups: Create a new item"""
71 # url('users_groups')
72
73 def new(self, format='html'):
74 """GET /users_groups/new: Form to create a new item"""
75 # url('new_users_group')
76
77 def update(self, id):
78 """PUT /users_groups/id: Update an existing item"""
79 # Forms posted to this method should contain a hidden field:
80 # <input type="hidden" name="_method" value="PUT" />
81 # Or using helpers:
82 # h.form(url('users_group', id=ID),
83 # method='put')
84 # url('users_group', id=ID)
85
86 def delete(self, id):
87 """DELETE /users_groups/id: Delete an existing item"""
88 # Forms posted to this method should contain a hidden field:
89 # <input type="hidden" name="_method" value="DELETE" />
90 # Or using helpers:
91 # h.form(url('users_group', id=ID),
92 # method='delete')
93 # url('users_group', id=ID)
94
95 def show(self, id, format='html'):
96 """GET /users_groups/id: Show a specific item"""
97 # url('users_group', id=ID)
98
99 def edit(self, id, format='html'):
100 """GET /users_groups/id/edit: Form to edit an existing item"""
101 # url('edit_users_group', id=ID)
@@ -0,0 +1,26 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.model.user_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 users groups model for RhodeCode
7
8 :created_on: Jan 25, 2011
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
@@ -0,0 +1,54 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${_('Users groups administration')} - ${c.rhodecode_name}
6 </%def>
7
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Users groups')}
10 </%def>
11
12 <%def name="page_nav()">
13 ${self.menu('admin')}
14 </%def>
15
16 <%def name="main()">
17 <div class="box">
18 <!-- box / title -->
19 <div class="title">
20 ${self.breadcrumbs()}
21 <ul class="links">
22 <li>
23 <span>${h.link_to(u'ADD NEW USER GROUP',h.url('new_users_group'))}</span>
24 </li>
25
26 </ul>
27 </div>
28 <!-- end box / title -->
29 <div class="table">
30 <table class="table_disp">
31 <tr class="header">
32 <th></th>
33 <th class="left">${_('group name')}</th>
34 <th class="left">${_('members')}</th>
35 <th class="left">${_('active')}</th>
36 <th class="left">${_('action')}</th>
37 </tr>
38 %for cnt,u_group in enumerate(c.users_groups_list):
39 <tr class="parity${cnt%2}">
40 <td>${h.link_to(u_group.groupname,h.url('edit_user_group', id=u_group.group_id))}</td>
41 <td>${u_group.members}</td>
42 <td>${h.bool2icon(u_group.active)}</td>
43 <td>
44 ${h.form(url('users_group', id=group.group_id),method='delete')}
45 ${h.submit('remove_','delete',id="remove_group_%s" % group.group_id,
46 class_="delete_icon action_button",onclick="return confirm('Confirm to delete this user group');")}
47 ${h.end_form()}
48 </td>
49 </tr>
50 %endfor
51 </table>
52 </div>
53 </div>
54 </%def>
@@ -0,0 +1,43 b''
1 from rhodecode.tests import *
2
3 class TestUsersGroupsController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url('users_groups'))
7 # Test response...
8
9 def test_index_as_xml(self):
10 response = self.app.get(url('formatted_users_groups', format='xml'))
11
12 def test_create(self):
13 response = self.app.post(url('users_groups'))
14
15 def test_new(self):
16 response = self.app.get(url('new_users_group'))
17
18 def test_new_as_xml(self):
19 response = self.app.get(url('formatted_new_users_group', format='xml'))
20
21 def test_update(self):
22 response = self.app.put(url('users_group', id=1))
23
24 def test_update_browser_fakeout(self):
25 response = self.app.post(url('users_group', id=1), params=dict(_method='put'))
26
27 def test_delete(self):
28 response = self.app.delete(url('users_group', id=1))
29
30 def test_delete_browser_fakeout(self):
31 response = self.app.post(url('users_group', id=1), params=dict(_method='delete'))
32
33 def test_show(self):
34 response = self.app.get(url('users_group', id=1))
35
36 def test_show_as_xml(self):
37 response = self.app.get(url('formatted_users_group', id=1, format='xml'))
38
39 def test_edit(self):
40 response = self.app.get(url('edit_users_group', id=1))
41
42 def test_edit_as_xml(self):
43 response = self.app.get(url('formatted_edit_users_group', id=1, format='xml'))
@@ -81,19 +81,20 b' def make_map(config):'
81 action="repo_cache", conditions=dict(method=["DELETE"],
81 action="repo_cache", conditions=dict(method=["DELETE"],
82 function=check_repo))
82 function=check_repo))
83 #ADMIN USER REST ROUTES
83 #ADMIN USER REST ROUTES
84 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
84 map.resource('users_group', 'users_groups', controller='admin/users_groups', path_prefix='/_admin')
85
86 #ADMIN GROUP REST ROUTES
87 map.resource('group', 'groups', controller='admin/groups', path_prefix='/_admin')
85
88
86 #ADMIN PERMISSIONS REST ROUTES
89 #ADMIN PERMISSIONS REST ROUTES
87 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
90 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
88
91
89
90 ##ADMIN LDAP SETTINGS
92 ##ADMIN LDAP SETTINGS
91 map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
93 map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
92 action='ldap_settings', conditions=dict(method=["POST"]))
94 action='ldap_settings', conditions=dict(method=["POST"]))
93 map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
95 map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
94
96
95
97
96
97 #ADMIN SETTINGS REST ROUTES
98 #ADMIN SETTINGS REST ROUTES
98 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
99 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
99 m.connect("admin_settings", "/settings",
100 m.connect("admin_settings", "/settings",
@@ -153,6 +153,29 b' class UserLog(Base, BaseModel):'
153 user = relation('User')
153 user = relation('User')
154 repository = relation('Repository')
154 repository = relation('Repository')
155
155
156
157 class UsersGroup(Base, BaseModel):
158 __tablename__ = 'users_groups'
159 __table_args__ = {'useexisting':True}
160
161 user_group_id = Column("users_groups_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
162 user_group_name = Column("user_group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
163
164
165 members = relation('UsersGroupMember')
166
167
168 class UsersGroupMember(Base, BaseModel):
169 __tablename__ = 'users_groups_members'
170 __table_args__ = {'useexisting':True}
171
172 user_groups_members_id = Column("user_groups_members_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
173 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_groups_id'), nullable=False, unique=None, default=None)
174 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
175
176 user = relation('User')
177 users_group = relation('UsersGroup')
178
156 class Repository(Base, BaseModel):
179 class Repository(Base, BaseModel):
157 __tablename__ = 'repositories'
180 __tablename__ = 'repositories'
158 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
181 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
@@ -1,7 +1,7 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 package.rhodecode.model.user
3 rhodecode.model.user
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 users model for RhodeCode
6 users model for RhodeCode
7
7
@@ -478,6 +478,13 b' margin:0;'
478 padding:12px 9px 7px 24px;
478 padding:12px 9px 7px 24px;
479 }
479 }
480
480
481 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover {
482 background:#FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
483 width:167px;
484 margin:0;
485 padding:12px 9px 7px 24px;
486 }
487
481 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
488 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
482 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
489 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
483 width:167px;
490 width:167px;
@@ -240,6 +240,7 b''
240 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
240 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
241 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
241 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
242 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
242 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
243 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
243 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
244 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
244 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
245 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
245 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
246 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
General Comments 0
You need to be logged in to leave comments. Login now