Show More
@@ -0,0 +1,133 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 modify | |||
|
14 | # it under the terms of the GNU General Public License as published by | |||
|
15 | # the Free Software Foundation, either version 3 of the License, or | |||
|
16 | # (at your option) any later version. | |||
|
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, see <http://www.gnu.org/licenses/>. | |||
|
25 | ||||
|
26 | import os | |||
|
27 | import logging | |||
|
28 | import traceback | |||
|
29 | ||||
|
30 | from pylons.i18n.translation import _ | |||
|
31 | ||||
|
32 | from vcs.utils.lazy import LazyProperty | |||
|
33 | ||||
|
34 | from rhodecode.model import BaseModel | |||
|
35 | from rhodecode.model.caching_query import FromCache | |||
|
36 | from rhodecode.model.db import Group, RhodeCodeUi | |||
|
37 | ||||
|
38 | log = logging.getLogger(__name__) | |||
|
39 | ||||
|
40 | ||||
|
41 | class ReposGroupModel(BaseModel): | |||
|
42 | ||||
|
43 | @LazyProperty | |||
|
44 | def repos_path(self): | |||
|
45 | """ | |||
|
46 | Get's the repositories root path from database | |||
|
47 | """ | |||
|
48 | ||||
|
49 | q = RhodeCodeUi.get_by_key('/').one() | |||
|
50 | return q.ui_value | |||
|
51 | ||||
|
52 | def __create_group(self, group_name, parent_id): | |||
|
53 | """ | |||
|
54 | makes repositories group on filesystem | |||
|
55 | ||||
|
56 | :param repo_name: | |||
|
57 | :param parent_id: | |||
|
58 | """ | |||
|
59 | ||||
|
60 | if parent_id: | |||
|
61 | parent_group_name = Group.get(parent_id).group_name | |||
|
62 | else: | |||
|
63 | parent_group_name = '' | |||
|
64 | ||||
|
65 | create_path = os.path.join(self.repos_path, parent_group_name, | |||
|
66 | group_name) | |||
|
67 | log.debug('creating new group in %s', create_path) | |||
|
68 | ||||
|
69 | if os.path.isdir(create_path): | |||
|
70 | raise Exception('That directory already exists !') | |||
|
71 | ||||
|
72 | ||||
|
73 | os.makedirs(create_path) | |||
|
74 | ||||
|
75 | ||||
|
76 | def __rename_group(self, group_name): | |||
|
77 | """ | |||
|
78 | Renames a group on filesystem | |||
|
79 | ||||
|
80 | :param group_name: | |||
|
81 | """ | |||
|
82 | pass | |||
|
83 | ||||
|
84 | def __delete_group(self, group_name): | |||
|
85 | """ | |||
|
86 | Deletes a group from a filesystem | |||
|
87 | ||||
|
88 | :param group_name: | |||
|
89 | """ | |||
|
90 | pass | |||
|
91 | ||||
|
92 | def create(self, form_data): | |||
|
93 | try: | |||
|
94 | new_repos_group = Group() | |||
|
95 | new_repos_group.group_name = form_data['repos_group_name'] | |||
|
96 | new_repos_group.group_description = \ | |||
|
97 | form_data['repos_group_description'] | |||
|
98 | new_repos_group.group_parent_id = form_data['repos_group_parent'] | |||
|
99 | ||||
|
100 | self.sa.add(new_repos_group) | |||
|
101 | ||||
|
102 | self.__create_group(form_data['repos_group_name'], | |||
|
103 | form_data['repos_group_parent']) | |||
|
104 | ||||
|
105 | self.sa.commit() | |||
|
106 | except: | |||
|
107 | log.error(traceback.format_exc()) | |||
|
108 | self.sa.rollback() | |||
|
109 | raise | |||
|
110 | ||||
|
111 | def update(self, repos_group_id, form_data): | |||
|
112 | ||||
|
113 | try: | |||
|
114 | repos_group = Group.get(repos_group_id) | |||
|
115 | ||||
|
116 | ||||
|
117 | ||||
|
118 | self.sa.add(repos_group) | |||
|
119 | self.sa.commit() | |||
|
120 | except: | |||
|
121 | log.error(traceback.format_exc()) | |||
|
122 | self.sa.rollback() | |||
|
123 | raise | |||
|
124 | ||||
|
125 | def delete(self, users_group_id): | |||
|
126 | try: | |||
|
127 | users_group = self.get(users_group_id, cache=False) | |||
|
128 | self.sa.delete(users_group) | |||
|
129 | self.sa.commit() | |||
|
130 | except: | |||
|
131 | log.error(traceback.format_exc()) | |||
|
132 | self.sa.rollback() | |||
|
133 | raise |
@@ -0,0 +1,64 b'' | |||||
|
1 | ## -*- coding: utf-8 -*- | |||
|
2 | <%inherit file="/base/base.html"/> | |||
|
3 | ||||
|
4 | <%def name="title()"> | |||
|
5 | ${_('Add repos group')} - ${c.rhodecode_name} | |||
|
6 | </%def> | |||
|
7 | <%def name="breadcrumbs_links()"> | |||
|
8 | ${h.link_to(_('Admin'),h.url('admin_home'))} | |||
|
9 | » | |||
|
10 | ${h.link_to(_('Repos groups'),h.url('repos_groups'))} | |||
|
11 | » | |||
|
12 | ${_('add new repos group')} | |||
|
13 | </%def> | |||
|
14 | ||||
|
15 | <%def name="page_nav()"> | |||
|
16 | ${self.menu('admin')} | |||
|
17 | </%def> | |||
|
18 | ||||
|
19 | <%def name="main()"> | |||
|
20 | <div class="box"> | |||
|
21 | <!-- box / title --> | |||
|
22 | <div class="title"> | |||
|
23 | ${self.breadcrumbs()} | |||
|
24 | </div> | |||
|
25 | <!-- end box / title --> | |||
|
26 | ${h.form(url('repos_groups'))} | |||
|
27 | <div class="form"> | |||
|
28 | <!-- fields --> | |||
|
29 | <div class="fields"> | |||
|
30 | <div class="field"> | |||
|
31 | <div class="label"> | |||
|
32 | <label for="users_group_name">${_('Group name')}:</label> | |||
|
33 | </div> | |||
|
34 | <div class="input"> | |||
|
35 | ${h.text('repos_group_name',class_='medium')} | |||
|
36 | </div> | |||
|
37 | </div> | |||
|
38 | ||||
|
39 | <div class="field"> | |||
|
40 | <div class="label label-textarea"> | |||
|
41 | <label for="description">${_('Description')}:</label> | |||
|
42 | </div> | |||
|
43 | <div class="textarea text-area editor"> | |||
|
44 | ${h.textarea('repos_group_description',cols=23,rows=5,class_="medium")} | |||
|
45 | </div> | |||
|
46 | </div> | |||
|
47 | ||||
|
48 | <div class="field"> | |||
|
49 | <div class="label"> | |||
|
50 | <label for="repo_group">${_('Group parent')}:</label> | |||
|
51 | </div> | |||
|
52 | <div class="input"> | |||
|
53 | ${h.select('repos_group_parent','',c.repo_groups,class_="medium")} | |||
|
54 | </div> | |||
|
55 | </div> | |||
|
56 | ||||
|
57 | <div class="buttons"> | |||
|
58 | ${h.submit('save','save',class_="ui-button")} | |||
|
59 | </div> | |||
|
60 | </div> | |||
|
61 | </div> | |||
|
62 | ${h.end_form()} | |||
|
63 | </div> | |||
|
64 | </%def> No newline at end of file |
@@ -0,0 +1,68 b'' | |||||
|
1 | ## -*- coding: utf-8 -*- | |||
|
2 | <%inherit file="/base/base.html"/> | |||
|
3 | ||||
|
4 | <%def name="title()"> | |||
|
5 | ${_('Repositories groups administration')} - ${c.rhodecode_name} | |||
|
6 | </%def> | |||
|
7 | ||||
|
8 | ||||
|
9 | <%def name="breadcrumbs_links()"> | |||
|
10 | ${h.link_to(_('Admin'),h.url('admin_home'))} » ${_('Repositories')} | |||
|
11 | </%def> | |||
|
12 | <%def name="page_nav()"> | |||
|
13 | ${self.menu('admin')} | |||
|
14 | </%def> | |||
|
15 | <%def name="main()"> | |||
|
16 | <div class="box"> | |||
|
17 | <!-- box / title --> | |||
|
18 | <div class="title"> | |||
|
19 | ${self.breadcrumbs()} | |||
|
20 | <ul class="links"> | |||
|
21 | <li> | |||
|
22 | <span>${h.link_to(u'ADD NEW GROUP',h.url('new_repos_group'))}</span> | |||
|
23 | </li> | |||
|
24 | </ul> | |||
|
25 | </div> | |||
|
26 | <!-- end box / title --> | |||
|
27 | <div class="table"> | |||
|
28 | % if c.groups: | |||
|
29 | <table class="table_disp"> | |||
|
30 | ||||
|
31 | <thead> | |||
|
32 | <tr> | |||
|
33 | <th class="left"><a href="#">${_('Group name')}</a></th> | |||
|
34 | <th class="left"><a href="#">${_('Description')}</a></th> | |||
|
35 | <th class="left"><a href="#">${_('Number of repositories')}</a></th> | |||
|
36 | <th class="left">${_('action')}</th> | |||
|
37 | </tr> | |||
|
38 | </thead> | |||
|
39 | ||||
|
40 | ## REPO GROUPS | |||
|
41 | ||||
|
42 | % for gr in c.groups: | |||
|
43 | <tr> | |||
|
44 | <td> | |||
|
45 | <div style="white-space: nowrap"> | |||
|
46 | <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/> | |||
|
47 | ${h.link_to(h.literal(' » '.join([g.group_name for g in gr.parents+[gr]])),url('edit_repos_group',id=gr.group_id))} | |||
|
48 | </div> | |||
|
49 | </td> | |||
|
50 | <td>${gr.group_description}</td> | |||
|
51 | <td><b>${gr.repositories.count()}</b></td> | |||
|
52 | <td> | |||
|
53 | ${h.form(url('repos_group', id=gr.group_id),method='delete')} | |||
|
54 | ${h.submit('remove_%s' % gr.group_name,'delete',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this group');")} | |||
|
55 | ${h.end_form()} | |||
|
56 | </td> | |||
|
57 | </tr> | |||
|
58 | % endfor | |||
|
59 | ||||
|
60 | </table> | |||
|
61 | % else: | |||
|
62 | {_('There are no repositories groups yet')} | |||
|
63 | % endif | |||
|
64 | ||||
|
65 | </div> | |||
|
66 | </div> | |||
|
67 | ||||
|
68 | </%def> |
@@ -74,6 +74,8 b' class ReposController(BaseController):' | |||||
74 |
|
74 | |||
75 | c.repo_groups.extend([(x.group_id, parents_link(x)) for \ |
|
75 | c.repo_groups.extend([(x.group_id, parents_link(x)) for \ | |
76 | x in self.sa.query(Group).all()]) |
|
76 | x in self.sa.query(Group).all()]) | |
|
77 | c.repo_groups = sorted(c.repo_groups, | |||
|
78 | key=lambda t: t[1].split('»')[0]) | |||
77 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) |
|
79 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |
78 | c.users_array = repo_model.get_users_js() |
|
80 | c.users_array = repo_model.get_users_js() | |
79 | c.users_groups_array = repo_model.get_users_groups_js() |
|
81 | c.users_groups_array = repo_model.get_users_groups_js() |
@@ -1,11 +1,21 b'' | |||||
1 | import logging |
|
1 | import logging | |
|
2 | import traceback | |||
|
3 | import formencode | |||
|
4 | ||||
|
5 | from formencode import htmlfill | |||
2 | from operator import itemgetter |
|
6 | from operator import itemgetter | |
3 |
|
7 | |||
4 | from pylons import request, response, session, tmpl_context as c, url |
|
8 | from pylons import request, response, session, tmpl_context as c, url | |
5 | from pylons.controllers.util import abort, redirect |
|
9 | from pylons.controllers.util import abort, redirect | |
|
10 | from pylons.i18n.translation import _ | |||
6 |
|
11 | |||
|
12 | from rhodecode.lib import helpers as h | |||
|
13 | from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ | |||
|
14 | HasPermissionAnyDecorator | |||
7 | from rhodecode.lib.base import BaseController, render |
|
15 | from rhodecode.lib.base import BaseController, render | |
8 | from rhodecode.model.db import Group |
|
16 | from rhodecode.model.db import Group | |
|
17 | from rhodecode.model.repos_group import ReposGroupModel | |||
|
18 | from rhodecode.model.forms import ReposGroupForm | |||
9 |
|
19 | |||
10 | log = logging.getLogger(__name__) |
|
20 | log = logging.getLogger(__name__) | |
11 |
|
21 | |||
@@ -16,18 +26,73 b' class ReposGroupsController(BaseControll' | |||||
16 | # file has a resource setup: |
|
26 | # file has a resource setup: | |
17 | # map.resource('repos_group', 'repos_groups') |
|
27 | # map.resource('repos_group', 'repos_groups') | |
18 |
|
28 | |||
|
29 | def __load_defaults(self): | |||
|
30 | ||||
|
31 | c.repo_groups = [('', '')] | |||
|
32 | parents_link = lambda k: h.literal('»'.join( | |||
|
33 | map(lambda k: k.group_name, | |||
|
34 | k.parents + [k]) | |||
|
35 | ) | |||
|
36 | ) | |||
|
37 | ||||
|
38 | c.repo_groups.extend([(x.group_id, parents_link(x)) for \ | |||
|
39 | x in self.sa.query(Group).all()]) | |||
|
40 | ||||
|
41 | c.repo_groups = sorted(c.repo_groups, | |||
|
42 | key=lambda t: t[1].split('»')[0]) | |||
|
43 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |||
|
44 | ||||
|
45 | @LoginRequired() | |||
|
46 | def __before__(self): | |||
|
47 | super(ReposGroupsController, self).__before__() | |||
|
48 | ||||
|
49 | @HasPermissionAnyDecorator('hg.admin') | |||
19 | def index(self, format='html'): |
|
50 | def index(self, format='html'): | |
20 | """GET /repos_groups: All items in the collection""" |
|
51 | """GET /repos_groups: All items in the collection""" | |
21 | # url('repos_groups') |
|
52 | # url('repos_groups') | |
22 |
|
53 | |||
|
54 | sk = lambda g:g.parents[0].group_name if g.parents else g.group_name | |||
|
55 | c.groups = sorted(Group.query().all(), key=sk) | |||
|
56 | return render('admin/repos_groups/repos_groups_show.html') | |||
|
57 | ||||
|
58 | @HasPermissionAnyDecorator('hg.admin') | |||
23 | def create(self): |
|
59 | def create(self): | |
24 | """POST /repos_groups: Create a new item""" |
|
60 | """POST /repos_groups: Create a new item""" | |
25 | # url('repos_groups') |
|
61 | # url('repos_groups') | |
|
62 | self.__load_defaults() | |||
|
63 | repos_group_model = ReposGroupModel() | |||
|
64 | repos_group_form = ReposGroupForm(available_groups= | |||
|
65 | c.repo_groups_choices)() | |||
|
66 | try: | |||
|
67 | form_result = repos_group_form.to_python(dict(request.POST)) | |||
|
68 | repos_group_model.create(form_result) | |||
|
69 | h.flash(_('created repos group %s') \ | |||
|
70 | % form_result['repos_group_name'], category='success') | |||
|
71 | #TODO: in futureaction_logger(, '', '', '', self.sa) | |||
|
72 | except formencode.Invalid, errors: | |||
26 |
|
73 | |||
|
74 | return htmlfill.render( | |||
|
75 | render('admin/repos_groups/repos_groups_add.html'), | |||
|
76 | defaults=errors.value, | |||
|
77 | errors=errors.error_dict or {}, | |||
|
78 | prefix_error=False, | |||
|
79 | encoding="UTF-8") | |||
|
80 | except Exception: | |||
|
81 | log.error(traceback.format_exc()) | |||
|
82 | h.flash(_('error occurred during creation of repos group %s') \ | |||
|
83 | % request.POST.get('repos_group_name'), category='error') | |||
|
84 | ||||
|
85 | return redirect(url('repos_groups')) | |||
|
86 | ||||
|
87 | ||||
|
88 | @HasPermissionAnyDecorator('hg.admin') | |||
27 | def new(self, format='html'): |
|
89 | def new(self, format='html'): | |
28 | """GET /repos_groups/new: Form to create a new item""" |
|
90 | """GET /repos_groups/new: Form to create a new item""" | |
29 | # url('new_repos_group') |
|
91 | # url('new_repos_group') | |
|
92 | self.__load_defaults() | |||
|
93 | return render('admin/repos_groups/repos_groups_add.html') | |||
30 |
|
94 | |||
|
95 | @HasPermissionAnyDecorator('hg.admin') | |||
31 | def update(self, id): |
|
96 | def update(self, id): | |
32 | """PUT /repos_groups/id: Update an existing item""" |
|
97 | """PUT /repos_groups/id: Update an existing item""" | |
33 | # Forms posted to this method should contain a hidden field: |
|
98 | # Forms posted to this method should contain a hidden field: | |
@@ -37,6 +102,7 b' class ReposGroupsController(BaseControll' | |||||
37 | # method='put') |
|
102 | # method='put') | |
38 | # url('repos_group', id=ID) |
|
103 | # url('repos_group', id=ID) | |
39 |
|
104 | |||
|
105 | @HasPermissionAnyDecorator('hg.admin') | |||
40 | def delete(self, id): |
|
106 | def delete(self, id): | |
41 | """DELETE /repos_groups/id: Delete an existing item""" |
|
107 | """DELETE /repos_groups/id: Delete an existing item""" | |
42 | # Forms posted to this method should contain a hidden field: |
|
108 | # Forms posted to this method should contain a hidden field: | |
@@ -88,6 +154,7 b' class ReposGroupsController(BaseControll' | |||||
88 |
|
154 | |||
89 | return render('admin/repos_groups/repos_groups.html') |
|
155 | return render('admin/repos_groups/repos_groups.html') | |
90 |
|
156 | |||
|
157 | @HasPermissionAnyDecorator('hg.admin') | |||
91 | def edit(self, id, format='html'): |
|
158 | def edit(self, id, format='html'): | |
92 | """GET /repos_groups/id/edit: Form to edit an existing item""" |
|
159 | """GET /repos_groups/id/edit: Form to edit an existing item""" | |
93 | # url('edit_repos_group', id=ID) |
|
160 | # url('edit_repos_group', id=ID) |
@@ -332,6 +332,8 b' class SettingsController(BaseController)' | |||||
332 |
|
332 | |||
333 | c.repo_groups.extend([(x.group_id, parents_link(x)) for \ |
|
333 | c.repo_groups.extend([(x.group_id, parents_link(x)) for \ | |
334 | x in self.sa.query(Group).all()]) |
|
334 | x in self.sa.query(Group).all()]) | |
|
335 | c.repo_groups = sorted(c.repo_groups, | |||
|
336 | key=lambda t: t[1].split('»')[0]) | |||
335 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) |
|
337 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |
336 |
|
338 | |||
337 | new_repo = request.GET.get('repo', '') |
|
339 | new_repo = request.GET.get('repo', '') |
@@ -66,8 +66,7 b' class HomeController(BaseController):' | |||||
66 | c.repo_cnt = len(c.repos_list) |
|
66 | c.repo_cnt = len(c.repos_list) | |
67 |
|
67 | |||
68 |
|
68 | |||
69 | c.groups = self.sa.query(Group)\ |
|
69 | c.groups = Group.query().filter(Group.group_parent_id == None).all() | |
70 | .filter(Group.group_parent_id == None).all() |
|
|||
71 |
|
70 | |||
72 |
|
71 | |||
73 | return render('/index.html') |
|
72 | return render('/index.html') |
@@ -107,6 +107,11 b' class RhodeCodeUi(Base):' | |||||
107 | ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) |
|
107 | ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) | |
108 |
|
108 | |||
109 |
|
109 | |||
|
110 | @classmethod | |||
|
111 | def get_by_key(cls, key): | |||
|
112 | return Session.query(cls).filter(cls.ui_key == key) | |||
|
113 | ||||
|
114 | ||||
110 | class User(Base): |
|
115 | class User(Base): | |
111 | __tablename__ = 'users' |
|
116 | __tablename__ = 'users' | |
112 | __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True}) |
|
117 | __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True}) | |
@@ -296,7 +301,7 b' class Repository(Base):' | |||||
296 |
|
301 | |||
297 | class Group(Base): |
|
302 | class Group(Base): | |
298 | __tablename__ = 'groups' |
|
303 | __tablename__ = 'groups' | |
299 | __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},) |
|
304 | __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'), {'useexisting':True},) | |
300 | __mapper_args__ = {'order_by':'group_name'} |
|
305 | __mapper_args__ = {'order_by':'group_name'} | |
301 |
|
306 | |||
302 | group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) |
|
307 | group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) |
@@ -35,7 +35,6 b' from webhelpers.pylonslib.secure_form im' | |||||
35 | from rhodecode.lib.utils import repo_name_slug |
|
35 | from rhodecode.lib.utils import repo_name_slug | |
36 | from rhodecode.lib.auth import authenticate, get_crypt_password |
|
36 | from rhodecode.lib.auth import authenticate, get_crypt_password | |
37 | from rhodecode.lib.exceptions import LdapImportError |
|
37 | from rhodecode.lib.exceptions import LdapImportError | |
38 | from rhodecode.model import meta |
|
|||
39 | from rhodecode.model.user import UserModel |
|
38 | from rhodecode.model.user import UserModel | |
40 | from rhodecode.model.repo import RepoModel |
|
39 | from rhodecode.model.repo import RepoModel | |
41 | from rhodecode.model.db import User, UsersGroup, Group |
|
40 | from rhodecode.model.db import User, UsersGroup, Group | |
@@ -117,6 +116,27 b' def ValidUsersGroup(edit, old_data):' | |||||
117 | return _ValidUsersGroup |
|
116 | return _ValidUsersGroup | |
118 |
|
117 | |||
119 |
|
118 | |||
|
119 | def ValidReposGroup(edit, old_data): | |||
|
120 | ||||
|
121 | class _ValidReposGroup(formencode.validators.FancyValidator): | |||
|
122 | ||||
|
123 | def validate_python(self, value, state): | |||
|
124 | #TODO WRITE VALIDATIONS | |||
|
125 | group_name = value.get('repos_group_name') | |||
|
126 | parent_id = value.get('repos_group_parent') | |||
|
127 | ||||
|
128 | # slugify repo group just in case :) | |||
|
129 | slug = repo_name_slug(group_name) | |||
|
130 | ||||
|
131 | # check filesystem | |||
|
132 | gr = Group.query().filter(Group.group_name == slug)\ | |||
|
133 | .filter(Group.group_parent_id == parent_id).scalar() | |||
|
134 | ||||
|
135 | if gr: | |||
|
136 | e_dict = {'repos_group_name':_('This group already exists')} | |||
|
137 | raise formencode.Invalid('', value, state, | |||
|
138 | error_dict=e_dict) | |||
|
139 | return _ValidReposGroup | |||
120 |
|
140 | |||
121 | class ValidPassword(formencode.validators.FancyValidator): |
|
141 | class ValidPassword(formencode.validators.FancyValidator): | |
122 |
|
142 | |||
@@ -193,17 +213,13 b' class ValidAuth(formencode.validators.Fa' | |||||
193 | class ValidRepoUser(formencode.validators.FancyValidator): |
|
213 | class ValidRepoUser(formencode.validators.FancyValidator): | |
194 |
|
214 | |||
195 | def to_python(self, value, state): |
|
215 | def to_python(self, value, state): | |
196 | sa = meta.Session() |
|
|||
197 | try: |
|
216 | try: | |
198 |
self.user_db = |
|
217 | self.user_db = User.query()\ | |
199 | .filter(User.active == True)\ |
|
218 | .filter(User.active == True)\ | |
200 | .filter(User.username == value).one() |
|
219 | .filter(User.username == value).one() | |
201 | except Exception: |
|
220 | except Exception: | |
202 | raise formencode.Invalid(_('This username is not valid'), |
|
221 | raise formencode.Invalid(_('This username is not valid'), | |
203 | value, state) |
|
222 | value, state) | |
204 | finally: |
|
|||
205 | meta.Session.remove() |
|
|||
206 |
|
||||
207 | return value |
|
223 | return value | |
208 |
|
224 | |||
209 | def ValidRepoName(edit, old_data): |
|
225 | def ValidRepoName(edit, old_data): | |
@@ -222,6 +238,7 b' def ValidRepoName(edit, old_data):' | |||||
222 | gr = Group.get(value.get('repo_group')) |
|
238 | gr = Group.get(value.get('repo_group')) | |
223 | group_path = gr.full_path |
|
239 | group_path = gr.full_path | |
224 | # value needs to be aware of group name |
|
240 | # value needs to be aware of group name | |
|
241 | # it has to use '/' | |||
225 | repo_name_full = group_path + '/' + repo_name |
|
242 | repo_name_full = group_path + '/' + repo_name | |
226 | else: |
|
243 | else: | |
227 | group_path = '' |
|
244 | group_path = '' | |
@@ -250,13 +267,13 b' def ValidRepoName(edit, old_data):' | |||||
250 |
|
267 | |||
251 | return _ValidRepoName |
|
268 | return _ValidRepoName | |
252 |
|
269 | |||
253 |
def Slugify |
|
270 | def SlugifyName(): | |
254 |
class _Slugify |
|
271 | class _SlugifyName(formencode.validators.FancyValidator): | |
255 |
|
272 | |||
256 | def to_python(self, value, state): |
|
273 | def to_python(self, value, state): | |
257 | return repo_name_slug(value) |
|
274 | return repo_name_slug(value) | |
258 |
|
275 | |||
259 |
return _Slugify |
|
276 | return _SlugifyName | |
260 |
|
277 | |||
261 | def ValidCloneUri(): |
|
278 | def ValidCloneUri(): | |
262 | from mercurial.httprepo import httprepository, httpsrepository |
|
279 | from mercurial.httprepo import httprepository, httpsrepository | |
@@ -331,15 +348,14 b' class ValidPerms(formencode.validators.F' | |||||
331 | value['perms_new'] = perms_new |
|
348 | value['perms_new'] = perms_new | |
332 |
|
349 | |||
333 | #update permissions |
|
350 | #update permissions | |
334 | sa = meta.Session |
|
|||
335 | for k, v, t in perms_new: |
|
351 | for k, v, t in perms_new: | |
336 | try: |
|
352 | try: | |
337 | if t is 'user': |
|
353 | if t is 'user': | |
338 |
self.user_db = |
|
354 | self.user_db = User.query()\ | |
339 | .filter(User.active == True)\ |
|
355 | .filter(User.active == True)\ | |
340 | .filter(User.username == k).one() |
|
356 | .filter(User.username == k).one() | |
341 | if t is 'users_group': |
|
357 | if t is 'users_group': | |
342 |
self.user_db = |
|
358 | self.user_db = UsersGroup.query()\ | |
343 | .filter(UsersGroup.users_group_active == True)\ |
|
359 | .filter(UsersGroup.users_group_active == True)\ | |
344 | .filter(UsersGroup.users_group_name == k).one() |
|
360 | .filter(UsersGroup.users_group_name == k).one() | |
345 |
|
361 | |||
@@ -373,15 +389,11 b' def UniqSystemEmail(old_data):' | |||||
373 | def to_python(self, value, state): |
|
389 | def to_python(self, value, state): | |
374 | value = value.lower() |
|
390 | value = value.lower() | |
375 | if old_data.get('email') != value: |
|
391 | if old_data.get('email') != value: | |
376 | sa = meta.Session() |
|
392 | user = User.query().filter(User.email == value).scalar() | |
377 | try: |
|
|||
378 | user = sa.query(User).filter(User.email == value).scalar() |
|
|||
379 |
|
|
393 | if user: | |
380 |
|
|
394 | raise formencode.Invalid( | |
|
395 | _("This e-mail address is already taken"), | |||
381 |
|
|
396 | value, state) | |
382 | finally: |
|
|||
383 | meta.Session.remove() |
|
|||
384 |
|
||||
385 | return value |
|
397 | return value | |
386 |
|
398 | |||
387 | return _UniqSystemEmail |
|
399 | return _UniqSystemEmail | |
@@ -389,14 +401,10 b' def UniqSystemEmail(old_data):' | |||||
389 | class ValidSystemEmail(formencode.validators.FancyValidator): |
|
401 | class ValidSystemEmail(formencode.validators.FancyValidator): | |
390 | def to_python(self, value, state): |
|
402 | def to_python(self, value, state): | |
391 | value = value.lower() |
|
403 | value = value.lower() | |
392 | sa = meta.Session |
|
404 | user = User.query().filter(User.email == value).scalar() | |
393 | try: |
|
|||
394 | user = sa.query(User).filter(User.email == value).scalar() |
|
|||
395 |
|
|
405 | if user is None: | |
396 |
|
|
406 | raise formencode.Invalid(_("This e-mail address doesn't exist.") , | |
397 |
|
|
407 | value, state) | |
398 | finally: |
|
|||
399 | meta.Session.remove() |
|
|||
400 |
|
408 | |||
401 | return value |
|
409 | return value | |
402 |
|
410 | |||
@@ -489,6 +497,23 b' def UsersGroupForm(edit=False, old_data=' | |||||
489 |
|
497 | |||
490 | return _UsersGroupForm |
|
498 | return _UsersGroupForm | |
491 |
|
499 | |||
|
500 | def ReposGroupForm(edit=False, old_data={}, available_groups=[]): | |||
|
501 | class _ReposGroupForm(formencode.Schema): | |||
|
502 | allow_extra_fields = True | |||
|
503 | filter_extra_fields = True | |||
|
504 | ||||
|
505 | repos_group_name = All(UnicodeString(strip=True, min=1, not_empty=True), | |||
|
506 | SlugifyName()) | |||
|
507 | repos_group_description = UnicodeString(strip=True, min=1, | |||
|
508 | not_empty=True) | |||
|
509 | repos_group_parent = OneOf(available_groups, hideList=False, | |||
|
510 | testValueList=True, | |||
|
511 | if_missing=None, not_empty=False) | |||
|
512 | ||||
|
513 | chained_validators = [ValidReposGroup(edit, old_data)] | |||
|
514 | ||||
|
515 | return _ReposGroupForm | |||
|
516 | ||||
492 | def RegisterForm(edit=False, old_data={}): |
|
517 | def RegisterForm(edit=False, old_data={}): | |
493 | class _RegisterForm(formencode.Schema): |
|
518 | class _RegisterForm(formencode.Schema): | |
494 | allow_extra_fields = True |
|
519 | allow_extra_fields = True | |
@@ -519,7 +544,7 b' def RepoForm(edit=False, old_data={}, su' | |||||
519 | allow_extra_fields = True |
|
544 | allow_extra_fields = True | |
520 | filter_extra_fields = False |
|
545 | filter_extra_fields = False | |
521 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), |
|
546 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), | |
522 |
Slugify |
|
547 | SlugifyName()) | |
523 | clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False), |
|
548 | clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False), | |
524 | ValidCloneUri()()) |
|
549 | ValidCloneUri()()) | |
525 | repo_group = OneOf(repo_groups, hideList=True) |
|
550 | repo_group = OneOf(repo_groups, hideList=True) | |
@@ -541,7 +566,7 b' def RepoForkForm(edit=False, old_data={}' | |||||
541 | allow_extra_fields = True |
|
566 | allow_extra_fields = True | |
542 | filter_extra_fields = False |
|
567 | filter_extra_fields = False | |
543 | fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), |
|
568 | fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), | |
544 |
Slugify |
|
569 | SlugifyName()) | |
545 | description = UnicodeString(strip=True, min=1, not_empty=True) |
|
570 | description = UnicodeString(strip=True, min=1, not_empty=True) | |
546 | private = StringBoolean(if_missing=False) |
|
571 | private = StringBoolean(if_missing=False) | |
547 | repo_type = All(ValidForkType(old_data), OneOf(supported_backends)) |
|
572 | repo_type = All(ValidForkType(old_data), OneOf(supported_backends)) | |
@@ -552,7 +577,7 b' def RepoSettingsForm(edit=False, old_dat' | |||||
552 | allow_extra_fields = True |
|
577 | allow_extra_fields = True | |
553 | filter_extra_fields = False |
|
578 | filter_extra_fields = False | |
554 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), |
|
579 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), | |
555 |
Slugify |
|
580 | SlugifyName()) | |
556 | description = UnicodeString(strip=True, min=1, not_empty=True) |
|
581 | description = UnicodeString(strip=True, min=1, not_empty=True) | |
557 | private = StringBoolean(if_missing=False) |
|
582 | private = StringBoolean(if_missing=False) | |
558 |
|
583 |
@@ -477,6 +477,13 b' margin:0;' | |||||
477 | padding:12px 9px 7px 24px; |
|
477 | padding:12px 9px 7px 24px; | |
478 | } |
|
478 | } | |
479 |
|
479 | |||
|
480 | #header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover { | |||
|
481 | background:url("../images/icons/database_link.png") no-repeat scroll 4px 9px #FFF; | |||
|
482 | width:167px; | |||
|
483 | margin:0; | |||
|
484 | padding:12px 9px 7px 24px; | |||
|
485 | } | |||
|
486 | ||||
480 | #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover { |
|
487 | #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover { | |
481 | background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px; |
|
488 | background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px; | |
482 | width:167px; |
|
489 | width:167px; |
@@ -26,7 +26,6 b'' | |||||
26 | </div> |
|
26 | </div> | |
27 | <div class="input"> |
|
27 | <div class="input"> | |
28 | ${h.select('repo_group','',c.repo_groups,class_="medium")} |
|
28 | ${h.select('repo_group','',c.repo_groups,class_="medium")} | |
29 | <span>${h.link_to(_('add new group'),h.url(''))}</span> |
|
|||
30 | </div> |
|
29 | </div> | |
31 | </div> |
|
30 | </div> | |
32 | <div class="field"> |
|
31 | <div class="field"> |
@@ -49,7 +49,6 b'' | |||||
49 | </div> |
|
49 | </div> | |
50 | <div class="input"> |
|
50 | <div class="input"> | |
51 | ${h.select('repo_group','',c.repo_groups,class_="medium")} |
|
51 | ${h.select('repo_group','',c.repo_groups,class_="medium")} | |
52 | <span>${h.link_to(_('add new group'),h.url(''))}</span> |
|
|||
53 | </div> |
|
52 | </div> | |
54 | </div> |
|
53 | </div> | |
55 | <div class="field"> |
|
54 | <div class="field"> |
@@ -322,6 +322,7 b'' | |||||
322 | <ul> |
|
322 | <ul> | |
323 | <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li> |
|
323 | <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li> | |
324 | <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li> |
|
324 | <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li> | |
|
325 | <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li> | |||
325 | <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li> |
|
326 | <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li> | |
326 | <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li> |
|
327 | <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li> | |
327 | <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li> |
|
328 | <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li> |
General Comments 0
You need to be logged in to leave comments.
Login now