##// END OF EJS Templates
caches: flush cache when adding new objects so we can access them right away.
marcink -
r2852:3d46d13d default
parent child Browse files
Show More
@@ -1,205 +1,207 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import formencode
22 import formencode
23 import formencode.htmlfill
23 import formencode.htmlfill
24
24
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
26 from pyramid.view import view_config
26 from pyramid.view import view_config
27 from pyramid.renderers import render
27 from pyramid.renderers import render
28 from pyramid.response import Response
28 from pyramid.response import Response
29
29
30 from rhodecode import events
30 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31
32
32 from rhodecode.lib.ext_json import json
33 from rhodecode.lib.ext_json import json
33 from rhodecode.lib.auth import (
34 from rhodecode.lib.auth import (
34 LoginRequired, CSRFRequired, NotAnonymous,
35 LoginRequired, CSRFRequired, NotAnonymous,
35 HasPermissionAny, HasRepoGroupPermissionAny)
36 HasPermissionAny, HasRepoGroupPermissionAny)
36 from rhodecode.lib import helpers as h, audit_logger
37 from rhodecode.lib import helpers as h, audit_logger
37 from rhodecode.lib.utils2 import safe_int, safe_unicode
38 from rhodecode.lib.utils2 import safe_int, safe_unicode
38 from rhodecode.model.forms import RepoGroupForm
39 from rhodecode.model.forms import RepoGroupForm
39 from rhodecode.model.repo_group import RepoGroupModel
40 from rhodecode.model.repo_group import RepoGroupModel
40 from rhodecode.model.scm import RepoGroupList
41 from rhodecode.model.scm import RepoGroupList
41 from rhodecode.model.db import Session, RepoGroup
42 from rhodecode.model.db import Session, RepoGroup
42
43
43 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
44
45
45
46
46 class AdminRepoGroupsView(BaseAppView, DataGridAppView):
47 class AdminRepoGroupsView(BaseAppView, DataGridAppView):
47
48
48 def load_default_context(self):
49 def load_default_context(self):
49 c = self._get_local_tmpl_context()
50 c = self._get_local_tmpl_context()
50
51
51 return c
52 return c
52
53
53 def _load_form_data(self, c):
54 def _load_form_data(self, c):
54 allow_empty_group = False
55 allow_empty_group = False
55
56
56 if self._can_create_repo_group():
57 if self._can_create_repo_group():
57 # we're global admin, we're ok and we can create TOP level groups
58 # we're global admin, we're ok and we can create TOP level groups
58 allow_empty_group = True
59 allow_empty_group = True
59
60
60 # override the choices for this form, we need to filter choices
61 # override the choices for this form, we need to filter choices
61 # and display only those we have ADMIN right
62 # and display only those we have ADMIN right
62 groups_with_admin_rights = RepoGroupList(
63 groups_with_admin_rights = RepoGroupList(
63 RepoGroup.query().all(),
64 RepoGroup.query().all(),
64 perm_set=['group.admin'])
65 perm_set=['group.admin'])
65 c.repo_groups = RepoGroup.groups_choices(
66 c.repo_groups = RepoGroup.groups_choices(
66 groups=groups_with_admin_rights,
67 groups=groups_with_admin_rights,
67 show_empty_group=allow_empty_group)
68 show_empty_group=allow_empty_group)
68
69
69 def _can_create_repo_group(self, parent_group_id=None):
70 def _can_create_repo_group(self, parent_group_id=None):
70 is_admin = HasPermissionAny('hg.admin')('group create controller')
71 is_admin = HasPermissionAny('hg.admin')('group create controller')
71 create_repo_group = HasPermissionAny(
72 create_repo_group = HasPermissionAny(
72 'hg.repogroup.create.true')('group create controller')
73 'hg.repogroup.create.true')('group create controller')
73 if is_admin or (create_repo_group and not parent_group_id):
74 if is_admin or (create_repo_group and not parent_group_id):
74 # we're global admin, or we have global repo group create
75 # we're global admin, or we have global repo group create
75 # permission
76 # permission
76 # we're ok and we can create TOP level groups
77 # we're ok and we can create TOP level groups
77 return True
78 return True
78 elif parent_group_id:
79 elif parent_group_id:
79 # we check the permission if we can write to parent group
80 # we check the permission if we can write to parent group
80 group = RepoGroup.get(parent_group_id)
81 group = RepoGroup.get(parent_group_id)
81 group_name = group.group_name if group else None
82 group_name = group.group_name if group else None
82 if HasRepoGroupPermissionAny('group.admin')(
83 if HasRepoGroupPermissionAny('group.admin')(
83 group_name, 'check if user is an admin of group'):
84 group_name, 'check if user is an admin of group'):
84 # we're an admin of passed in group, we're ok.
85 # we're an admin of passed in group, we're ok.
85 return True
86 return True
86 else:
87 else:
87 return False
88 return False
88 return False
89 return False
89
90
90 @LoginRequired()
91 @LoginRequired()
91 @NotAnonymous()
92 @NotAnonymous()
92 # perms check inside
93 # perms check inside
93 @view_config(
94 @view_config(
94 route_name='repo_groups', request_method='GET',
95 route_name='repo_groups', request_method='GET',
95 renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako')
96 renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako')
96 def repo_group_list(self):
97 def repo_group_list(self):
97 c = self.load_default_context()
98 c = self.load_default_context()
98
99
99 repo_group_list = RepoGroup.get_all_repo_groups()
100 repo_group_list = RepoGroup.get_all_repo_groups()
100 repo_group_list_acl = RepoGroupList(
101 repo_group_list_acl = RepoGroupList(
101 repo_group_list, perm_set=['group.admin'])
102 repo_group_list, perm_set=['group.admin'])
102 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
103 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
103 repo_group_list=repo_group_list_acl, admin=True)
104 repo_group_list=repo_group_list_acl, admin=True)
104 c.data = json.dumps(repo_group_data)
105 c.data = json.dumps(repo_group_data)
105 return self._get_template_context(c)
106 return self._get_template_context(c)
106
107
107 @LoginRequired()
108 @LoginRequired()
108 @NotAnonymous()
109 @NotAnonymous()
109 # perm checks inside
110 # perm checks inside
110 @view_config(
111 @view_config(
111 route_name='repo_group_new', request_method='GET',
112 route_name='repo_group_new', request_method='GET',
112 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
113 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
113 def repo_group_new(self):
114 def repo_group_new(self):
114 c = self.load_default_context()
115 c = self.load_default_context()
115
116
116 # perm check for admin, create_group perm or admin of parent_group
117 # perm check for admin, create_group perm or admin of parent_group
117 parent_group_id = safe_int(self.request.GET.get('parent_group'))
118 parent_group_id = safe_int(self.request.GET.get('parent_group'))
118 if not self._can_create_repo_group(parent_group_id):
119 if not self._can_create_repo_group(parent_group_id):
119 raise HTTPForbidden()
120 raise HTTPForbidden()
120
121
121 self._load_form_data(c)
122 self._load_form_data(c)
122
123
123 defaults = {} # Future proof for default of repo group
124 defaults = {} # Future proof for default of repo group
124 data = render(
125 data = render(
125 'rhodecode:templates/admin/repo_groups/repo_group_add.mako',
126 'rhodecode:templates/admin/repo_groups/repo_group_add.mako',
126 self._get_template_context(c), self.request)
127 self._get_template_context(c), self.request)
127 html = formencode.htmlfill.render(
128 html = formencode.htmlfill.render(
128 data,
129 data,
129 defaults=defaults,
130 defaults=defaults,
130 encoding="UTF-8",
131 encoding="UTF-8",
131 force_defaults=False
132 force_defaults=False
132 )
133 )
133 return Response(html)
134 return Response(html)
134
135
135 @LoginRequired()
136 @LoginRequired()
136 @NotAnonymous()
137 @NotAnonymous()
137 @CSRFRequired()
138 @CSRFRequired()
138 # perm checks inside
139 # perm checks inside
139 @view_config(
140 @view_config(
140 route_name='repo_group_create', request_method='POST',
141 route_name='repo_group_create', request_method='POST',
141 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
142 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
142 def repo_group_create(self):
143 def repo_group_create(self):
143 c = self.load_default_context()
144 c = self.load_default_context()
144 _ = self.request.translate
145 _ = self.request.translate
145
146
146 parent_group_id = safe_int(self.request.POST.get('group_parent_id'))
147 parent_group_id = safe_int(self.request.POST.get('group_parent_id'))
147 can_create = self._can_create_repo_group(parent_group_id)
148 can_create = self._can_create_repo_group(parent_group_id)
148
149
149 self._load_form_data(c)
150 self._load_form_data(c)
150 # permissions for can create group based on parent_id are checked
151 # permissions for can create group based on parent_id are checked
151 # here in the Form
152 # here in the Form
152 available_groups = map(lambda k: safe_unicode(k[0]), c.repo_groups)
153 available_groups = map(lambda k: safe_unicode(k[0]), c.repo_groups)
153 repo_group_form = RepoGroupForm(
154 repo_group_form = RepoGroupForm(
154 self.request.translate, available_groups=available_groups,
155 self.request.translate, available_groups=available_groups,
155 can_create_in_root=can_create)()
156 can_create_in_root=can_create)()
156
157
157 repo_group_name = self.request.POST.get('group_name')
158 repo_group_name = self.request.POST.get('group_name')
158 try:
159 try:
159 owner = self._rhodecode_user
160 owner = self._rhodecode_user
160 form_result = repo_group_form.to_python(dict(self.request.POST))
161 form_result = repo_group_form.to_python(dict(self.request.POST))
161 repo_group = RepoGroupModel().create(
162 repo_group = RepoGroupModel().create(
162 group_name=form_result['group_name_full'],
163 group_name=form_result['group_name_full'],
163 group_description=form_result['group_description'],
164 group_description=form_result['group_description'],
164 owner=owner.user_id,
165 owner=owner.user_id,
165 copy_permissions=form_result['group_copy_permissions']
166 copy_permissions=form_result['group_copy_permissions']
166 )
167 )
167 Session().flush()
168 Session().flush()
168
169
169 repo_group_data = repo_group.get_api_data()
170 repo_group_data = repo_group.get_api_data()
170 audit_logger.store_web(
171 audit_logger.store_web(
171 'repo_group.create', action_data={'data': repo_group_data},
172 'repo_group.create', action_data={'data': repo_group_data},
172 user=self._rhodecode_user)
173 user=self._rhodecode_user)
173
174
174 Session().commit()
175 Session().commit()
175
176
176 _new_group_name = form_result['group_name_full']
177 _new_group_name = form_result['group_name_full']
177
178
178 repo_group_url = h.link_to(
179 repo_group_url = h.link_to(
179 _new_group_name,
180 _new_group_name,
180 h.route_path('repo_group_home', repo_group_name=_new_group_name))
181 h.route_path('repo_group_home', repo_group_name=_new_group_name))
181 h.flash(h.literal(_('Created repository group %s')
182 h.flash(h.literal(_('Created repository group %s')
182 % repo_group_url), category='success')
183 % repo_group_url), category='success')
183
184
184 except formencode.Invalid as errors:
185 except formencode.Invalid as errors:
185 data = render(
186 data = render(
186 'rhodecode:templates/admin/repo_groups/repo_group_add.mako',
187 'rhodecode:templates/admin/repo_groups/repo_group_add.mako',
187 self._get_template_context(c), self.request)
188 self._get_template_context(c), self.request)
188 html = formencode.htmlfill.render(
189 html = formencode.htmlfill.render(
189 data,
190 data,
190 defaults=errors.value,
191 defaults=errors.value,
191 errors=errors.error_dict or {},
192 errors=errors.error_dict or {},
192 prefix_error=False,
193 prefix_error=False,
193 encoding="UTF-8",
194 encoding="UTF-8",
194 force_defaults=False
195 force_defaults=False
195 )
196 )
196 return Response(html)
197 return Response(html)
197 except Exception:
198 except Exception:
198 log.exception("Exception during creation of repository group")
199 log.exception("Exception during creation of repository group")
199 h.flash(_('Error occurred during creation of repository group %s')
200 h.flash(_('Error occurred during creation of repository group %s')
200 % repo_group_name, category='error')
201 % repo_group_name, category='error')
201 raise HTTPFound(h.route_path('home'))
202 raise HTTPFound(h.route_path('home'))
202
203
204 events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id]))
203 raise HTTPFound(
205 raise HTTPFound(
204 h.route_path('repo_group_home',
206 h.route_path('repo_group_home',
205 repo_group_name=form_result['group_name_full']))
207 repo_group_name=form_result['group_name_full']))
@@ -1,181 +1,184 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import formencode
22 import formencode
23 import formencode.htmlfill
23 import formencode.htmlfill
24
24
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
26 from pyramid.view import view_config
26 from pyramid.view import view_config
27 from pyramid.renderers import render
27 from pyramid.renderers import render
28 from pyramid.response import Response
28 from pyramid.response import Response
29
29
30 from rhodecode import events
30 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.lib.celerylib.utils import get_task_id
32 from rhodecode.lib.celerylib.utils import get_task_id
32
33
33 from rhodecode.lib.ext_json import json
34 from rhodecode.lib.ext_json import json
34 from rhodecode.lib.auth import (
35 from rhodecode.lib.auth import (
35 LoginRequired, CSRFRequired, NotAnonymous,
36 LoginRequired, CSRFRequired, NotAnonymous,
36 HasPermissionAny, HasRepoGroupPermissionAny)
37 HasPermissionAny, HasRepoGroupPermissionAny)
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib.utils import repo_name_slug
39 from rhodecode.lib.utils import repo_name_slug
39 from rhodecode.lib.utils2 import safe_int, safe_unicode
40 from rhodecode.lib.utils2 import safe_int, safe_unicode
40 from rhodecode.model.forms import RepoForm
41 from rhodecode.model.forms import RepoForm
41 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
43 from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
43 from rhodecode.model.settings import SettingsModel
44 from rhodecode.model.settings import SettingsModel
44 from rhodecode.model.db import Repository, RepoGroup
45 from rhodecode.model.db import Repository, RepoGroup
45
46
46 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
47
48
48
49
49 class AdminReposView(BaseAppView, DataGridAppView):
50 class AdminReposView(BaseAppView, DataGridAppView):
50
51
51 def load_default_context(self):
52 def load_default_context(self):
52 c = self._get_local_tmpl_context()
53 c = self._get_local_tmpl_context()
53
54
54 return c
55 return c
55
56
56 def _load_form_data(self, c):
57 def _load_form_data(self, c):
57 acl_groups = RepoGroupList(RepoGroup.query().all(),
58 acl_groups = RepoGroupList(RepoGroup.query().all(),
58 perm_set=['group.write', 'group.admin'])
59 perm_set=['group.write', 'group.admin'])
59 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
60 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
60 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
61 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
61 c.landing_revs_choices, c.landing_revs = \
62 c.landing_revs_choices, c.landing_revs = \
62 ScmModel().get_repo_landing_revs(self.request.translate)
63 ScmModel().get_repo_landing_revs(self.request.translate)
63 c.personal_repo_group = self._rhodecode_user.personal_repo_group
64 c.personal_repo_group = self._rhodecode_user.personal_repo_group
64
65
65 @LoginRequired()
66 @LoginRequired()
66 @NotAnonymous()
67 @NotAnonymous()
67 # perms check inside
68 # perms check inside
68 @view_config(
69 @view_config(
69 route_name='repos', request_method='GET',
70 route_name='repos', request_method='GET',
70 renderer='rhodecode:templates/admin/repos/repos.mako')
71 renderer='rhodecode:templates/admin/repos/repos.mako')
71 def repository_list(self):
72 def repository_list(self):
72 c = self.load_default_context()
73 c = self.load_default_context()
73
74
74 repo_list = Repository.get_all_repos()
75 repo_list = Repository.get_all_repos()
75 c.repo_list = RepoList(repo_list, perm_set=['repository.admin'])
76 c.repo_list = RepoList(repo_list, perm_set=['repository.admin'])
76 repos_data = RepoModel().get_repos_as_dict(
77 repos_data = RepoModel().get_repos_as_dict(
77 repo_list=c.repo_list, admin=True, super_user_actions=True)
78 repo_list=c.repo_list, admin=True, super_user_actions=True)
78 # json used to render the grid
79 # json used to render the grid
79 c.data = json.dumps(repos_data)
80 c.data = json.dumps(repos_data)
80
81
81 return self._get_template_context(c)
82 return self._get_template_context(c)
82
83
83 @LoginRequired()
84 @LoginRequired()
84 @NotAnonymous()
85 @NotAnonymous()
85 # perms check inside
86 # perms check inside
86 @view_config(
87 @view_config(
87 route_name='repo_new', request_method='GET',
88 route_name='repo_new', request_method='GET',
88 renderer='rhodecode:templates/admin/repos/repo_add.mako')
89 renderer='rhodecode:templates/admin/repos/repo_add.mako')
89 def repository_new(self):
90 def repository_new(self):
90 c = self.load_default_context()
91 c = self.load_default_context()
91
92
92 new_repo = self.request.GET.get('repo', '')
93 new_repo = self.request.GET.get('repo', '')
93 parent_group = safe_int(self.request.GET.get('parent_group'))
94 parent_group = safe_int(self.request.GET.get('parent_group'))
94 _gr = RepoGroup.get(parent_group)
95 _gr = RepoGroup.get(parent_group)
95
96
96 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
97 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
97 # you're not super admin nor have global create permissions,
98 # you're not super admin nor have global create permissions,
98 # but maybe you have at least write permission to a parent group ?
99 # but maybe you have at least write permission to a parent group ?
99
100
100 gr_name = _gr.group_name if _gr else None
101 gr_name = _gr.group_name if _gr else None
101 # create repositories with write permission on group is set to true
102 # create repositories with write permission on group is set to true
102 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
103 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
103 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
104 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
104 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
105 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
105 if not (group_admin or (group_write and create_on_write)):
106 if not (group_admin or (group_write and create_on_write)):
106 raise HTTPForbidden()
107 raise HTTPForbidden()
107
108
108 self._load_form_data(c)
109 self._load_form_data(c)
109 c.new_repo = repo_name_slug(new_repo)
110 c.new_repo = repo_name_slug(new_repo)
110
111
111 # apply the defaults from defaults page
112 # apply the defaults from defaults page
112 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
113 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
113 # set checkbox to autochecked
114 # set checkbox to autochecked
114 defaults['repo_copy_permissions'] = True
115 defaults['repo_copy_permissions'] = True
115
116
116 parent_group_choice = '-1'
117 parent_group_choice = '-1'
117 if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
118 if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
118 parent_group_choice = self._rhodecode_user.personal_repo_group
119 parent_group_choice = self._rhodecode_user.personal_repo_group
119
120
120 if parent_group and _gr:
121 if parent_group and _gr:
121 if parent_group in [x[0] for x in c.repo_groups]:
122 if parent_group in [x[0] for x in c.repo_groups]:
122 parent_group_choice = safe_unicode(parent_group)
123 parent_group_choice = safe_unicode(parent_group)
123
124
124 defaults.update({'repo_group': parent_group_choice})
125 defaults.update({'repo_group': parent_group_choice})
125
126
126 data = render('rhodecode:templates/admin/repos/repo_add.mako',
127 data = render('rhodecode:templates/admin/repos/repo_add.mako',
127 self._get_template_context(c), self.request)
128 self._get_template_context(c), self.request)
128 html = formencode.htmlfill.render(
129 html = formencode.htmlfill.render(
129 data,
130 data,
130 defaults=defaults,
131 defaults=defaults,
131 encoding="UTF-8",
132 encoding="UTF-8",
132 force_defaults=False
133 force_defaults=False
133 )
134 )
134 return Response(html)
135 return Response(html)
135
136
136 @LoginRequired()
137 @LoginRequired()
137 @NotAnonymous()
138 @NotAnonymous()
138 @CSRFRequired()
139 @CSRFRequired()
139 # perms check inside
140 # perms check inside
140 @view_config(
141 @view_config(
141 route_name='repo_create', request_method='POST',
142 route_name='repo_create', request_method='POST',
142 renderer='rhodecode:templates/admin/repos/repos.mako')
143 renderer='rhodecode:templates/admin/repos/repos.mako')
143 def repository_create(self):
144 def repository_create(self):
144 c = self.load_default_context()
145 c = self.load_default_context()
145
146
146 form_result = {}
147 form_result = {}
147 self._load_form_data(c)
148 self._load_form_data(c)
148 task_id = None
149 task_id = None
149 try:
150 try:
150 # CanWriteToGroup validators checks permissions of this POST
151 # CanWriteToGroup validators checks permissions of this POST
151 form = RepoForm(
152 form = RepoForm(
152 self.request.translate, repo_groups=c.repo_groups_choices,
153 self.request.translate, repo_groups=c.repo_groups_choices,
153 landing_revs=c.landing_revs_choices)()
154 landing_revs=c.landing_revs_choices)()
154 form_result = form.to_python(dict(self.request.POST))
155 form_result = form.to_python(dict(self.request.POST))
155
156
156 # create is done sometimes async on celery, db transaction
157 # create is done sometimes async on celery, db transaction
157 # management is handled there.
158 # management is handled there.
158 task = RepoModel().create(form_result, self._rhodecode_user.user_id)
159 task = RepoModel().create(form_result, self._rhodecode_user.user_id)
159 task_id = get_task_id(task)
160 task_id = get_task_id(task)
160 except formencode.Invalid as errors:
161 except formencode.Invalid as errors:
161 data = render('rhodecode:templates/admin/repos/repo_add.mako',
162 data = render('rhodecode:templates/admin/repos/repo_add.mako',
162 self._get_template_context(c), self.request)
163 self._get_template_context(c), self.request)
163 html = formencode.htmlfill.render(
164 html = formencode.htmlfill.render(
164 data,
165 data,
165 defaults=errors.value,
166 defaults=errors.value,
166 errors=errors.error_dict or {},
167 errors=errors.error_dict or {},
167 prefix_error=False,
168 prefix_error=False,
168 encoding="UTF-8",
169 encoding="UTF-8",
169 force_defaults=False
170 force_defaults=False
170 )
171 )
171 return Response(html)
172 return Response(html)
172
173
173 except Exception as e:
174 except Exception as e:
174 msg = self._log_creation_exception(e, form_result.get('repo_name'))
175 msg = self._log_creation_exception(e, form_result.get('repo_name'))
175 h.flash(msg, category='error')
176 h.flash(msg, category='error')
176 raise HTTPFound(h.route_path('home'))
177 raise HTTPFound(h.route_path('home'))
177
178
179 events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id]))
180
178 raise HTTPFound(
181 raise HTTPFound(
179 h.route_path('repo_creating',
182 h.route_path('repo_creating',
180 repo_name=form_result['repo_name_full'],
183 repo_name=form_result['repo_name_full'],
181 _query=dict(task_id=task_id)))
184 _query=dict(task_id=task_id)))
@@ -1,257 +1,259 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 import formencode
23 import formencode
24 import formencode.htmlfill
24 import formencode.htmlfill
25
25
26 from pyramid.httpexceptions import HTTPFound
26 from pyramid.httpexceptions import HTTPFound
27 from pyramid.view import view_config
27 from pyramid.view import view_config
28 from pyramid.response import Response
28 from pyramid.response import Response
29 from pyramid.renderers import render
29 from pyramid.renderers import render
30
30
31 from rhodecode import events
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
33 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
34 LoginRequired, NotAnonymous, CSRFRequired, HasPermissionAnyDecorator)
34 from rhodecode.lib import helpers as h, audit_logger
35 from rhodecode.lib import helpers as h, audit_logger
35 from rhodecode.lib.utils2 import safe_unicode
36 from rhodecode.lib.utils2 import safe_unicode
36
37
37 from rhodecode.model.forms import UserGroupForm
38 from rhodecode.model.forms import UserGroupForm
38 from rhodecode.model.permission import PermissionModel
39 from rhodecode.model.permission import PermissionModel
39 from rhodecode.model.scm import UserGroupList
40 from rhodecode.model.scm import UserGroupList
40 from rhodecode.model.db import (
41 from rhodecode.model.db import (
41 or_, count, User, UserGroup, UserGroupMember)
42 or_, count, User, UserGroup, UserGroupMember)
42 from rhodecode.model.meta import Session
43 from rhodecode.model.meta import Session
43 from rhodecode.model.user_group import UserGroupModel
44 from rhodecode.model.user_group import UserGroupModel
44 from rhodecode.model.db import true
45 from rhodecode.model.db import true
45
46
46 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
47
48
48
49
49 class AdminUserGroupsView(BaseAppView, DataGridAppView):
50 class AdminUserGroupsView(BaseAppView, DataGridAppView):
50
51
51 def load_default_context(self):
52 def load_default_context(self):
52 c = self._get_local_tmpl_context()
53 c = self._get_local_tmpl_context()
53
54
54 PermissionModel().set_global_permission_choices(
55 PermissionModel().set_global_permission_choices(
55 c, gettext_translator=self.request.translate)
56 c, gettext_translator=self.request.translate)
56
57
57 return c
58 return c
58
59
59 # permission check in data loading of
60 # permission check in data loading of
60 # `user_groups_list_data` via UserGroupList
61 # `user_groups_list_data` via UserGroupList
61 @LoginRequired()
62 @LoginRequired()
62 @NotAnonymous()
63 @NotAnonymous()
63 @view_config(
64 @view_config(
64 route_name='user_groups', request_method='GET',
65 route_name='user_groups', request_method='GET',
65 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
66 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
66 def user_groups_list(self):
67 def user_groups_list(self):
67 c = self.load_default_context()
68 c = self.load_default_context()
68 return self._get_template_context(c)
69 return self._get_template_context(c)
69
70
70 # permission check inside
71 # permission check inside
71 @LoginRequired()
72 @LoginRequired()
72 @NotAnonymous()
73 @NotAnonymous()
73 @view_config(
74 @view_config(
74 route_name='user_groups_data', request_method='GET',
75 route_name='user_groups_data', request_method='GET',
75 renderer='json_ext', xhr=True)
76 renderer='json_ext', xhr=True)
76 def user_groups_list_data(self):
77 def user_groups_list_data(self):
77 self.load_default_context()
78 self.load_default_context()
78 column_map = {
79 column_map = {
79 'active': 'users_group_active',
80 'active': 'users_group_active',
80 'description': 'user_group_description',
81 'description': 'user_group_description',
81 'members': 'members_total',
82 'members': 'members_total',
82 'owner': 'user_username',
83 'owner': 'user_username',
83 'sync': 'group_data'
84 'sync': 'group_data'
84 }
85 }
85 draw, start, limit = self._extract_chunk(self.request)
86 draw, start, limit = self._extract_chunk(self.request)
86 search_q, order_by, order_dir = self._extract_ordering(
87 search_q, order_by, order_dir = self._extract_ordering(
87 self.request, column_map=column_map)
88 self.request, column_map=column_map)
88
89
89 _render = self.request.get_partial_renderer(
90 _render = self.request.get_partial_renderer(
90 'rhodecode:templates/data_table/_dt_elements.mako')
91 'rhodecode:templates/data_table/_dt_elements.mako')
91
92
92 def user_group_name(user_group_name):
93 def user_group_name(user_group_name):
93 return _render("user_group_name", user_group_name)
94 return _render("user_group_name", user_group_name)
94
95
95 def user_group_actions(user_group_id, user_group_name):
96 def user_group_actions(user_group_id, user_group_name):
96 return _render("user_group_actions", user_group_id, user_group_name)
97 return _render("user_group_actions", user_group_id, user_group_name)
97
98
98 def user_profile(username):
99 def user_profile(username):
99 return _render('user_profile', username)
100 return _render('user_profile', username)
100
101
101 auth_user_group_list = UserGroupList(
102 auth_user_group_list = UserGroupList(
102 UserGroup.query().all(), perm_set=['usergroup.admin'])
103 UserGroup.query().all(), perm_set=['usergroup.admin'])
103
104
104 allowed_ids = [-1]
105 allowed_ids = [-1]
105 for user_group in auth_user_group_list:
106 for user_group in auth_user_group_list:
106 allowed_ids.append(user_group.users_group_id)
107 allowed_ids.append(user_group.users_group_id)
107
108
108 user_groups_data_total_count = UserGroup.query()\
109 user_groups_data_total_count = UserGroup.query()\
109 .filter(UserGroup.users_group_id.in_(allowed_ids))\
110 .filter(UserGroup.users_group_id.in_(allowed_ids))\
110 .count()
111 .count()
111
112
112 user_groups_data_total_inactive_count = UserGroup.query()\
113 user_groups_data_total_inactive_count = UserGroup.query()\
113 .filter(UserGroup.users_group_id.in_(allowed_ids))\
114 .filter(UserGroup.users_group_id.in_(allowed_ids))\
114 .filter(UserGroup.users_group_active != true()).count()
115 .filter(UserGroup.users_group_active != true()).count()
115
116
116 member_count = count(UserGroupMember.user_id)
117 member_count = count(UserGroupMember.user_id)
117 base_q = Session.query(
118 base_q = Session.query(
118 UserGroup.users_group_name,
119 UserGroup.users_group_name,
119 UserGroup.user_group_description,
120 UserGroup.user_group_description,
120 UserGroup.users_group_active,
121 UserGroup.users_group_active,
121 UserGroup.users_group_id,
122 UserGroup.users_group_id,
122 UserGroup.group_data,
123 UserGroup.group_data,
123 User,
124 User,
124 member_count.label('member_count')
125 member_count.label('member_count')
125 ) \
126 ) \
126 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
127 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
127 .outerjoin(UserGroupMember) \
128 .outerjoin(UserGroupMember) \
128 .join(User, User.user_id == UserGroup.user_id) \
129 .join(User, User.user_id == UserGroup.user_id) \
129 .group_by(UserGroup, User)
130 .group_by(UserGroup, User)
130
131
131 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
132 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
132
133
133 if search_q:
134 if search_q:
134 like_expression = u'%{}%'.format(safe_unicode(search_q))
135 like_expression = u'%{}%'.format(safe_unicode(search_q))
135 base_q = base_q.filter(or_(
136 base_q = base_q.filter(or_(
136 UserGroup.users_group_name.ilike(like_expression),
137 UserGroup.users_group_name.ilike(like_expression),
137 ))
138 ))
138 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
139 base_q_inactive = base_q.filter(UserGroup.users_group_active != true())
139
140
140 user_groups_data_total_filtered_count = base_q.count()
141 user_groups_data_total_filtered_count = base_q.count()
141 user_groups_data_total_filtered_inactive_count = base_q_inactive.count()
142 user_groups_data_total_filtered_inactive_count = base_q_inactive.count()
142
143
143 if order_by == 'members_total':
144 if order_by == 'members_total':
144 sort_col = member_count
145 sort_col = member_count
145 elif order_by == 'user_username':
146 elif order_by == 'user_username':
146 sort_col = User.username
147 sort_col = User.username
147 else:
148 else:
148 sort_col = getattr(UserGroup, order_by, None)
149 sort_col = getattr(UserGroup, order_by, None)
149
150
150 if isinstance(sort_col, count) or sort_col:
151 if isinstance(sort_col, count) or sort_col:
151 if order_dir == 'asc':
152 if order_dir == 'asc':
152 sort_col = sort_col.asc()
153 sort_col = sort_col.asc()
153 else:
154 else:
154 sort_col = sort_col.desc()
155 sort_col = sort_col.desc()
155
156
156 base_q = base_q.order_by(sort_col)
157 base_q = base_q.order_by(sort_col)
157 base_q = base_q.offset(start).limit(limit)
158 base_q = base_q.offset(start).limit(limit)
158
159
159 # authenticated access to user groups
160 # authenticated access to user groups
160 auth_user_group_list = base_q.all()
161 auth_user_group_list = base_q.all()
161
162
162 user_groups_data = []
163 user_groups_data = []
163 for user_gr in auth_user_group_list:
164 for user_gr in auth_user_group_list:
164 user_groups_data.append({
165 user_groups_data.append({
165 "users_group_name": user_group_name(user_gr.users_group_name),
166 "users_group_name": user_group_name(user_gr.users_group_name),
166 "name_raw": h.escape(user_gr.users_group_name),
167 "name_raw": h.escape(user_gr.users_group_name),
167 "description": h.escape(user_gr.user_group_description),
168 "description": h.escape(user_gr.user_group_description),
168 "members": user_gr.member_count,
169 "members": user_gr.member_count,
169 # NOTE(marcink): because of advanced query we
170 # NOTE(marcink): because of advanced query we
170 # need to load it like that
171 # need to load it like that
171 "sync": UserGroup._load_sync(
172 "sync": UserGroup._load_sync(
172 UserGroup._load_group_data(user_gr.group_data)),
173 UserGroup._load_group_data(user_gr.group_data)),
173 "active": h.bool2icon(user_gr.users_group_active),
174 "active": h.bool2icon(user_gr.users_group_active),
174 "owner": user_profile(user_gr.User.username),
175 "owner": user_profile(user_gr.User.username),
175 "action": user_group_actions(
176 "action": user_group_actions(
176 user_gr.users_group_id, user_gr.users_group_name)
177 user_gr.users_group_id, user_gr.users_group_name)
177 })
178 })
178
179
179 data = ({
180 data = ({
180 'draw': draw,
181 'draw': draw,
181 'data': user_groups_data,
182 'data': user_groups_data,
182 'recordsTotal': user_groups_data_total_count,
183 'recordsTotal': user_groups_data_total_count,
183 'recordsTotalInactive': user_groups_data_total_inactive_count,
184 'recordsTotalInactive': user_groups_data_total_inactive_count,
184 'recordsFiltered': user_groups_data_total_filtered_count,
185 'recordsFiltered': user_groups_data_total_filtered_count,
185 'recordsFilteredInactive': user_groups_data_total_filtered_inactive_count,
186 'recordsFilteredInactive': user_groups_data_total_filtered_inactive_count,
186 })
187 })
187
188
188 return data
189 return data
189
190
190 @LoginRequired()
191 @LoginRequired()
191 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
192 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
192 @view_config(
193 @view_config(
193 route_name='user_groups_new', request_method='GET',
194 route_name='user_groups_new', request_method='GET',
194 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
195 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
195 def user_groups_new(self):
196 def user_groups_new(self):
196 c = self.load_default_context()
197 c = self.load_default_context()
197 return self._get_template_context(c)
198 return self._get_template_context(c)
198
199
199 @LoginRequired()
200 @LoginRequired()
200 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
201 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
201 @CSRFRequired()
202 @CSRFRequired()
202 @view_config(
203 @view_config(
203 route_name='user_groups_create', request_method='POST',
204 route_name='user_groups_create', request_method='POST',
204 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
205 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
205 def user_groups_create(self):
206 def user_groups_create(self):
206 _ = self.request.translate
207 _ = self.request.translate
207 c = self.load_default_context()
208 c = self.load_default_context()
208 users_group_form = UserGroupForm(self.request.translate)()
209 users_group_form = UserGroupForm(self.request.translate)()
209
210
210 user_group_name = self.request.POST.get('users_group_name')
211 user_group_name = self.request.POST.get('users_group_name')
211 try:
212 try:
212 form_result = users_group_form.to_python(dict(self.request.POST))
213 form_result = users_group_form.to_python(dict(self.request.POST))
213 user_group = UserGroupModel().create(
214 user_group = UserGroupModel().create(
214 name=form_result['users_group_name'],
215 name=form_result['users_group_name'],
215 description=form_result['user_group_description'],
216 description=form_result['user_group_description'],
216 owner=self._rhodecode_user.user_id,
217 owner=self._rhodecode_user.user_id,
217 active=form_result['users_group_active'])
218 active=form_result['users_group_active'])
218 Session().flush()
219 Session().flush()
219 creation_data = user_group.get_api_data()
220 creation_data = user_group.get_api_data()
220 user_group_name = form_result['users_group_name']
221 user_group_name = form_result['users_group_name']
221
222
222 audit_logger.store_web(
223 audit_logger.store_web(
223 'user_group.create', action_data={'data': creation_data},
224 'user_group.create', action_data={'data': creation_data},
224 user=self._rhodecode_user)
225 user=self._rhodecode_user)
225
226
226 user_group_link = h.link_to(
227 user_group_link = h.link_to(
227 h.escape(user_group_name),
228 h.escape(user_group_name),
228 h.route_path(
229 h.route_path(
229 'edit_user_group', user_group_id=user_group.users_group_id))
230 'edit_user_group', user_group_id=user_group.users_group_id))
230 h.flash(h.literal(_('Created user group %(user_group_link)s')
231 h.flash(h.literal(_('Created user group %(user_group_link)s')
231 % {'user_group_link': user_group_link}),
232 % {'user_group_link': user_group_link}),
232 category='success')
233 category='success')
233 Session().commit()
234 Session().commit()
234 user_group_id = user_group.users_group_id
235 user_group_id = user_group.users_group_id
235 except formencode.Invalid as errors:
236 except formencode.Invalid as errors:
236
237
237 data = render(
238 data = render(
238 'rhodecode:templates/admin/user_groups/user_group_add.mako',
239 'rhodecode:templates/admin/user_groups/user_group_add.mako',
239 self._get_template_context(c), self.request)
240 self._get_template_context(c), self.request)
240 html = formencode.htmlfill.render(
241 html = formencode.htmlfill.render(
241 data,
242 data,
242 defaults=errors.value,
243 defaults=errors.value,
243 errors=errors.error_dict or {},
244 errors=errors.error_dict or {},
244 prefix_error=False,
245 prefix_error=False,
245 encoding="UTF-8",
246 encoding="UTF-8",
246 force_defaults=False
247 force_defaults=False
247 )
248 )
248 return Response(html)
249 return Response(html)
249
250
250 except Exception:
251 except Exception:
251 log.exception("Exception creating user group")
252 log.exception("Exception creating user group")
252 h.flash(_('Error occurred during creation of user group %s') \
253 h.flash(_('Error occurred during creation of user group %s') \
253 % user_group_name, category='error')
254 % user_group_name, category='error')
254 raise HTTPFound(h.route_path('user_groups_new'))
255 raise HTTPFound(h.route_path('user_groups_new'))
255
256
257 events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id]))
256 raise HTTPFound(
258 raise HTTPFound(
257 h.route_path('edit_user_group', user_group_id=user_group_id))
259 h.route_path('edit_user_group', user_group_id=user_group_id))
General Comments 0
You need to be logged in to leave comments. Login now