##// END OF EJS Templates
fix(permissions): added a common way to update private flag via repo model...
super-admin -
r5551:5b9b5ed2 default
parent child Browse files
Show More
@@ -1,128 +1,122 b''
1 # Copyright (C) 2011-2023 RhodeCode GmbH
1 # Copyright (C) 2011-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20
20
21 from pyramid.httpexceptions import HTTPFound
21 from pyramid.httpexceptions import HTTPFound
22
22
23 from rhodecode.apps._base import RepoAppView
23 from rhodecode.apps._base import RepoAppView
24 from rhodecode.lib import helpers as h
24 from rhodecode.lib import helpers as h
25 from rhodecode.lib import audit_logger
25 from rhodecode.lib import audit_logger
26 from rhodecode.lib.auth import (
26 from rhodecode.lib.auth import (
27 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
27 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
28 from rhodecode.lib.utils2 import str2bool
28 from rhodecode.lib.utils2 import str2bool
29 from rhodecode.model.db import User
29 from rhodecode.model.db import User
30 from rhodecode.model.forms import RepoPermsForm
30 from rhodecode.model.forms import RepoPermsForm
31 from rhodecode.model.meta import Session
31 from rhodecode.model.meta import Session
32 from rhodecode.model.permission import PermissionModel
32 from rhodecode.model.permission import PermissionModel
33 from rhodecode.model.repo import RepoModel
33 from rhodecode.model.repo import RepoModel
34
34
35 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
36
36
37
37
38 class RepoSettingsPermissionsView(RepoAppView):
38 class RepoSettingsPermissionsView(RepoAppView):
39
39
40 def load_default_context(self):
40 def load_default_context(self):
41 c = self._get_local_tmpl_context()
41 c = self._get_local_tmpl_context()
42 return c
42 return c
43
43
44 @LoginRequired()
44 @LoginRequired()
45 @HasRepoPermissionAnyDecorator('repository.admin')
45 @HasRepoPermissionAnyDecorator('repository.admin')
46 def edit_permissions(self):
46 def edit_permissions(self):
47 _ = self.request.translate
47 _ = self.request.translate
48 c = self.load_default_context()
48 c = self.load_default_context()
49 c.active = 'permissions'
49 c.active = 'permissions'
50 if self.request.GET.get('branch_permissions'):
50 if self.request.GET.get('branch_permissions'):
51 h.flash(_('Explicitly add user or user group with write or higher '
51 h.flash(_('Explicitly add user or user group with write or higher '
52 'permission to modify their branch permissions.'),
52 'permission to modify their branch permissions.'),
53 category='notice')
53 category='notice')
54 return self._get_template_context(c)
54 return self._get_template_context(c)
55
55
56 @LoginRequired()
56 @LoginRequired()
57 @HasRepoPermissionAnyDecorator('repository.admin')
57 @HasRepoPermissionAnyDecorator('repository.admin')
58 @CSRFRequired()
58 @CSRFRequired()
59 def edit_permissions_update(self):
59 def edit_permissions_update(self):
60 _ = self.request.translate
60 _ = self.request.translate
61 c = self.load_default_context()
61 c = self.load_default_context()
62 c.active = 'permissions'
62 c.active = 'permissions'
63 data = self.request.POST
63 data = self.request.POST
64 # store private flag outside of HTML to verify if we can modify
64 # store private flag outside of HTML to verify if we can modify
65 # default user permissions, prevents submission of FAKE post data
65 # default user permissions, prevents submission of FAKE post data
66 # into the form for private repos
66 # into the form for private repos
67 data['repo_private'] = self.db_repo.private
67 data['repo_private'] = self.db_repo.private
68 form = RepoPermsForm(self.request.translate)().to_python(data)
68 form = RepoPermsForm(self.request.translate)().to_python(data)
69 changes = RepoModel().update_permissions(
69 changes = RepoModel().update_permissions(
70 self.db_repo_name, form['perm_additions'], form['perm_updates'],
70 self.db_repo_name, form['perm_additions'], form['perm_updates'],
71 form['perm_deletions'])
71 form['perm_deletions'])
72
72
73 action_data = {
73 action_data = {
74 'added': changes['added'],
74 'added': changes['added'],
75 'updated': changes['updated'],
75 'updated': changes['updated'],
76 'deleted': changes['deleted'],
76 'deleted': changes['deleted'],
77 }
77 }
78 audit_logger.store_web(
78 audit_logger.store_web(
79 'repo.edit.permissions', action_data=action_data,
79 'repo.edit.permissions', action_data=action_data,
80 user=self._rhodecode_user, repo=self.db_repo)
80 user=self._rhodecode_user, repo=self.db_repo)
81
81
82 Session().commit()
82 Session().commit()
83 h.flash(_('Repository access permissions updated'), category='success')
83 h.flash(_('Repository access permissions updated'), category='success')
84
84
85 affected_user_ids = None
85 affected_user_ids = None
86 if changes.get('default_user_changed', False):
86 if changes.get('default_user_changed', False):
87 # if we change the default user, we need to flush everyone permissions
87 # if we change the default user, we need to flush everyone permissions
88 affected_user_ids = User.get_all_user_ids()
88 affected_user_ids = User.get_all_user_ids()
89 PermissionModel().flush_user_permission_caches(
89 PermissionModel().flush_user_permission_caches(
90 changes, affected_user_ids=affected_user_ids)
90 changes, affected_user_ids=affected_user_ids)
91
91
92 raise HTTPFound(
92 raise HTTPFound(
93 h.route_path('edit_repo_perms', repo_name=self.db_repo_name))
93 h.route_path('edit_repo_perms', repo_name=self.db_repo_name))
94
94
95 @LoginRequired()
95 @LoginRequired()
96 @HasRepoPermissionAnyDecorator('repository.admin')
96 @HasRepoPermissionAnyDecorator('repository.admin')
97 @CSRFRequired()
97 @CSRFRequired()
98 def edit_permissions_set_private_repo(self):
98 def edit_permissions_set_private_repo(self):
99 _ = self.request.translate
99 _ = self.request.translate
100 self.load_default_context()
100 self.load_default_context()
101
101
102 private_flag = str2bool(self.request.POST.get('private'))
102 private_flag = str2bool(self.request.POST.get('private'))
103
103 changes = {
104 'repo_private': private_flag
105 }
104 try:
106 try:
105 repo = RepoModel().get(self.db_repo.repo_id)
107 repo = RepoModel().get(self.db_repo.repo_id)
106 repo.private = private_flag
108 RepoModel().update(repo, **changes)
107 Session().add(repo)
108 RepoModel().grant_user_permission(
109 repo=self.db_repo, user=User.DEFAULT_USER, perm='repository.none'
110 )
111
112 Session().commit()
109 Session().commit()
113
110
114 h.flash(_('Repository `{}` private mode set successfully').format(self.db_repo_name),
111 h.flash(_('Repository `{}` private mode set successfully').format(self.db_repo_name),
115 category='success')
112 category='success')
116 # NOTE(dan): we change repo private mode we need to notify all USERS
117 affected_user_ids = User.get_all_user_ids()
118 PermissionModel().trigger_permission_flush(affected_user_ids)
119
113
120 except Exception:
114 except Exception:
121 log.exception("Exception during update of repository")
115 log.exception("Exception during update of repository")
122 h.flash(_('Error occurred during update of repository {}').format(
116 h.flash(_('Error occurred during update of repository {}').format(
123 self.db_repo_name), category='error')
117 self.db_repo_name), category='error')
124
118
125 return {
119 return {
126 'redirect_url': h.route_path('edit_repo_perms', repo_name=self.db_repo_name),
120 'redirect_url': h.route_path('edit_repo_perms', repo_name=self.db_repo_name),
127 'private': private_flag
121 'private': private_flag
128 }
122 }
@@ -1,1203 +1,1212 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import os
19 import os
20 import re
20 import re
21 import shutil
21 import shutil
22 import time
22 import time
23 import logging
23 import logging
24 import traceback
24 import traceback
25 import datetime
25 import datetime
26
26
27 from pyramid.threadlocal import get_current_request
27 from pyramid.threadlocal import get_current_request
28 from sqlalchemy.orm import aliased
28 from sqlalchemy.orm import aliased
29 from zope.cachedescriptors.property import Lazy as LazyProperty
29 from zope.cachedescriptors.property import Lazy as LazyProperty
30
30
31 from rhodecode import events
31 from rhodecode import events
32 from rhodecode.lib.auth import HasUserGroupPermissionAny
32 from rhodecode.lib.auth import HasUserGroupPermissionAny
33 from rhodecode.lib.caching_query import FromCache
33 from rhodecode.lib.caching_query import FromCache
34 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError, AttachedArtifactsError
34 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError, AttachedArtifactsError
35 from rhodecode.lib import hooks_base
35 from rhodecode.lib import hooks_base
36 from rhodecode.lib.user_log_filter import user_log_filter
36 from rhodecode.lib.user_log_filter import user_log_filter
37 from rhodecode.lib.utils import make_db_config
37 from rhodecode.lib.utils import make_db_config
38 from rhodecode.lib.utils2 import (
38 from rhodecode.lib.utils2 import (
39 safe_str, remove_prefix, obfuscate_url_pw,
39 safe_str, remove_prefix, obfuscate_url_pw,
40 get_current_rhodecode_user, safe_int, action_logger_generic)
40 get_current_rhodecode_user, safe_int, action_logger_generic)
41 from rhodecode.lib.vcs.backends import get_backend
41 from rhodecode.lib.vcs.backends import get_backend
42 from rhodecode.lib.vcs.nodes import NodeKind
42 from rhodecode.lib.vcs.nodes import NodeKind
43 from rhodecode.model import BaseModel
43 from rhodecode.model import BaseModel
44 from rhodecode.model.db import (
44 from rhodecode.model.db import (
45 _hash_key, func, case, joinedload, or_, in_filter_generator,
45 _hash_key, func, case, joinedload, or_, in_filter_generator,
46 Session, Repository, UserRepoToPerm, UserGroupRepoToPerm,
46 Session, Repository, UserRepoToPerm, UserGroupRepoToPerm,
47 UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
47 UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
48 Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
48 Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
49 from rhodecode.model.permission import PermissionModel
49 from rhodecode.model.permission import PermissionModel
50 from rhodecode.model.settings import VcsSettingsModel
50 from rhodecode.model.settings import VcsSettingsModel
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 class RepoModel(BaseModel):
55 class RepoModel(BaseModel):
56
56
57 cls = Repository
57 cls = Repository
58
58
59 def _get_user_group(self, users_group):
59 def _get_user_group(self, users_group):
60 return self._get_instance(UserGroup, users_group,
60 return self._get_instance(UserGroup, users_group,
61 callback=UserGroup.get_by_group_name)
61 callback=UserGroup.get_by_group_name)
62
62
63 def _get_repo_group(self, repo_group):
63 def _get_repo_group(self, repo_group):
64 return self._get_instance(RepoGroup, repo_group,
64 return self._get_instance(RepoGroup, repo_group,
65 callback=RepoGroup.get_by_group_name)
65 callback=RepoGroup.get_by_group_name)
66
66
67 def _create_default_perms(self, repository, private):
67 def _create_default_perms(self, repository, private):
68 # create default permission
68 # create default permission
69 default = 'repository.read'
69 default = 'repository.read'
70 def_user = User.get_default_user()
70 def_user = User.get_default_user()
71 for p in def_user.user_perms:
71 for p in def_user.user_perms:
72 if p.permission.permission_name.startswith('repository.'):
72 if p.permission.permission_name.startswith('repository.'):
73 default = p.permission.permission_name
73 default = p.permission.permission_name
74 break
74 break
75
75
76 default_perm = 'repository.none' if private else default
76 default_perm = 'repository.none' if private else default
77
77
78 repo_to_perm = UserRepoToPerm()
78 repo_to_perm = UserRepoToPerm()
79 repo_to_perm.permission = Permission.get_by_key(default_perm)
79 repo_to_perm.permission = Permission.get_by_key(default_perm)
80
80
81 repo_to_perm.repository = repository
81 repo_to_perm.repository = repository
82 repo_to_perm.user = def_user
82 repo_to_perm.user = def_user
83
83
84 return repo_to_perm
84 return repo_to_perm
85
85
86 def get(self, repo_id):
86 def get(self, repo_id):
87 repo = self.sa.query(Repository) \
87 repo = self.sa.query(Repository) \
88 .filter(Repository.repo_id == repo_id)
88 .filter(Repository.repo_id == repo_id)
89
89
90 return repo.scalar()
90 return repo.scalar()
91
91
92 def get_repo(self, repository):
92 def get_repo(self, repository):
93 return self._get_repo(repository)
93 return self._get_repo(repository)
94
94
95 def get_by_repo_name(self, repo_name, cache=False):
95 def get_by_repo_name(self, repo_name, cache=False):
96 repo = self.sa.query(Repository) \
96 repo = self.sa.query(Repository) \
97 .filter(Repository.repo_name == repo_name)
97 .filter(Repository.repo_name == repo_name)
98
98
99 if cache:
99 if cache:
100 name_key = _hash_key(repo_name)
100 name_key = _hash_key(repo_name)
101 repo = repo.options(
101 repo = repo.options(
102 FromCache("sql_cache_short", f"get_repo_{name_key}"))
102 FromCache("sql_cache_short", f"get_repo_{name_key}"))
103 return repo.scalar()
103 return repo.scalar()
104
104
105 def _extract_id_from_repo_name(self, repo_name):
105 def _extract_id_from_repo_name(self, repo_name):
106 if repo_name.startswith('/'):
106 if repo_name.startswith('/'):
107 repo_name = repo_name.lstrip('/')
107 repo_name = repo_name.lstrip('/')
108 by_id_match = re.match(r'^_(\d+)', repo_name)
108 by_id_match = re.match(r'^_(\d+)', repo_name)
109 if by_id_match:
109 if by_id_match:
110 return by_id_match.groups()[0]
110 return by_id_match.groups()[0]
111
111
112 def get_repo_by_id(self, repo_name):
112 def get_repo_by_id(self, repo_name):
113 """
113 """
114 Extracts repo_name by id from special urls.
114 Extracts repo_name by id from special urls.
115 Example url is _11/repo_name
115 Example url is _11/repo_name
116
116
117 :param repo_name:
117 :param repo_name:
118 :return: repo object if matched else None
118 :return: repo object if matched else None
119 """
119 """
120 _repo_id = None
120 _repo_id = None
121 try:
121 try:
122 _repo_id = self._extract_id_from_repo_name(repo_name)
122 _repo_id = self._extract_id_from_repo_name(repo_name)
123 if _repo_id:
123 if _repo_id:
124 return self.get(_repo_id)
124 return self.get(_repo_id)
125 except Exception:
125 except Exception:
126 log.exception('Failed to extract repo_name from URL')
126 log.exception('Failed to extract repo_name from URL')
127 if _repo_id:
127 if _repo_id:
128 Session().rollback()
128 Session().rollback()
129
129
130 return None
130 return None
131
131
132 def get_repos_for_root(self, root, traverse=False):
132 def get_repos_for_root(self, root, traverse=False):
133 if traverse:
133 if traverse:
134 like_expression = u'{}%'.format(safe_str(root))
134 like_expression = u'{}%'.format(safe_str(root))
135 repos = Repository.query().filter(
135 repos = Repository.query().filter(
136 Repository.repo_name.like(like_expression)).all()
136 Repository.repo_name.like(like_expression)).all()
137 else:
137 else:
138 if root and not isinstance(root, RepoGroup):
138 if root and not isinstance(root, RepoGroup):
139 raise ValueError(
139 raise ValueError(
140 'Root must be an instance '
140 'Root must be an instance '
141 'of RepoGroup, got:{} instead'.format(type(root)))
141 'of RepoGroup, got:{} instead'.format(type(root)))
142 repos = Repository.query().filter(Repository.group == root).all()
142 repos = Repository.query().filter(Repository.group == root).all()
143 return repos
143 return repos
144
144
145 def get_url(self, repo, request=None, permalink=False):
145 def get_url(self, repo, request=None, permalink=False):
146 if not request:
146 if not request:
147 request = get_current_request()
147 request = get_current_request()
148
148
149 if not request:
149 if not request:
150 return
150 return
151
151
152 if permalink:
152 if permalink:
153 return request.route_url(
153 return request.route_url(
154 'repo_summary', repo_name='_{}'.format(safe_str(repo.repo_id)))
154 'repo_summary', repo_name='_{}'.format(safe_str(repo.repo_id)))
155 else:
155 else:
156 return request.route_url(
156 return request.route_url(
157 'repo_summary', repo_name=safe_str(repo.repo_name))
157 'repo_summary', repo_name=safe_str(repo.repo_name))
158
158
159 def get_commit_url(self, repo, commit_id, request=None, permalink=False):
159 def get_commit_url(self, repo, commit_id, request=None, permalink=False):
160 if not request:
160 if not request:
161 request = get_current_request()
161 request = get_current_request()
162
162
163 if not request:
163 if not request:
164 return
164 return
165
165
166 if permalink:
166 if permalink:
167 return request.route_url(
167 return request.route_url(
168 'repo_commit', repo_name=safe_str(repo.repo_id),
168 'repo_commit', repo_name=safe_str(repo.repo_id),
169 commit_id=commit_id)
169 commit_id=commit_id)
170
170
171 else:
171 else:
172 return request.route_url(
172 return request.route_url(
173 'repo_commit', repo_name=safe_str(repo.repo_name),
173 'repo_commit', repo_name=safe_str(repo.repo_name),
174 commit_id=commit_id)
174 commit_id=commit_id)
175
175
176 def get_repo_log(self, repo, filter_term):
176 def get_repo_log(self, repo, filter_term):
177 repo_log = UserLog.query()\
177 repo_log = UserLog.query()\
178 .filter(or_(UserLog.repository_id == repo.repo_id,
178 .filter(or_(UserLog.repository_id == repo.repo_id,
179 UserLog.repository_name == repo.repo_name))\
179 UserLog.repository_name == repo.repo_name))\
180 .options(joinedload(UserLog.user))\
180 .options(joinedload(UserLog.user))\
181 .options(joinedload(UserLog.repository))\
181 .options(joinedload(UserLog.repository))\
182 .order_by(UserLog.action_date.desc())
182 .order_by(UserLog.action_date.desc())
183
183
184 repo_log = user_log_filter(repo_log, filter_term)
184 repo_log = user_log_filter(repo_log, filter_term)
185 return repo_log
185 return repo_log
186
186
187 @classmethod
187 @classmethod
188 def update_commit_cache(cls, repositories=None):
188 def update_commit_cache(cls, repositories=None):
189 if not repositories:
189 if not repositories:
190 repositories = Repository.getAll()
190 repositories = Repository.getAll()
191 for repo in repositories:
191 for repo in repositories:
192 repo.update_commit_cache()
192 repo.update_commit_cache()
193
193
194 def get_repos_as_dict(self, repo_list=None, admin=False,
194 def get_repos_as_dict(self, repo_list=None, admin=False,
195 super_user_actions=False, short_name=None):
195 super_user_actions=False, short_name=None):
196
196
197 _render = get_current_request().get_partial_renderer(
197 _render = get_current_request().get_partial_renderer(
198 'rhodecode:templates/data_table/_dt_elements.mako')
198 'rhodecode:templates/data_table/_dt_elements.mako')
199 c = _render.get_call_context()
199 c = _render.get_call_context()
200 h = _render.get_helpers()
200 h = _render.get_helpers()
201
201
202 def quick_menu(repo_name):
202 def quick_menu(repo_name):
203 return _render('quick_menu', repo_name)
203 return _render('quick_menu', repo_name)
204
204
205 def repo_lnk(name, rtype, rstate, private, archived, fork_repo_name):
205 def repo_lnk(name, rtype, rstate, private, archived, fork_repo_name):
206 if short_name is not None:
206 if short_name is not None:
207 short_name_var = short_name
207 short_name_var = short_name
208 else:
208 else:
209 short_name_var = not admin
209 short_name_var = not admin
210 return _render('repo_name', name, rtype, rstate, private, archived, fork_repo_name,
210 return _render('repo_name', name, rtype, rstate, private, archived, fork_repo_name,
211 short_name=short_name_var, admin=False)
211 short_name=short_name_var, admin=False)
212
212
213 def last_change(last_change):
213 def last_change(last_change):
214 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
214 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
215 ts = time.time()
215 ts = time.time()
216 utc_offset = (datetime.datetime.fromtimestamp(ts)
216 utc_offset = (datetime.datetime.fromtimestamp(ts)
217 - datetime.datetime.utcfromtimestamp(ts)).total_seconds()
217 - datetime.datetime.utcfromtimestamp(ts)).total_seconds()
218 last_change = last_change + datetime.timedelta(seconds=utc_offset)
218 last_change = last_change + datetime.timedelta(seconds=utc_offset)
219
219
220 return _render("last_change", last_change)
220 return _render("last_change", last_change)
221
221
222 def rss_lnk(repo_name):
222 def rss_lnk(repo_name):
223 return _render("rss", repo_name)
223 return _render("rss", repo_name)
224
224
225 def atom_lnk(repo_name):
225 def atom_lnk(repo_name):
226 return _render("atom", repo_name)
226 return _render("atom", repo_name)
227
227
228 def last_rev(repo_name, cs_cache):
228 def last_rev(repo_name, cs_cache):
229 return _render('revision', repo_name, cs_cache.get('revision'),
229 return _render('revision', repo_name, cs_cache.get('revision'),
230 cs_cache.get('raw_id'), cs_cache.get('author'),
230 cs_cache.get('raw_id'), cs_cache.get('author'),
231 cs_cache.get('message'), cs_cache.get('date'))
231 cs_cache.get('message'), cs_cache.get('date'))
232
232
233 def desc(desc):
233 def desc(desc):
234 return _render('repo_desc', desc, c.visual.stylify_metatags)
234 return _render('repo_desc', desc, c.visual.stylify_metatags)
235
235
236 def state(repo_state):
236 def state(repo_state):
237 return _render("repo_state", repo_state)
237 return _render("repo_state", repo_state)
238
238
239 def repo_actions(repo_name):
239 def repo_actions(repo_name):
240 return _render('repo_actions', repo_name, super_user_actions)
240 return _render('repo_actions', repo_name, super_user_actions)
241
241
242 def user_profile(username):
242 def user_profile(username):
243 return _render('user_profile', username)
243 return _render('user_profile', username)
244
244
245 repos_data = []
245 repos_data = []
246 for repo in repo_list:
246 for repo in repo_list:
247 # NOTE(marcink): because we use only raw column we need to load it like that
247 # NOTE(marcink): because we use only raw column we need to load it like that
248 changeset_cache = Repository._load_changeset_cache(
248 changeset_cache = Repository._load_changeset_cache(
249 repo.repo_id, repo._changeset_cache)
249 repo.repo_id, repo._changeset_cache)
250
250
251 row = {
251 row = {
252 "menu": quick_menu(repo.repo_name),
252 "menu": quick_menu(repo.repo_name),
253
253
254 "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state,
254 "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state,
255 repo.private, repo.archived, repo.fork_repo_name),
255 repo.private, repo.archived, repo.fork_repo_name),
256
256
257 "desc": desc(h.escape(repo.description)),
257 "desc": desc(h.escape(repo.description)),
258
258
259 "last_change": last_change(repo.updated_on),
259 "last_change": last_change(repo.updated_on),
260
260
261 "last_changeset": last_rev(repo.repo_name, changeset_cache),
261 "last_changeset": last_rev(repo.repo_name, changeset_cache),
262 "last_changeset_raw": changeset_cache.get('revision'),
262 "last_changeset_raw": changeset_cache.get('revision'),
263
263
264 "owner": user_profile(repo.owner_username),
264 "owner": user_profile(repo.owner_username),
265
265
266 "state": state(repo.repo_state),
266 "state": state(repo.repo_state),
267 "rss": rss_lnk(repo.repo_name),
267 "rss": rss_lnk(repo.repo_name),
268 "atom": atom_lnk(repo.repo_name),
268 "atom": atom_lnk(repo.repo_name),
269 }
269 }
270 if admin:
270 if admin:
271 row.update({
271 row.update({
272 "action": repo_actions(repo.repo_name),
272 "action": repo_actions(repo.repo_name),
273 })
273 })
274 repos_data.append(row)
274 repos_data.append(row)
275
275
276 return repos_data
276 return repos_data
277
277
278 def get_repos_data_table(
278 def get_repos_data_table(
279 self, draw, start, limit,
279 self, draw, start, limit,
280 search_q, order_by, order_dir,
280 search_q, order_by, order_dir,
281 auth_user, repo_group_id):
281 auth_user, repo_group_id):
282 from rhodecode.model.scm import RepoList
282 from rhodecode.model.scm import RepoList
283
283
284 _perms = ['repository.read', 'repository.write', 'repository.admin']
284 _perms = ['repository.read', 'repository.write', 'repository.admin']
285
285
286 repos = Repository.query() \
286 repos = Repository.query() \
287 .filter(Repository.group_id == repo_group_id) \
287 .filter(Repository.group_id == repo_group_id) \
288 .all()
288 .all()
289 auth_repo_list = RepoList(
289 auth_repo_list = RepoList(
290 repos, perm_set=_perms,
290 repos, perm_set=_perms,
291 extra_kwargs=dict(user=auth_user))
291 extra_kwargs=dict(user=auth_user))
292
292
293 allowed_ids = [-1]
293 allowed_ids = [-1]
294 for repo in auth_repo_list:
294 for repo in auth_repo_list:
295 allowed_ids.append(repo.repo_id)
295 allowed_ids.append(repo.repo_id)
296
296
297 repos_data_total_count = Repository.query() \
297 repos_data_total_count = Repository.query() \
298 .filter(Repository.group_id == repo_group_id) \
298 .filter(Repository.group_id == repo_group_id) \
299 .filter(or_(
299 .filter(or_(
300 # generate multiple IN to fix limitation problems
300 # generate multiple IN to fix limitation problems
301 *in_filter_generator(Repository.repo_id, allowed_ids))
301 *in_filter_generator(Repository.repo_id, allowed_ids))
302 ) \
302 ) \
303 .count()
303 .count()
304
304
305 RepoFork = aliased(Repository)
305 RepoFork = aliased(Repository)
306 OwnerUser = aliased(User)
306 OwnerUser = aliased(User)
307 base_q = Session.query(
307 base_q = Session.query(
308 Repository.repo_id,
308 Repository.repo_id,
309 Repository.repo_name,
309 Repository.repo_name,
310 Repository.description,
310 Repository.description,
311 Repository.repo_type,
311 Repository.repo_type,
312 Repository.repo_state,
312 Repository.repo_state,
313 Repository.private,
313 Repository.private,
314 Repository.archived,
314 Repository.archived,
315 Repository.updated_on,
315 Repository.updated_on,
316 Repository._changeset_cache,
316 Repository._changeset_cache,
317 RepoFork.repo_name.label('fork_repo_name'),
317 RepoFork.repo_name.label('fork_repo_name'),
318 OwnerUser.username.label('owner_username'),
318 OwnerUser.username.label('owner_username'),
319 ) \
319 ) \
320 .filter(Repository.group_id == repo_group_id) \
320 .filter(Repository.group_id == repo_group_id) \
321 .filter(or_(
321 .filter(or_(
322 # generate multiple IN to fix limitation problems
322 # generate multiple IN to fix limitation problems
323 *in_filter_generator(Repository.repo_id, allowed_ids))
323 *in_filter_generator(Repository.repo_id, allowed_ids))
324 ) \
324 ) \
325 .outerjoin(RepoFork, Repository.fork_id == RepoFork.repo_id) \
325 .outerjoin(RepoFork, Repository.fork_id == RepoFork.repo_id) \
326 .join(OwnerUser, Repository.user_id == OwnerUser.user_id)
326 .join(OwnerUser, Repository.user_id == OwnerUser.user_id)
327
327
328 repos_data_total_filtered_count = base_q.count()
328 repos_data_total_filtered_count = base_q.count()
329
329
330 sort_defined = False
330 sort_defined = False
331 if order_by == 'repo_name':
331 if order_by == 'repo_name':
332 sort_col = func.lower(Repository.repo_name)
332 sort_col = func.lower(Repository.repo_name)
333 sort_defined = True
333 sort_defined = True
334 elif order_by == 'user_username':
334 elif order_by == 'user_username':
335 sort_col = User.username
335 sort_col = User.username
336 else:
336 else:
337 sort_col = getattr(Repository, order_by, None)
337 sort_col = getattr(Repository, order_by, None)
338
338
339 if sort_defined or sort_col:
339 if sort_defined or sort_col:
340 if order_dir == 'asc':
340 if order_dir == 'asc':
341 sort_col = sort_col.asc()
341 sort_col = sort_col.asc()
342 else:
342 else:
343 sort_col = sort_col.desc()
343 sort_col = sort_col.desc()
344
344
345 base_q = base_q.order_by(sort_col)
345 base_q = base_q.order_by(sort_col)
346 base_q = base_q.offset(start).limit(limit)
346 base_q = base_q.offset(start).limit(limit)
347
347
348 repos_list = base_q.all()
348 repos_list = base_q.all()
349
349
350 repos_data = RepoModel().get_repos_as_dict(
350 repos_data = RepoModel().get_repos_as_dict(
351 repo_list=repos_list, admin=False)
351 repo_list=repos_list, admin=False)
352
352
353 data = ({
353 data = ({
354 'draw': draw,
354 'draw': draw,
355 'data': repos_data,
355 'data': repos_data,
356 'recordsTotal': repos_data_total_count,
356 'recordsTotal': repos_data_total_count,
357 'recordsFiltered': repos_data_total_filtered_count,
357 'recordsFiltered': repos_data_total_filtered_count,
358 })
358 })
359 return data
359 return data
360
360
361 def _get_defaults(self, repo_name):
361 def _get_defaults(self, repo_name):
362 """
362 """
363 Gets information about repository, and returns a dict for
363 Gets information about repository, and returns a dict for
364 usage in forms
364 usage in forms
365
365
366 :param repo_name:
366 :param repo_name:
367 """
367 """
368
368
369 repo_info = Repository.get_by_repo_name(repo_name)
369 repo_info = Repository.get_by_repo_name(repo_name)
370
370
371 if repo_info is None:
371 if repo_info is None:
372 return None
372 return None
373
373
374 defaults = repo_info.get_dict()
374 defaults = repo_info.get_dict()
375 defaults['repo_name'] = repo_info.just_name
375 defaults['repo_name'] = repo_info.just_name
376
376
377 groups = repo_info.groups_with_parents
377 groups = repo_info.groups_with_parents
378 parent_group = groups[-1] if groups else None
378 parent_group = groups[-1] if groups else None
379
379
380 # we use -1 as this is how in HTML, we mark an empty group
380 # we use -1 as this is how in HTML, we mark an empty group
381 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
381 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
382
382
383 keys_to_process = (
383 keys_to_process = (
384 {'k': 'repo_type', 'strip': False},
384 {'k': 'repo_type', 'strip': False},
385 {'k': 'repo_enable_downloads', 'strip': True},
385 {'k': 'repo_enable_downloads', 'strip': True},
386 {'k': 'repo_description', 'strip': True},
386 {'k': 'repo_description', 'strip': True},
387 {'k': 'repo_enable_locking', 'strip': True},
387 {'k': 'repo_enable_locking', 'strip': True},
388 {'k': 'repo_landing_rev', 'strip': True},
388 {'k': 'repo_landing_rev', 'strip': True},
389 {'k': 'clone_uri', 'strip': False},
389 {'k': 'clone_uri', 'strip': False},
390 {'k': 'push_uri', 'strip': False},
390 {'k': 'push_uri', 'strip': False},
391 {'k': 'repo_private', 'strip': True},
391 {'k': 'repo_private', 'strip': True},
392 {'k': 'repo_enable_statistics', 'strip': True}
392 {'k': 'repo_enable_statistics', 'strip': True}
393 )
393 )
394
394
395 for item in keys_to_process:
395 for item in keys_to_process:
396 attr = item['k']
396 attr = item['k']
397 if item['strip']:
397 if item['strip']:
398 attr = remove_prefix(item['k'], 'repo_')
398 attr = remove_prefix(item['k'], 'repo_')
399
399
400 val = defaults[attr]
400 val = defaults[attr]
401 if item['k'] == 'repo_landing_rev':
401 if item['k'] == 'repo_landing_rev':
402 val = ':'.join(defaults[attr])
402 val = ':'.join(defaults[attr])
403 defaults[item['k']] = val
403 defaults[item['k']] = val
404 if item['k'] == 'clone_uri':
404 if item['k'] == 'clone_uri':
405 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
405 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
406 if item['k'] == 'push_uri':
406 if item['k'] == 'push_uri':
407 defaults['push_uri_hidden'] = repo_info.push_uri_hidden
407 defaults['push_uri_hidden'] = repo_info.push_uri_hidden
408
408
409 # fill owner
409 # fill owner
410 if repo_info.user:
410 if repo_info.user:
411 defaults.update({'user': repo_info.user.username})
411 defaults.update({'user': repo_info.user.username})
412 else:
412 else:
413 replacement_user = User.get_first_super_admin().username
413 replacement_user = User.get_first_super_admin().username
414 defaults.update({'user': replacement_user})
414 defaults.update({'user': replacement_user})
415
415
416 return defaults
416 return defaults
417
417
418 def update(self, repo, **kwargs):
418 def update(self, repo, **kwargs):
419 try:
419 try:
420 cur_repo = self._get_repo(repo)
420 cur_repo = self._get_repo(repo)
421 source_repo_name = cur_repo.repo_name
421 source_repo_name = cur_repo.repo_name
422
422
423 affected_user_ids = []
423 affected_user_ids = []
424 if 'user' in kwargs:
424 if 'user' in kwargs:
425 old_owner_id = cur_repo.user.user_id
425 old_owner_id = cur_repo.user.user_id
426 new_owner = User.get_by_username(kwargs['user'])
426 new_owner = User.get_by_username(kwargs['user'])
427 cur_repo.user = new_owner
427 cur_repo.user = new_owner
428
428
429 if old_owner_id != new_owner.user_id:
429 if old_owner_id != new_owner.user_id:
430 affected_user_ids = [new_owner.user_id, old_owner_id]
430 affected_user_ids = [new_owner.user_id, old_owner_id]
431
431
432 if 'repo_group' in kwargs:
432 if 'repo_group' in kwargs:
433 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
433 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
434 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
434 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
435
435
436 update_keys = [
436 update_keys = [
437 (1, 'repo_description'),
437 (1, 'repo_description'),
438 (1, 'repo_landing_rev'),
438 (1, 'repo_landing_rev'),
439 (1, 'repo_private'),
439 (1, 'repo_private'),
440 (1, 'repo_enable_downloads'),
440 (1, 'repo_enable_downloads'),
441 (1, 'repo_enable_locking'),
441 (1, 'repo_enable_locking'),
442 (1, 'repo_enable_statistics'),
442 (1, 'repo_enable_statistics'),
443 (0, 'clone_uri'),
443 (0, 'clone_uri'),
444 (0, 'push_uri'),
444 (0, 'push_uri'),
445 (0, 'fork_id')
445 (0, 'fork_id')
446 ]
446 ]
447 for strip, k in update_keys:
447 for strip, k in update_keys:
448 if k in kwargs:
448 if k in kwargs:
449 val = kwargs[k]
449 val = kwargs[k]
450 if strip:
450 if strip:
451 k = remove_prefix(k, 'repo_')
451 k = remove_prefix(k, 'repo_')
452
452
453 setattr(cur_repo, k, val)
453 setattr(cur_repo, k, val)
454
454
455 new_name = source_repo_name
456 if 'repo_name' in kwargs:
455 new_name = cur_repo.get_new_name(kwargs['repo_name'])
457 new_name = cur_repo.get_new_name(kwargs['repo_name'])
456 cur_repo.repo_name = new_name
458 cur_repo.repo_name = new_name
457
459
458 # if private flag is set, reset default permission to NONE
460 if 'repo_private' in kwargs:
459 if kwargs.get('repo_private'):
461 # if private flag is set to True, reset default permission to NONE
462 set_private_to = kwargs.get('repo_private')
463 if set_private_to:
460 EMPTY_PERM = 'repository.none'
464 EMPTY_PERM = 'repository.none'
461 RepoModel().grant_user_permission(
465 RepoModel().grant_user_permission(
462 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
466 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
463 )
467 )
468 if set_private_to != cur_repo.private:
469 # NOTE(dan): we change repo private mode we need to notify all USERS
470 # this is just by having this value set to a different value then it was before
471 affected_user_ids = User.get_all_user_ids()
472
464 if kwargs.get('repo_landing_rev'):
473 if kwargs.get('repo_landing_rev'):
465 landing_rev_val = kwargs['repo_landing_rev']
474 landing_rev_val = kwargs['repo_landing_rev']
466 RepoModel().set_landing_rev(cur_repo, landing_rev_val)
475 RepoModel().set_landing_rev(cur_repo, landing_rev_val)
467
476
468 # handle extra fields
477 # handle extra fields
469 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
478 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
470 k = RepositoryField.un_prefix_key(field)
479 k = RepositoryField.un_prefix_key(field)
471 ex_field = RepositoryField.get_by_key_name(
480 ex_field = RepositoryField.get_by_key_name(
472 key=k, repo=cur_repo)
481 key=k, repo=cur_repo)
473 if ex_field:
482 if ex_field:
474 ex_field.field_value = kwargs[field]
483 ex_field.field_value = kwargs[field]
475 self.sa.add(ex_field)
484 self.sa.add(ex_field)
476
485
477 self.sa.add(cur_repo)
486 self.sa.add(cur_repo)
478
487
479 if source_repo_name != new_name:
488 if source_repo_name != new_name:
480 # rename repository
489 # rename repository
481 self._rename_filesystem_repo(
490 self._rename_filesystem_repo(
482 old=source_repo_name, new=new_name)
491 old=source_repo_name, new=new_name)
483
492
484 if affected_user_ids:
493 if affected_user_ids:
485 PermissionModel().trigger_permission_flush(affected_user_ids)
494 PermissionModel().trigger_permission_flush(affected_user_ids)
486
495
487 return cur_repo
496 return cur_repo
488 except Exception:
497 except Exception:
489 log.error(traceback.format_exc())
498 log.error(traceback.format_exc())
490 raise
499 raise
491
500
492 def _create_repo(self, repo_name, repo_type, description, owner,
501 def _create_repo(self, repo_name, repo_type, description, owner,
493 private=False, clone_uri=None, repo_group=None,
502 private=False, clone_uri=None, repo_group=None,
494 landing_rev=None, fork_of=None,
503 landing_rev=None, fork_of=None,
495 copy_fork_permissions=False, enable_statistics=False,
504 copy_fork_permissions=False, enable_statistics=False,
496 enable_locking=False, enable_downloads=False,
505 enable_locking=False, enable_downloads=False,
497 copy_group_permissions=False,
506 copy_group_permissions=False,
498 state=Repository.STATE_PENDING):
507 state=Repository.STATE_PENDING):
499 """
508 """
500 Create repository inside database with PENDING state, this should be
509 Create repository inside database with PENDING state, this should be
501 only executed by create() repo. With exception of importing existing
510 only executed by create() repo. With exception of importing existing
502 repos
511 repos
503 """
512 """
504 from rhodecode.model.scm import ScmModel
513 from rhodecode.model.scm import ScmModel
505
514
506 owner = self._get_user(owner)
515 owner = self._get_user(owner)
507 fork_of = self._get_repo(fork_of)
516 fork_of = self._get_repo(fork_of)
508 repo_group = self._get_repo_group(safe_int(repo_group))
517 repo_group = self._get_repo_group(safe_int(repo_group))
509 default_landing_ref, _lbl = ScmModel.backend_landing_ref(repo_type)
518 default_landing_ref, _lbl = ScmModel.backend_landing_ref(repo_type)
510 landing_rev = landing_rev or default_landing_ref
519 landing_rev = landing_rev or default_landing_ref
511
520
512 try:
521 try:
513 repo_name = safe_str(repo_name)
522 repo_name = safe_str(repo_name)
514 description = safe_str(description)
523 description = safe_str(description)
515 # repo name is just a name of repository
524 # repo name is just a name of repository
516 # while repo_name_full is a full qualified name that is combined
525 # while repo_name_full is a full qualified name that is combined
517 # with name and path of group
526 # with name and path of group
518 repo_name_full = repo_name
527 repo_name_full = repo_name
519 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
528 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
520
529
521 new_repo = Repository()
530 new_repo = Repository()
522 new_repo.repo_state = state
531 new_repo.repo_state = state
523 new_repo.enable_statistics = False
532 new_repo.enable_statistics = False
524 new_repo.repo_name = repo_name_full
533 new_repo.repo_name = repo_name_full
525 new_repo.repo_type = repo_type
534 new_repo.repo_type = repo_type
526 new_repo.user = owner
535 new_repo.user = owner
527 new_repo.group = repo_group
536 new_repo.group = repo_group
528 new_repo.description = description or repo_name
537 new_repo.description = description or repo_name
529 new_repo.private = private
538 new_repo.private = private
530 new_repo.archived = False
539 new_repo.archived = False
531 new_repo.clone_uri = clone_uri
540 new_repo.clone_uri = clone_uri
532 new_repo.landing_rev = landing_rev
541 new_repo.landing_rev = landing_rev
533
542
534 new_repo.enable_statistics = enable_statistics
543 new_repo.enable_statistics = enable_statistics
535 new_repo.enable_locking = enable_locking
544 new_repo.enable_locking = enable_locking
536 new_repo.enable_downloads = enable_downloads
545 new_repo.enable_downloads = enable_downloads
537
546
538 if repo_group:
547 if repo_group:
539 new_repo.enable_locking = repo_group.enable_locking
548 new_repo.enable_locking = repo_group.enable_locking
540
549
541 if fork_of:
550 if fork_of:
542 parent_repo = fork_of
551 parent_repo = fork_of
543 new_repo.fork = parent_repo
552 new_repo.fork = parent_repo
544
553
545 events.trigger(events.RepoPreCreateEvent(new_repo))
554 events.trigger(events.RepoPreCreateEvent(new_repo))
546
555
547 self.sa.add(new_repo)
556 self.sa.add(new_repo)
548
557
549 EMPTY_PERM = 'repository.none'
558 EMPTY_PERM = 'repository.none'
550 if fork_of and copy_fork_permissions:
559 if fork_of and copy_fork_permissions:
551 repo = fork_of
560 repo = fork_of
552 user_perms = UserRepoToPerm.query() \
561 user_perms = UserRepoToPerm.query() \
553 .filter(UserRepoToPerm.repository == repo).all()
562 .filter(UserRepoToPerm.repository == repo).all()
554 group_perms = UserGroupRepoToPerm.query() \
563 group_perms = UserGroupRepoToPerm.query() \
555 .filter(UserGroupRepoToPerm.repository == repo).all()
564 .filter(UserGroupRepoToPerm.repository == repo).all()
556
565
557 for perm in user_perms:
566 for perm in user_perms:
558 UserRepoToPerm.create(
567 UserRepoToPerm.create(
559 perm.user, new_repo, perm.permission)
568 perm.user, new_repo, perm.permission)
560
569
561 for perm in group_perms:
570 for perm in group_perms:
562 UserGroupRepoToPerm.create(
571 UserGroupRepoToPerm.create(
563 perm.users_group, new_repo, perm.permission)
572 perm.users_group, new_repo, perm.permission)
564 # in case we copy permissions and also set this repo to private
573 # in case we copy permissions and also set this repo to private
565 # override the default user permission to make it a private repo
574 # override the default user permission to make it a private repo
566 if private:
575 if private:
567 RepoModel(self.sa).grant_user_permission(
576 RepoModel(self.sa).grant_user_permission(
568 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
577 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
569
578
570 elif repo_group and copy_group_permissions:
579 elif repo_group and copy_group_permissions:
571 user_perms = UserRepoGroupToPerm.query() \
580 user_perms = UserRepoGroupToPerm.query() \
572 .filter(UserRepoGroupToPerm.group == repo_group).all()
581 .filter(UserRepoGroupToPerm.group == repo_group).all()
573
582
574 group_perms = UserGroupRepoGroupToPerm.query() \
583 group_perms = UserGroupRepoGroupToPerm.query() \
575 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
584 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
576
585
577 for perm in user_perms:
586 for perm in user_perms:
578 perm_name = perm.permission.permission_name.replace(
587 perm_name = perm.permission.permission_name.replace(
579 'group.', 'repository.')
588 'group.', 'repository.')
580 perm_obj = Permission.get_by_key(perm_name)
589 perm_obj = Permission.get_by_key(perm_name)
581 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
590 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
582
591
583 for perm in group_perms:
592 for perm in group_perms:
584 perm_name = perm.permission.permission_name.replace(
593 perm_name = perm.permission.permission_name.replace(
585 'group.', 'repository.')
594 'group.', 'repository.')
586 perm_obj = Permission.get_by_key(perm_name)
595 perm_obj = Permission.get_by_key(perm_name)
587 UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj)
596 UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj)
588
597
589 if private:
598 if private:
590 RepoModel(self.sa).grant_user_permission(
599 RepoModel(self.sa).grant_user_permission(
591 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
600 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
592
601
593 else:
602 else:
594 perm_obj = self._create_default_perms(new_repo, private)
603 perm_obj = self._create_default_perms(new_repo, private)
595 self.sa.add(perm_obj)
604 self.sa.add(perm_obj)
596
605
597 # now automatically start following this repository as owner
606 # now automatically start following this repository as owner
598 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, owner.user_id)
607 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, owner.user_id)
599
608
600 # we need to flush here, in order to check if database won't
609 # we need to flush here, in order to check if database won't
601 # throw any exceptions, create filesystem dirs at the very end
610 # throw any exceptions, create filesystem dirs at the very end
602 self.sa.flush()
611 self.sa.flush()
603 events.trigger(events.RepoCreateEvent(new_repo, actor=owner))
612 events.trigger(events.RepoCreateEvent(new_repo, actor=owner))
604 return new_repo
613 return new_repo
605
614
606 except Exception:
615 except Exception:
607 log.error(traceback.format_exc())
616 log.error(traceback.format_exc())
608 raise
617 raise
609
618
610 def create(self, form_data, cur_user):
619 def create(self, form_data, cur_user):
611 """
620 """
612 Create repository using celery tasks
621 Create repository using celery tasks
613
622
614 :param form_data:
623 :param form_data:
615 :param cur_user:
624 :param cur_user:
616 """
625 """
617 from rhodecode.lib.celerylib import tasks, run_task
626 from rhodecode.lib.celerylib import tasks, run_task
618 return run_task(tasks.create_repo, form_data, cur_user)
627 return run_task(tasks.create_repo, form_data, cur_user)
619
628
620 def update_permissions(self, repo, perm_additions=None, perm_updates=None,
629 def update_permissions(self, repo, perm_additions=None, perm_updates=None,
621 perm_deletions=None, check_perms=True,
630 perm_deletions=None, check_perms=True,
622 cur_user=None):
631 cur_user=None):
623 if not perm_additions:
632 if not perm_additions:
624 perm_additions = []
633 perm_additions = []
625 if not perm_updates:
634 if not perm_updates:
626 perm_updates = []
635 perm_updates = []
627 if not perm_deletions:
636 if not perm_deletions:
628 perm_deletions = []
637 perm_deletions = []
629
638
630 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
639 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
631
640
632 changes = {
641 changes = {
633 'added': [],
642 'added': [],
634 'updated': [],
643 'updated': [],
635 'deleted': [],
644 'deleted': [],
636 'default_user_changed': None
645 'default_user_changed': None
637 }
646 }
638
647
639 repo = self._get_repo(repo)
648 repo = self._get_repo(repo)
640
649
641 # update permissions
650 # update permissions
642 for member_id, perm, member_type in perm_updates:
651 for member_id, perm, member_type in perm_updates:
643 member_id = int(member_id)
652 member_id = int(member_id)
644 if member_type == 'user':
653 if member_type == 'user':
645 member_name = User.get(member_id).username
654 member_name = User.get(member_id).username
646 if member_name == User.DEFAULT_USER:
655 if member_name == User.DEFAULT_USER:
647 # NOTE(dan): detect if we changed permissions for default user
656 # NOTE(dan): detect if we changed permissions for default user
648 perm_obj = self.sa.query(UserRepoToPerm) \
657 perm_obj = self.sa.query(UserRepoToPerm) \
649 .filter(UserRepoToPerm.user_id == member_id) \
658 .filter(UserRepoToPerm.user_id == member_id) \
650 .filter(UserRepoToPerm.repository == repo) \
659 .filter(UserRepoToPerm.repository == repo) \
651 .scalar()
660 .scalar()
652 if perm_obj and perm_obj.permission.permission_name != perm:
661 if perm_obj and perm_obj.permission.permission_name != perm:
653 changes['default_user_changed'] = True
662 changes['default_user_changed'] = True
654
663
655 # this updates also current one if found
664 # this updates also current one if found
656 self.grant_user_permission(
665 self.grant_user_permission(
657 repo=repo, user=member_id, perm=perm)
666 repo=repo, user=member_id, perm=perm)
658 elif member_type == 'user_group':
667 elif member_type == 'user_group':
659 # check if we have permissions to alter this usergroup
668 # check if we have permissions to alter this usergroup
660 member_name = UserGroup.get(member_id).users_group_name
669 member_name = UserGroup.get(member_id).users_group_name
661 if not check_perms or HasUserGroupPermissionAny(
670 if not check_perms or HasUserGroupPermissionAny(
662 *req_perms)(member_name, user=cur_user):
671 *req_perms)(member_name, user=cur_user):
663 self.grant_user_group_permission(
672 self.grant_user_group_permission(
664 repo=repo, group_name=member_id, perm=perm)
673 repo=repo, group_name=member_id, perm=perm)
665 else:
674 else:
666 raise ValueError("member_type must be 'user' or 'user_group' "
675 raise ValueError("member_type must be 'user' or 'user_group' "
667 "got {} instead".format(member_type))
676 "got {} instead".format(member_type))
668 changes['updated'].append({'type': member_type, 'id': member_id,
677 changes['updated'].append({'type': member_type, 'id': member_id,
669 'name': member_name, 'new_perm': perm})
678 'name': member_name, 'new_perm': perm})
670
679
671 # set new permissions
680 # set new permissions
672 for member_id, perm, member_type in perm_additions:
681 for member_id, perm, member_type in perm_additions:
673 member_id = int(member_id)
682 member_id = int(member_id)
674 if member_type == 'user':
683 if member_type == 'user':
675 member_name = User.get(member_id).username
684 member_name = User.get(member_id).username
676 self.grant_user_permission(
685 self.grant_user_permission(
677 repo=repo, user=member_id, perm=perm)
686 repo=repo, user=member_id, perm=perm)
678 elif member_type == 'user_group':
687 elif member_type == 'user_group':
679 # check if we have permissions to alter this usergroup
688 # check if we have permissions to alter this usergroup
680 member_name = UserGroup.get(member_id).users_group_name
689 member_name = UserGroup.get(member_id).users_group_name
681 if not check_perms or HasUserGroupPermissionAny(
690 if not check_perms or HasUserGroupPermissionAny(
682 *req_perms)(member_name, user=cur_user):
691 *req_perms)(member_name, user=cur_user):
683 self.grant_user_group_permission(
692 self.grant_user_group_permission(
684 repo=repo, group_name=member_id, perm=perm)
693 repo=repo, group_name=member_id, perm=perm)
685 else:
694 else:
686 raise ValueError("member_type must be 'user' or 'user_group' "
695 raise ValueError("member_type must be 'user' or 'user_group' "
687 "got {} instead".format(member_type))
696 "got {} instead".format(member_type))
688
697
689 changes['added'].append({'type': member_type, 'id': member_id,
698 changes['added'].append({'type': member_type, 'id': member_id,
690 'name': member_name, 'new_perm': perm})
699 'name': member_name, 'new_perm': perm})
691 # delete permissions
700 # delete permissions
692 for member_id, perm, member_type in perm_deletions:
701 for member_id, perm, member_type in perm_deletions:
693 member_id = int(member_id)
702 member_id = int(member_id)
694 if member_type == 'user':
703 if member_type == 'user':
695 member_name = User.get(member_id).username
704 member_name = User.get(member_id).username
696 self.revoke_user_permission(repo=repo, user=member_id)
705 self.revoke_user_permission(repo=repo, user=member_id)
697 elif member_type == 'user_group':
706 elif member_type == 'user_group':
698 # check if we have permissions to alter this usergroup
707 # check if we have permissions to alter this usergroup
699 member_name = UserGroup.get(member_id).users_group_name
708 member_name = UserGroup.get(member_id).users_group_name
700 if not check_perms or HasUserGroupPermissionAny(
709 if not check_perms or HasUserGroupPermissionAny(
701 *req_perms)(member_name, user=cur_user):
710 *req_perms)(member_name, user=cur_user):
702 self.revoke_user_group_permission(
711 self.revoke_user_group_permission(
703 repo=repo, group_name=member_id)
712 repo=repo, group_name=member_id)
704 else:
713 else:
705 raise ValueError("member_type must be 'user' or 'user_group' "
714 raise ValueError("member_type must be 'user' or 'user_group' "
706 "got {} instead".format(member_type))
715 "got {} instead".format(member_type))
707
716
708 changes['deleted'].append({'type': member_type, 'id': member_id,
717 changes['deleted'].append({'type': member_type, 'id': member_id,
709 'name': member_name, 'new_perm': perm})
718 'name': member_name, 'new_perm': perm})
710 return changes
719 return changes
711
720
712 def create_fork(self, form_data, cur_user):
721 def create_fork(self, form_data, cur_user):
713 """
722 """
714 Simple wrapper into executing celery task for fork creation
723 Simple wrapper into executing celery task for fork creation
715
724
716 :param form_data:
725 :param form_data:
717 :param cur_user:
726 :param cur_user:
718 """
727 """
719 from rhodecode.lib.celerylib import tasks, run_task
728 from rhodecode.lib.celerylib import tasks, run_task
720 return run_task(tasks.create_repo_fork, form_data, cur_user)
729 return run_task(tasks.create_repo_fork, form_data, cur_user)
721
730
722 def archive(self, repo):
731 def archive(self, repo):
723 """
732 """
724 Archive given repository. Set archive flag.
733 Archive given repository. Set archive flag.
725
734
726 :param repo:
735 :param repo:
727 """
736 """
728 repo = self._get_repo(repo)
737 repo = self._get_repo(repo)
729 if repo:
738 if repo:
730
739
731 try:
740 try:
732 repo.archived = True
741 repo.archived = True
733 self.sa.add(repo)
742 self.sa.add(repo)
734 self.sa.commit()
743 self.sa.commit()
735 except Exception:
744 except Exception:
736 log.error(traceback.format_exc())
745 log.error(traceback.format_exc())
737 raise
746 raise
738
747
739 def delete(self, repo, forks=None, pull_requests=None, artifacts=None, fs_remove=True, cur_user=None):
748 def delete(self, repo, forks=None, pull_requests=None, artifacts=None, fs_remove=True, cur_user=None):
740 """
749 """
741 Delete given repository, forks parameter defines what do do with
750 Delete given repository, forks parameter defines what do do with
742 attached forks. Throws AttachedForksError if deleted repo has attached
751 attached forks. Throws AttachedForksError if deleted repo has attached
743 forks
752 forks
744
753
745 :param repo:
754 :param repo:
746 :param forks: str 'delete' or 'detach'
755 :param forks: str 'delete' or 'detach'
747 :param pull_requests: str 'delete' or None
756 :param pull_requests: str 'delete' or None
748 :param artifacts: str 'delete' or None
757 :param artifacts: str 'delete' or None
749 :param fs_remove: remove(archive) repo from filesystem
758 :param fs_remove: remove(archive) repo from filesystem
750 """
759 """
751 if not cur_user:
760 if not cur_user:
752 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
761 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
753 repo = self._get_repo(repo)
762 repo = self._get_repo(repo)
754 if repo:
763 if repo:
755 if forks == 'detach':
764 if forks == 'detach':
756 for r in repo.forks:
765 for r in repo.forks:
757 r.fork = None
766 r.fork = None
758 self.sa.add(r)
767 self.sa.add(r)
759 elif forks == 'delete':
768 elif forks == 'delete':
760 for r in repo.forks:
769 for r in repo.forks:
761 self.delete(r, forks='delete')
770 self.delete(r, forks='delete')
762 elif [f for f in repo.forks]:
771 elif [f for f in repo.forks]:
763 raise AttachedForksError()
772 raise AttachedForksError()
764
773
765 # check for pull requests
774 # check for pull requests
766 pr_sources = repo.pull_requests_source
775 pr_sources = repo.pull_requests_source
767 pr_targets = repo.pull_requests_target
776 pr_targets = repo.pull_requests_target
768 if pull_requests != 'delete' and (pr_sources or pr_targets):
777 if pull_requests != 'delete' and (pr_sources or pr_targets):
769 raise AttachedPullRequestsError()
778 raise AttachedPullRequestsError()
770
779
771 artifacts_objs = repo.artifacts
780 artifacts_objs = repo.artifacts
772 if artifacts == 'delete':
781 if artifacts == 'delete':
773 for a in artifacts_objs:
782 for a in artifacts_objs:
774 self.sa.delete(a)
783 self.sa.delete(a)
775 elif [a for a in artifacts_objs]:
784 elif [a for a in artifacts_objs]:
776 raise AttachedArtifactsError()
785 raise AttachedArtifactsError()
777
786
778 old_repo_dict = repo.get_dict()
787 old_repo_dict = repo.get_dict()
779 events.trigger(events.RepoPreDeleteEvent(repo))
788 events.trigger(events.RepoPreDeleteEvent(repo))
780 try:
789 try:
781 self.sa.delete(repo)
790 self.sa.delete(repo)
782 if fs_remove:
791 if fs_remove:
783 self._delete_filesystem_repo(repo)
792 self._delete_filesystem_repo(repo)
784 else:
793 else:
785 log.debug('skipping removal from filesystem')
794 log.debug('skipping removal from filesystem')
786 old_repo_dict.update({
795 old_repo_dict.update({
787 'deleted_by': cur_user,
796 'deleted_by': cur_user,
788 'deleted_on': time.time(),
797 'deleted_on': time.time(),
789 })
798 })
790 hooks_base.delete_repository(**old_repo_dict)
799 hooks_base.delete_repository(**old_repo_dict)
791 events.trigger(events.RepoDeleteEvent(repo))
800 events.trigger(events.RepoDeleteEvent(repo))
792 except Exception:
801 except Exception:
793 log.error(traceback.format_exc())
802 log.error(traceback.format_exc())
794 raise
803 raise
795
804
796 def grant_user_permission(self, repo, user, perm):
805 def grant_user_permission(self, repo, user, perm):
797 """
806 """
798 Grant permission for user on given repository, or update existing one
807 Grant permission for user on given repository, or update existing one
799 if found
808 if found
800
809
801 :param repo: Instance of Repository, repository_id, or repository name
810 :param repo: Instance of Repository, repository_id, or repository name
802 :param user: Instance of User, user_id or username
811 :param user: Instance of User, user_id or username
803 :param perm: Instance of Permission, or permission_name
812 :param perm: Instance of Permission, or permission_name
804 """
813 """
805 user = self._get_user(user)
814 user = self._get_user(user)
806 repo = self._get_repo(repo)
815 repo = self._get_repo(repo)
807 permission = self._get_perm(perm)
816 permission = self._get_perm(perm)
808
817
809 # check if we have that permission already
818 # check if we have that permission already
810 obj = self.sa.query(UserRepoToPerm) \
819 obj = self.sa.query(UserRepoToPerm) \
811 .filter(UserRepoToPerm.user == user) \
820 .filter(UserRepoToPerm.user == user) \
812 .filter(UserRepoToPerm.repository == repo) \
821 .filter(UserRepoToPerm.repository == repo) \
813 .scalar()
822 .scalar()
814 if obj is None:
823 if obj is None:
815 # create new !
824 # create new !
816 obj = UserRepoToPerm()
825 obj = UserRepoToPerm()
817 obj.repository = repo
826 obj.repository = repo
818 obj.user = user
827 obj.user = user
819 obj.permission = permission
828 obj.permission = permission
820 self.sa.add(obj)
829 self.sa.add(obj)
821 log.debug('Granted perm %s to %s on %s', perm, user, repo)
830 log.debug('Granted perm %s to %s on %s', perm, user, repo)
822 action_logger_generic(
831 action_logger_generic(
823 'granted permission: {} to user: {} on repo: {}'.format(
832 'granted permission: {} to user: {} on repo: {}'.format(
824 perm, user, repo), namespace='security.repo')
833 perm, user, repo), namespace='security.repo')
825 return obj
834 return obj
826
835
827 def revoke_user_permission(self, repo, user):
836 def revoke_user_permission(self, repo, user):
828 """
837 """
829 Revoke permission for user on given repository
838 Revoke permission for user on given repository
830
839
831 :param repo: Instance of Repository, repository_id, or repository name
840 :param repo: Instance of Repository, repository_id, or repository name
832 :param user: Instance of User, user_id or username
841 :param user: Instance of User, user_id or username
833 """
842 """
834
843
835 user = self._get_user(user)
844 user = self._get_user(user)
836 repo = self._get_repo(repo)
845 repo = self._get_repo(repo)
837
846
838 obj = self.sa.query(UserRepoToPerm) \
847 obj = self.sa.query(UserRepoToPerm) \
839 .filter(UserRepoToPerm.repository == repo) \
848 .filter(UserRepoToPerm.repository == repo) \
840 .filter(UserRepoToPerm.user == user) \
849 .filter(UserRepoToPerm.user == user) \
841 .scalar()
850 .scalar()
842 if obj:
851 if obj:
843 self.sa.delete(obj)
852 self.sa.delete(obj)
844 log.debug('Revoked perm on %s on %s', repo, user)
853 log.debug('Revoked perm on %s on %s', repo, user)
845 action_logger_generic(
854 action_logger_generic(
846 'revoked permission from user: {} on repo: {}'.format(
855 'revoked permission from user: {} on repo: {}'.format(
847 user, repo), namespace='security.repo')
856 user, repo), namespace='security.repo')
848
857
849 def grant_user_group_permission(self, repo, group_name, perm):
858 def grant_user_group_permission(self, repo, group_name, perm):
850 """
859 """
851 Grant permission for user group on given repository, or update
860 Grant permission for user group on given repository, or update
852 existing one if found
861 existing one if found
853
862
854 :param repo: Instance of Repository, repository_id, or repository name
863 :param repo: Instance of Repository, repository_id, or repository name
855 :param group_name: Instance of UserGroup, users_group_id,
864 :param group_name: Instance of UserGroup, users_group_id,
856 or user group name
865 or user group name
857 :param perm: Instance of Permission, or permission_name
866 :param perm: Instance of Permission, or permission_name
858 """
867 """
859 repo = self._get_repo(repo)
868 repo = self._get_repo(repo)
860 group_name = self._get_user_group(group_name)
869 group_name = self._get_user_group(group_name)
861 permission = self._get_perm(perm)
870 permission = self._get_perm(perm)
862
871
863 # check if we have that permission already
872 # check if we have that permission already
864 obj = self.sa.query(UserGroupRepoToPerm) \
873 obj = self.sa.query(UserGroupRepoToPerm) \
865 .filter(UserGroupRepoToPerm.users_group == group_name) \
874 .filter(UserGroupRepoToPerm.users_group == group_name) \
866 .filter(UserGroupRepoToPerm.repository == repo) \
875 .filter(UserGroupRepoToPerm.repository == repo) \
867 .scalar()
876 .scalar()
868
877
869 if obj is None:
878 if obj is None:
870 # create new
879 # create new
871 obj = UserGroupRepoToPerm()
880 obj = UserGroupRepoToPerm()
872
881
873 obj.repository = repo
882 obj.repository = repo
874 obj.users_group = group_name
883 obj.users_group = group_name
875 obj.permission = permission
884 obj.permission = permission
876 self.sa.add(obj)
885 self.sa.add(obj)
877 log.debug('Granted perm %s to %s on %s', perm, group_name, repo)
886 log.debug('Granted perm %s to %s on %s', perm, group_name, repo)
878 action_logger_generic(
887 action_logger_generic(
879 'granted permission: {} to usergroup: {} on repo: {}'.format(
888 'granted permission: {} to usergroup: {} on repo: {}'.format(
880 perm, group_name, repo), namespace='security.repo')
889 perm, group_name, repo), namespace='security.repo')
881
890
882 return obj
891 return obj
883
892
884 def revoke_user_group_permission(self, repo, group_name):
893 def revoke_user_group_permission(self, repo, group_name):
885 """
894 """
886 Revoke permission for user group on given repository
895 Revoke permission for user group on given repository
887
896
888 :param repo: Instance of Repository, repository_id, or repository name
897 :param repo: Instance of Repository, repository_id, or repository name
889 :param group_name: Instance of UserGroup, users_group_id,
898 :param group_name: Instance of UserGroup, users_group_id,
890 or user group name
899 or user group name
891 """
900 """
892 repo = self._get_repo(repo)
901 repo = self._get_repo(repo)
893 group_name = self._get_user_group(group_name)
902 group_name = self._get_user_group(group_name)
894
903
895 obj = self.sa.query(UserGroupRepoToPerm) \
904 obj = self.sa.query(UserGroupRepoToPerm) \
896 .filter(UserGroupRepoToPerm.repository == repo) \
905 .filter(UserGroupRepoToPerm.repository == repo) \
897 .filter(UserGroupRepoToPerm.users_group == group_name) \
906 .filter(UserGroupRepoToPerm.users_group == group_name) \
898 .scalar()
907 .scalar()
899 if obj:
908 if obj:
900 self.sa.delete(obj)
909 self.sa.delete(obj)
901 log.debug('Revoked perm to %s on %s', repo, group_name)
910 log.debug('Revoked perm to %s on %s', repo, group_name)
902 action_logger_generic(
911 action_logger_generic(
903 'revoked permission from usergroup: {} on repo: {}'.format(
912 'revoked permission from usergroup: {} on repo: {}'.format(
904 group_name, repo), namespace='security.repo')
913 group_name, repo), namespace='security.repo')
905
914
906 def delete_stats(self, repo_name):
915 def delete_stats(self, repo_name):
907 """
916 """
908 removes stats for given repo
917 removes stats for given repo
909
918
910 :param repo_name:
919 :param repo_name:
911 """
920 """
912 repo = self._get_repo(repo_name)
921 repo = self._get_repo(repo_name)
913 try:
922 try:
914 obj = self.sa.query(Statistics) \
923 obj = self.sa.query(Statistics) \
915 .filter(Statistics.repository == repo).scalar()
924 .filter(Statistics.repository == repo).scalar()
916 if obj:
925 if obj:
917 self.sa.delete(obj)
926 self.sa.delete(obj)
918 except Exception:
927 except Exception:
919 log.error(traceback.format_exc())
928 log.error(traceback.format_exc())
920 raise
929 raise
921
930
922 def add_repo_field(self, repo_name, field_key, field_label, field_value='',
931 def add_repo_field(self, repo_name, field_key, field_label, field_value='',
923 field_type='str', field_desc=''):
932 field_type='str', field_desc=''):
924
933
925 repo = self._get_repo(repo_name)
934 repo = self._get_repo(repo_name)
926
935
927 new_field = RepositoryField()
936 new_field = RepositoryField()
928 new_field.repository = repo
937 new_field.repository = repo
929 new_field.field_key = field_key
938 new_field.field_key = field_key
930 new_field.field_type = field_type # python type
939 new_field.field_type = field_type # python type
931 new_field.field_value = field_value
940 new_field.field_value = field_value
932 new_field.field_desc = field_desc
941 new_field.field_desc = field_desc
933 new_field.field_label = field_label
942 new_field.field_label = field_label
934 self.sa.add(new_field)
943 self.sa.add(new_field)
935 return new_field
944 return new_field
936
945
937 def delete_repo_field(self, repo_name, field_key):
946 def delete_repo_field(self, repo_name, field_key):
938 repo = self._get_repo(repo_name)
947 repo = self._get_repo(repo_name)
939 field = RepositoryField.get_by_key_name(field_key, repo)
948 field = RepositoryField.get_by_key_name(field_key, repo)
940 if field:
949 if field:
941 self.sa.delete(field)
950 self.sa.delete(field)
942
951
943 def set_landing_rev(self, repo, landing_rev_name):
952 def set_landing_rev(self, repo, landing_rev_name):
944 if landing_rev_name.startswith('branch:'):
953 if landing_rev_name.startswith('branch:'):
945 landing_rev_name = landing_rev_name.split('branch:')[-1]
954 landing_rev_name = landing_rev_name.split('branch:')[-1]
946 scm_instance = repo.scm_instance()
955 scm_instance = repo.scm_instance()
947 if scm_instance:
956 if scm_instance:
948 return scm_instance._remote.set_head_ref(landing_rev_name)
957 return scm_instance._remote.set_head_ref(landing_rev_name)
949
958
950 def _create_filesystem_repo(self, repo_name, repo_type, repo_group,
959 def _create_filesystem_repo(self, repo_name, repo_type, repo_group,
951 clone_uri=None, repo_store_location=None,
960 clone_uri=None, repo_store_location=None,
952 use_global_config=False, install_hooks=True):
961 use_global_config=False, install_hooks=True):
953 """
962 """
954 makes repository on filesystem. It's group aware means it'll create
963 makes repository on filesystem. It's group aware means it'll create
955 a repository within a group, and alter the paths accordingly of
964 a repository within a group, and alter the paths accordingly of
956 group location
965 group location
957
966
958 :param repo_name:
967 :param repo_name:
959 :param alias:
968 :param alias:
960 :param parent:
969 :param parent:
961 :param clone_uri:
970 :param clone_uri:
962 :param repo_store_location:
971 :param repo_store_location:
963 """
972 """
964 from rhodecode.lib.utils import is_valid_repo, is_valid_repo_group
973 from rhodecode.lib.utils import is_valid_repo, is_valid_repo_group
965 from rhodecode.model.scm import ScmModel
974 from rhodecode.model.scm import ScmModel
966
975
967 if Repository.NAME_SEP in repo_name:
976 if Repository.NAME_SEP in repo_name:
968 raise ValueError(
977 raise ValueError(
969 'repo_name must not contain groups got `%s`' % repo_name)
978 'repo_name must not contain groups got `%s`' % repo_name)
970
979
971 if isinstance(repo_group, RepoGroup):
980 if isinstance(repo_group, RepoGroup):
972 new_parent_path = os.sep.join(repo_group.full_path_splitted)
981 new_parent_path = os.sep.join(repo_group.full_path_splitted)
973 else:
982 else:
974 new_parent_path = repo_group or ''
983 new_parent_path = repo_group or ''
975
984
976 if repo_store_location:
985 if repo_store_location:
977 _paths = [repo_store_location]
986 _paths = [repo_store_location]
978 else:
987 else:
979 _paths = [self.repos_path, new_parent_path, repo_name]
988 _paths = [self.repos_path, new_parent_path, repo_name]
980 # we need to make it str for mercurial
989 # we need to make it str for mercurial
981 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
990 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
982
991
983 # check if this path is not a repository
992 # check if this path is not a repository
984 if is_valid_repo(repo_path, self.repos_path):
993 if is_valid_repo(repo_path, self.repos_path):
985 raise Exception(f'This path {repo_path} is a valid repository')
994 raise Exception(f'This path {repo_path} is a valid repository')
986
995
987 # check if this path is a group
996 # check if this path is a group
988 if is_valid_repo_group(repo_path, self.repos_path):
997 if is_valid_repo_group(repo_path, self.repos_path):
989 raise Exception(f'This path {repo_path} is a valid group')
998 raise Exception(f'This path {repo_path} is a valid group')
990
999
991 log.info('creating repo %s in %s from url: `%s`',
1000 log.info('creating repo %s in %s from url: `%s`',
992 repo_name, safe_str(repo_path),
1001 repo_name, safe_str(repo_path),
993 obfuscate_url_pw(clone_uri))
1002 obfuscate_url_pw(clone_uri))
994
1003
995 backend = get_backend(repo_type)
1004 backend = get_backend(repo_type)
996
1005
997 config_repo = None if use_global_config else repo_name
1006 config_repo = None if use_global_config else repo_name
998 if config_repo and new_parent_path:
1007 if config_repo and new_parent_path:
999 config_repo = Repository.NAME_SEP.join(
1008 config_repo = Repository.NAME_SEP.join(
1000 (new_parent_path, config_repo))
1009 (new_parent_path, config_repo))
1001 config = make_db_config(clear_session=False, repo=config_repo)
1010 config = make_db_config(clear_session=False, repo=config_repo)
1002 config.set('extensions', 'largefiles', '')
1011 config.set('extensions', 'largefiles', '')
1003
1012
1004 # patch and reset hooks section of UI config to not run any
1013 # patch and reset hooks section of UI config to not run any
1005 # hooks on creating remote repo
1014 # hooks on creating remote repo
1006 config.clear_section('hooks')
1015 config.clear_section('hooks')
1007
1016
1008 # TODO: johbo: Unify this, hardcoded "bare=True" does not look nice
1017 # TODO: johbo: Unify this, hardcoded "bare=True" does not look nice
1009 if repo_type == 'git':
1018 if repo_type == 'git':
1010 repo = backend(
1019 repo = backend(
1011 repo_path, config=config, create=True, src_url=clone_uri, bare=True,
1020 repo_path, config=config, create=True, src_url=clone_uri, bare=True,
1012 with_wire={"cache": False})
1021 with_wire={"cache": False})
1013 else:
1022 else:
1014 repo = backend(
1023 repo = backend(
1015 repo_path, config=config, create=True, src_url=clone_uri,
1024 repo_path, config=config, create=True, src_url=clone_uri,
1016 with_wire={"cache": False})
1025 with_wire={"cache": False})
1017
1026
1018 if install_hooks:
1027 if install_hooks:
1019 repo.install_hooks()
1028 repo.install_hooks()
1020
1029
1021 log.debug('Created repo %s with %s backend',
1030 log.debug('Created repo %s with %s backend',
1022 safe_str(repo_name), safe_str(repo_type))
1031 safe_str(repo_name), safe_str(repo_type))
1023 return repo
1032 return repo
1024
1033
1025 def _rename_filesystem_repo(self, old, new):
1034 def _rename_filesystem_repo(self, old, new):
1026 """
1035 """
1027 renames repository on filesystem
1036 renames repository on filesystem
1028
1037
1029 :param old: old name
1038 :param old: old name
1030 :param new: new name
1039 :param new: new name
1031 """
1040 """
1032 log.info('renaming repo from %s to %s', old, new)
1041 log.info('renaming repo from %s to %s', old, new)
1033
1042
1034 old_path = os.path.join(self.repos_path, old)
1043 old_path = os.path.join(self.repos_path, old)
1035 new_path = os.path.join(self.repos_path, new)
1044 new_path = os.path.join(self.repos_path, new)
1036 if os.path.isdir(new_path):
1045 if os.path.isdir(new_path):
1037 raise Exception(
1046 raise Exception(
1038 'Was trying to rename to already existing dir %s' % new_path
1047 'Was trying to rename to already existing dir %s' % new_path
1039 )
1048 )
1040 shutil.move(old_path, new_path)
1049 shutil.move(old_path, new_path)
1041
1050
1042 def _delete_filesystem_repo(self, repo):
1051 def _delete_filesystem_repo(self, repo):
1043 """
1052 """
1044 removes repo from filesystem, the removal is actually made by
1053 removes repo from filesystem, the removal is actually made by
1045 added rm__ prefix into dir, and rename internal .hg/.git dirs so this
1054 added rm__ prefix into dir, and rename internal .hg/.git dirs so this
1046 repository is no longer valid for rhodecode, can be undeleted later on
1055 repository is no longer valid for rhodecode, can be undeleted later on
1047 by reverting the renames on this repository
1056 by reverting the renames on this repository
1048
1057
1049 :param repo: repo object
1058 :param repo: repo object
1050 """
1059 """
1051 rm_path = os.path.join(self.repos_path, repo.repo_name)
1060 rm_path = os.path.join(self.repos_path, repo.repo_name)
1052 repo_group = repo.group
1061 repo_group = repo.group
1053 log.info("delete_filesystem_repo: removing repository %s", rm_path)
1062 log.info("delete_filesystem_repo: removing repository %s", rm_path)
1054 # disable hg/git internal that it doesn't get detected as repo
1063 # disable hg/git internal that it doesn't get detected as repo
1055 alias = repo.repo_type
1064 alias = repo.repo_type
1056
1065
1057 config = make_db_config(clear_session=False)
1066 config = make_db_config(clear_session=False)
1058 config.set('extensions', 'largefiles', '')
1067 config.set('extensions', 'largefiles', '')
1059 bare = getattr(repo.scm_instance(config=config), 'bare', False)
1068 bare = getattr(repo.scm_instance(config=config), 'bare', False)
1060
1069
1061 # skip this for bare git repos
1070 # skip this for bare git repos
1062 if not bare:
1071 if not bare:
1063 # disable VCS repo
1072 # disable VCS repo
1064 vcs_path = os.path.join(rm_path, '.%s' % alias)
1073 vcs_path = os.path.join(rm_path, '.%s' % alias)
1065 if os.path.exists(vcs_path):
1074 if os.path.exists(vcs_path):
1066 shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias))
1075 shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias))
1067
1076
1068 _now = datetime.datetime.now()
1077 _now = datetime.datetime.now()
1069 _ms = str(_now.microsecond).rjust(6, '0')
1078 _ms = str(_now.microsecond).rjust(6, '0')
1070 _d = 'rm__{}__{}'.format(_now.strftime('%Y%m%d_%H%M%S_' + _ms),
1079 _d = 'rm__{}__{}'.format(_now.strftime('%Y%m%d_%H%M%S_' + _ms),
1071 repo.just_name)
1080 repo.just_name)
1072 if repo_group:
1081 if repo_group:
1073 # if repository is in group, prefix the removal path with the group
1082 # if repository is in group, prefix the removal path with the group
1074 args = repo_group.full_path_splitted + [_d]
1083 args = repo_group.full_path_splitted + [_d]
1075 _d = os.path.join(*args)
1084 _d = os.path.join(*args)
1076
1085
1077 if os.path.isdir(rm_path):
1086 if os.path.isdir(rm_path):
1078 shutil.move(rm_path, os.path.join(self.repos_path, _d))
1087 shutil.move(rm_path, os.path.join(self.repos_path, _d))
1079
1088
1080 # finally cleanup diff-cache if it exists
1089 # finally cleanup diff-cache if it exists
1081 cached_diffs_dir = repo.cached_diffs_dir
1090 cached_diffs_dir = repo.cached_diffs_dir
1082 if os.path.isdir(cached_diffs_dir):
1091 if os.path.isdir(cached_diffs_dir):
1083 shutil.rmtree(cached_diffs_dir)
1092 shutil.rmtree(cached_diffs_dir)
1084
1093
1085
1094
1086 class ReadmeFinder:
1095 class ReadmeFinder:
1087 """
1096 """
1088 Utility which knows how to find a readme for a specific commit.
1097 Utility which knows how to find a readme for a specific commit.
1089
1098
1090 The main idea is that this is a configurable algorithm. When creating an
1099 The main idea is that this is a configurable algorithm. When creating an
1091 instance you can define parameters, currently only the `default_renderer`.
1100 instance you can define parameters, currently only the `default_renderer`.
1092 Based on this configuration the method :meth:`search` behaves slightly
1101 Based on this configuration the method :meth:`search` behaves slightly
1093 different.
1102 different.
1094 """
1103 """
1095
1104
1096 readme_re = re.compile(r'^readme(\.[^\.]+)?$', re.IGNORECASE)
1105 readme_re = re.compile(r'^readme(\.[^\.]+)?$', re.IGNORECASE)
1097 path_re = re.compile(r'^docs?', re.IGNORECASE)
1106 path_re = re.compile(r'^docs?', re.IGNORECASE)
1098
1107
1099 default_priorities = {
1108 default_priorities = {
1100 None: 0,
1109 None: 0,
1101 '.rst': 1,
1110 '.rst': 1,
1102 '.md': 1,
1111 '.md': 1,
1103 '.rest': 2,
1112 '.rest': 2,
1104 '.mkdn': 2,
1113 '.mkdn': 2,
1105 '.text': 2,
1114 '.text': 2,
1106 '.txt': 3,
1115 '.txt': 3,
1107 '.mdown': 3,
1116 '.mdown': 3,
1108 '.markdown': 4,
1117 '.markdown': 4,
1109 }
1118 }
1110
1119
1111 path_priority = {
1120 path_priority = {
1112 'doc': 0,
1121 'doc': 0,
1113 'docs': 1,
1122 'docs': 1,
1114 }
1123 }
1115
1124
1116 FALLBACK_PRIORITY = 99
1125 FALLBACK_PRIORITY = 99
1117
1126
1118 RENDERER_TO_EXTENSION = {
1127 RENDERER_TO_EXTENSION = {
1119 'rst': ['.rst', '.rest'],
1128 'rst': ['.rst', '.rest'],
1120 'markdown': ['.md', 'mkdn', '.mdown', '.markdown'],
1129 'markdown': ['.md', 'mkdn', '.mdown', '.markdown'],
1121 }
1130 }
1122
1131
1123 def __init__(self, default_renderer=None):
1132 def __init__(self, default_renderer=None):
1124 self._default_renderer = default_renderer
1133 self._default_renderer = default_renderer
1125 self._renderer_extensions = self.RENDERER_TO_EXTENSION.get(
1134 self._renderer_extensions = self.RENDERER_TO_EXTENSION.get(
1126 default_renderer, [])
1135 default_renderer, [])
1127
1136
1128 def search(self, commit, path='/'):
1137 def search(self, commit, path='/'):
1129 """
1138 """
1130 Find a readme in the given `commit`.
1139 Find a readme in the given `commit`.
1131 """
1140 """
1132 # firstly, check the PATH type if it is actually a DIR
1141 # firstly, check the PATH type if it is actually a DIR
1133 if commit.get_node(path).kind != NodeKind.DIR:
1142 if commit.get_node(path).kind != NodeKind.DIR:
1134 return None
1143 return None
1135
1144
1136 nodes = commit.get_nodes(path)
1145 nodes = commit.get_nodes(path)
1137 matches = self._match_readmes(nodes)
1146 matches = self._match_readmes(nodes)
1138 matches = self._sort_according_to_priority(matches)
1147 matches = self._sort_according_to_priority(matches)
1139 if matches:
1148 if matches:
1140 return matches[0].node
1149 return matches[0].node
1141
1150
1142 paths = self._match_paths(nodes)
1151 paths = self._match_paths(nodes)
1143 paths = self._sort_paths_according_to_priority(paths)
1152 paths = self._sort_paths_according_to_priority(paths)
1144 for path in paths:
1153 for path in paths:
1145 match = self.search(commit, path=path)
1154 match = self.search(commit, path=path)
1146 if match:
1155 if match:
1147 return match
1156 return match
1148
1157
1149 return None
1158 return None
1150
1159
1151 def _match_readmes(self, nodes):
1160 def _match_readmes(self, nodes):
1152 for node in nodes:
1161 for node in nodes:
1153 if not node.is_file():
1162 if not node.is_file():
1154 continue
1163 continue
1155 path = node.path.rsplit('/', 1)[-1]
1164 path = node.path.rsplit('/', 1)[-1]
1156 match = self.readme_re.match(path)
1165 match = self.readme_re.match(path)
1157 if match:
1166 if match:
1158 extension = match.group(1)
1167 extension = match.group(1)
1159 yield ReadmeMatch(node, match, self._priority(extension))
1168 yield ReadmeMatch(node, match, self._priority(extension))
1160
1169
1161 def _match_paths(self, nodes):
1170 def _match_paths(self, nodes):
1162 for node in nodes:
1171 for node in nodes:
1163 if not node.is_dir():
1172 if not node.is_dir():
1164 continue
1173 continue
1165 match = self.path_re.match(node.path)
1174 match = self.path_re.match(node.path)
1166 if match:
1175 if match:
1167 yield node.path
1176 yield node.path
1168
1177
1169 def _priority(self, extension):
1178 def _priority(self, extension):
1170 renderer_priority = (
1179 renderer_priority = (
1171 0 if extension in self._renderer_extensions else 1)
1180 0 if extension in self._renderer_extensions else 1)
1172 extension_priority = self.default_priorities.get(
1181 extension_priority = self.default_priorities.get(
1173 extension, self.FALLBACK_PRIORITY)
1182 extension, self.FALLBACK_PRIORITY)
1174 return (renderer_priority, extension_priority)
1183 return (renderer_priority, extension_priority)
1175
1184
1176 def _sort_according_to_priority(self, matches):
1185 def _sort_according_to_priority(self, matches):
1177
1186
1178 def priority_and_path(match):
1187 def priority_and_path(match):
1179 return (match.priority, match.path)
1188 return (match.priority, match.path)
1180
1189
1181 return sorted(matches, key=priority_and_path)
1190 return sorted(matches, key=priority_and_path)
1182
1191
1183 def _sort_paths_according_to_priority(self, paths):
1192 def _sort_paths_according_to_priority(self, paths):
1184
1193
1185 def priority_and_path(path):
1194 def priority_and_path(path):
1186 return (self.path_priority.get(path, self.FALLBACK_PRIORITY), path)
1195 return (self.path_priority.get(path, self.FALLBACK_PRIORITY), path)
1187
1196
1188 return sorted(paths, key=priority_and_path)
1197 return sorted(paths, key=priority_and_path)
1189
1198
1190
1199
1191 class ReadmeMatch:
1200 class ReadmeMatch:
1192
1201
1193 def __init__(self, node, match, priority):
1202 def __init__(self, node, match, priority):
1194 self.node = node
1203 self.node = node
1195 self._match = match
1204 self._match = match
1196 self.priority = priority
1205 self.priority = priority
1197
1206
1198 @property
1207 @property
1199 def path(self):
1208 def path(self):
1200 return self.node.path
1209 return self.node.path
1201
1210
1202 def __repr__(self):
1211 def __repr__(self):
1203 return f'<ReadmeMatch {self.path} priority={self.priority}'
1212 return f'<ReadmeMatch {self.path} priority={self.priority}'
@@ -1,743 +1,811 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import pytest
20 import pytest
21
21
22 from rhodecode.lib.auth import AuthUser
22 from rhodecode.lib.auth import AuthUser
23 from rhodecode.model.db import (
23 from rhodecode.model.db import (
24 RepoGroup, User, UserGroupRepoGroupToPerm, Permission, UserToPerm,
24 RepoGroup, User, UserGroupRepoGroupToPerm, Permission, UserToPerm,
25 UserGroupToPerm)
25 UserGroupToPerm)
26 from rhodecode.model.meta import Session
26 from rhodecode.model.meta import Session
27 from rhodecode.model.permission import PermissionModel
27 from rhodecode.model.permission import PermissionModel
28 from rhodecode.model.repo import RepoModel
28 from rhodecode.model.repo import RepoModel
29 from rhodecode.model.repo_group import RepoGroupModel
29 from rhodecode.model.repo_group import RepoGroupModel
30 from rhodecode.model.user import UserModel
30 from rhodecode.model.user import UserModel
31 from rhodecode.model.user_group import UserGroupModel
31 from rhodecode.model.user_group import UserGroupModel
32 from rhodecode.tests.fixture import Fixture
32 from rhodecode.tests.fixture import Fixture
33
33
34
34
35 fixture = Fixture()
35 fixture = Fixture()
36
36
37
37
38 @pytest.fixture()
38 @pytest.fixture()
39 def repo_name(backend_hg):
39 def repo_name(backend_hg):
40 return backend_hg.repo_name
40 return backend_hg.repo_name
41
41
42
42
43 class TestPermissions(object):
43 class TestPermissions(object):
44
44
45 @pytest.fixture(scope='class', autouse=True)
45 @pytest.fixture(scope='class', autouse=True)
46 def default_permissions(self, request, baseapp):
46 def default_permissions(self, request, baseapp):
47 # recreate default user to get a clean start
47 # recreate default user to get a clean start
48 PermissionModel().create_default_user_permissions(
48 PermissionModel().create_default_user_permissions(
49 user=User.DEFAULT_USER, force=True)
49 user=User.DEFAULT_USER, force=True)
50 Session().commit()
50 Session().commit()
51
51
52 @pytest.fixture(autouse=True)
52 @pytest.fixture(autouse=True)
53 def prepare_users(self, request):
53 def prepare_users(self, request):
54 # TODO: User creation is a duplicate of test_nofitications, check
54 # TODO: User creation is a duplicate of test_nofitications, check
55 # if that can be unified
55 # if that can be unified
56 self.u1 = UserModel().create_or_update(
56 self.u1 = UserModel().create_or_update(
57 username=u'u1', password=u'qweqwe',
57 username=u'u1', password=u'qweqwe',
58 email=u'u1@rhodecode.org', firstname=u'u1', lastname=u'u1'
58 email=u'u1@rhodecode.org', firstname=u'u1', lastname=u'u1'
59 )
59 )
60 self.u2 = UserModel().create_or_update(
60 self.u2 = UserModel().create_or_update(
61 username=u'u2', password=u'qweqwe',
61 username=u'u2', password=u'qweqwe',
62 email=u'u2@rhodecode.org', firstname=u'u2', lastname=u'u2'
62 email=u'u2@rhodecode.org', firstname=u'u2', lastname=u'u2'
63 )
63 )
64 self.u3 = UserModel().create_or_update(
64 self.u3 = UserModel().create_or_update(
65 username=u'u3', password=u'qweqwe',
65 username=u'u3', password=u'qweqwe',
66 email=u'u3@rhodecode.org', firstname=u'u3', lastname=u'u3'
66 email=u'u3@rhodecode.org', firstname=u'u3', lastname=u'u3'
67 )
67 )
68 self.anon = User.get_default_user()
68 self.anon = User.get_default_user()
69 self.a1 = UserModel().create_or_update(
69 self.a1 = UserModel().create_or_update(
70 username=u'a1', password=u'qweqwe',
70 username=u'a1', password=u'qweqwe',
71 email=u'a1@rhodecode.org', firstname=u'a1', lastname=u'a1',
71 email=u'a1@rhodecode.org', firstname=u'a1', lastname=u'a1',
72 admin=True
72 admin=True
73 )
73 )
74 Session().commit()
74 Session().commit()
75
75
76 request.addfinalizer(self.cleanup)
76 request.addfinalizer(self.cleanup)
77
77
78 def cleanup(self):
78 def cleanup(self):
79 if hasattr(self, 'test_repo'):
79 if hasattr(self, 'test_repo'):
80 RepoModel().delete(repo=self.test_repo)
80 RepoModel().delete(repo=self.test_repo)
81 Session().commit()
81 Session().commit()
82
82
83 if hasattr(self, 'g1'):
83 if hasattr(self, 'g1'):
84 RepoGroupModel().delete(self.g1.group_id)
84 RepoGroupModel().delete(self.g1.group_id)
85 if hasattr(self, 'g2'):
85 if hasattr(self, 'g2'):
86 RepoGroupModel().delete(self.g2.group_id)
86 RepoGroupModel().delete(self.g2.group_id)
87 Session().commit()
87 Session().commit()
88
88
89 UserModel().delete(self.u1, handle_repos='delete', handle_repo_groups='delete')
89 UserModel().delete(self.u1, handle_repos='delete', handle_repo_groups='delete')
90 UserModel().delete(self.u2, handle_repos='delete', handle_repo_groups='delete')
90 UserModel().delete(self.u2, handle_repos='delete', handle_repo_groups='delete')
91 UserModel().delete(self.u3, handle_repos='delete', handle_repo_groups='delete')
91 UserModel().delete(self.u3, handle_repos='delete', handle_repo_groups='delete')
92 UserModel().delete(self.a1, handle_repos='delete', handle_repo_groups='delete')
92 UserModel().delete(self.a1, handle_repos='delete', handle_repo_groups='delete')
93 Session().commit()
93 Session().commit()
94
94
95 if hasattr(self, 'ug1'):
95 if hasattr(self, 'ug1'):
96 UserGroupModel().delete(self.ug1, force=True)
96 UserGroupModel().delete(self.ug1, force=True)
97 Session().commit()
97 Session().commit()
98
98
99 def test_default_perms_set(self, repo_name):
99 def test_default_perms_set(self, repo_name):
100 assert repo_perms(self.u1)[repo_name] == 'repository.read'
100 assert repo_perms(self.u1)[repo_name] == 'repository.read'
101 new_perm = 'repository.write'
101 new_perm = 'repository.write'
102 RepoModel().grant_user_permission(repo=repo_name, user=self.u1,
102 RepoModel().grant_user_permission(repo=repo_name, user=self.u1,
103 perm=new_perm)
103 perm=new_perm)
104 Session().commit()
104 Session().commit()
105 assert repo_perms(self.u1)[repo_name] == new_perm
105 assert repo_perms(self.u1)[repo_name] == new_perm
106
106
107 def test_default_admin_perms_set(self, repo_name):
107 def test_default_admin_perms_set(self, repo_name):
108 assert repo_perms(self.a1)[repo_name] == 'repository.admin'
108 assert repo_perms(self.a1)[repo_name] == 'repository.admin'
109 RepoModel().grant_user_permission(repo=repo_name, user=self.a1,
109 RepoModel().grant_user_permission(repo=repo_name, user=self.a1,
110 perm='repository.write')
110 perm='repository.write')
111 Session().commit()
111 Session().commit()
112 # cannot really downgrade admins permissions !? they still gets set as
112 # cannot really downgrade admins permissions !? they still gets set as
113 # admin !
113 # admin !
114 assert repo_perms(self.a1)[repo_name] == 'repository.admin'
114 assert repo_perms(self.a1)[repo_name] == 'repository.admin'
115
115
116 def test_default_group_perms(self, repo_name):
116 def test_default_group_perms(self, repo_name):
117 self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
117 self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
118 self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
118 self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
119
119
120 assert repo_perms(self.u1)[repo_name] == 'repository.read'
120 assert repo_perms(self.u1)[repo_name] == 'repository.read'
121 assert group_perms(self.u1) == {
121 assert group_perms(self.u1) == {
122 'test1': 'group.read', 'test2': 'group.read'}
122 'test1': 'group.read', 'test2': 'group.read'}
123 assert global_perms(self.u1) == set(
123 assert global_perms(self.u1) == set(
124 Permission.DEFAULT_USER_PERMISSIONS)
124 Permission.DEFAULT_USER_PERMISSIONS)
125
125
126 def test_default_admin_group_perms(self, repo_name):
126 def test_default_admin_group_perms(self, repo_name):
127 self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
127 self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
128 self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
128 self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
129
129
130 assert repo_perms(self.a1)[repo_name] == 'repository.admin'
130 assert repo_perms(self.a1)[repo_name] == 'repository.admin'
131 assert group_perms(self.a1) == {
131 assert group_perms(self.a1) == {
132 'test1': 'group.admin', 'test2': 'group.admin'}
132 'test1': 'group.admin', 'test2': 'group.admin'}
133
133
134 def test_default_owner_repo_perms(self, backend, user_util, test_repo):
134 def test_default_owner_repo_perms(self, backend, user_util, test_repo):
135 user = user_util.create_user()
135 user = user_util.create_user()
136 repo = test_repo('minimal', backend.alias)
136 repo = test_repo('minimal', backend.alias)
137 org_owner = repo.user
137 org_owner = repo.user
138 assert repo_perms(user)[repo.repo_name] == 'repository.read'
138 assert repo_perms(user)[repo.repo_name] == 'repository.read'
139
139
140 repo.user = user
140 repo.user = user
141 assert repo_perms(user)[repo.repo_name] == 'repository.admin'
141 assert repo_perms(user)[repo.repo_name] == 'repository.admin'
142 repo.user = org_owner
142 repo.user = org_owner
143
143
144 def test_default_owner_branch_perms(self, user_util, test_user_group):
144 def test_default_owner_branch_perms(self, user_util, test_user_group):
145 user = user_util.create_user()
145 user = user_util.create_user()
146 assert branch_perms(user) == {}
146 assert branch_perms(user) == {}
147
147
148 def test_default_owner_repo_group_perms(self, user_util, test_repo_group):
148 def test_default_owner_repo_group_perms(self, user_util, test_repo_group):
149 user = user_util.create_user()
149 user = user_util.create_user()
150 org_owner = test_repo_group.user
150 org_owner = test_repo_group.user
151
151
152 assert group_perms(user)[test_repo_group.group_name] == 'group.read'
152 assert group_perms(user)[test_repo_group.group_name] == 'group.read'
153
153
154 test_repo_group.user = user
154 test_repo_group.user = user
155 assert group_perms(user)[test_repo_group.group_name] == 'group.admin'
155 assert group_perms(user)[test_repo_group.group_name] == 'group.admin'
156 test_repo_group.user = org_owner
156 test_repo_group.user = org_owner
157
157
158 def test_default_owner_user_group_perms(self, user_util, test_user_group):
158 def test_default_owner_user_group_perms(self, user_util, test_user_group):
159 user = user_util.create_user()
159 user = user_util.create_user()
160 org_owner = test_user_group.user
160 org_owner = test_user_group.user
161
161
162 assert user_group_perms(user)[test_user_group.users_group_name] == 'usergroup.read'
162 assert user_group_perms(user)[test_user_group.users_group_name] == 'usergroup.read'
163
163
164 test_user_group.user = user
164 test_user_group.user = user
165 assert user_group_perms(user)[test_user_group.users_group_name] == 'usergroup.admin'
165 assert user_group_perms(user)[test_user_group.users_group_name] == 'usergroup.admin'
166
166
167 test_user_group.user = org_owner
167 test_user_group.user = org_owner
168
168
169 def test_propagated_permissions_from_repo_group_to_private_repo(self, repo_name):
170 # make group
171 self.g1 = fixture.create_repo_group('TOP_LEVEL', skip_if_exists=True)
172 # both perms should be read !
173 assert group_perms(self.anon) == {
174 'TOP_LEVEL': 'group.read'
175 }
176
177 # Create repo inside the TOP_LEVEL
178 repo_name_in_group = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm_on_private_repo'])
179 self.test_repo = fixture.create_repo(name=repo_name_in_group,
180 repo_type='hg',
181 repo_group=self.g1,
182 cur_user=self.u1,)
183 assert repo_perms(self.anon) == {
184 repo_name_in_group: 'repository.read',
185 'vcs_test_git': 'repository.read',
186 'vcs_test_hg': 'repository.read',
187 'vcs_test_svn': 'repository.read',
188 }
189 # Now change default user permissions
190 new_perm = 'repository.write'
191 perm_updates = [
192 [self.anon.user_id, new_perm, 'user']
193 ]
194 RepoGroupModel().update_permissions(
195 repo_group=self.g1, perm_updates=perm_updates, recursive='all')
196
197 Session().commit()
198 assert repo_perms(self.anon) == {
199 repo_name_in_group: new_perm,
200 'vcs_test_git': 'repository.read',
201 'vcs_test_hg': 'repository.read',
202 'vcs_test_svn': 'repository.read',
203 }
204
205 # NOW MARK repo as private
206 changes = {
207 'repo_private': True
208 }
209 repo = RepoModel().get_by_repo_name(repo_name_in_group)
210 RepoModel().update(repo, **changes)
211 Session().commit()
212
213 # Private repo sets 'none' permission for default user
214 assert repo_perms(self.anon) == {
215 repo_name_in_group: 'repository.none',
216 'vcs_test_git': 'repository.read',
217 'vcs_test_hg': 'repository.read',
218 'vcs_test_svn': 'repository.read',
219 }
220
221 # apply same logic of "updated" recursive, but now the anon permissions should be not be impacted
222 new_perm = 'repository.write'
223 perm_updates = [
224 [self.anon.user_id, new_perm, 'user']
225 ]
226 RepoGroupModel().update_permissions(
227 repo_group=self.g1, perm_updates=perm_updates, recursive='all')
228
229 Session().commit()
230 assert repo_perms(self.anon) == {
231 repo_name_in_group: 'repository.none',
232 'vcs_test_git': 'repository.read',
233 'vcs_test_hg': 'repository.read',
234 'vcs_test_svn': 'repository.read',
235 }
236
169 def test_propagated_permission_from_users_group_by_explicit_perms_exist(
237 def test_propagated_permission_from_users_group_by_explicit_perms_exist(
170 self, repo_name):
238 self, repo_name):
171 # make group
239 # make group
172 self.ug1 = fixture.create_user_group('G1')
240 self.ug1 = fixture.create_user_group('G1')
173 UserGroupModel().add_user_to_group(self.ug1, self.u1)
241 UserGroupModel().add_user_to_group(self.ug1, self.u1)
174
242
175 # set permission to lower
243 # set permission to lower
176 new_perm = 'repository.none'
244 new_perm = 'repository.none'
177 RepoModel().grant_user_permission(
245 RepoModel().grant_user_permission(
178 repo=repo_name, user=self.u1, perm=new_perm)
246 repo=repo_name, user=self.u1, perm=new_perm)
179 Session().commit()
247 Session().commit()
180 assert repo_perms(self.u1)[repo_name] == new_perm
248 assert repo_perms(self.u1)[repo_name] == new_perm
181
249
182 # grant perm for group this should not override permission from user
250 # grant perm for group this should not override permission from user
183 # since it has explicitly set
251 # since it has explicitly set
184 new_perm_gr = 'repository.write'
252 new_perm_gr = 'repository.write'
185 RepoModel().grant_user_group_permission(
253 RepoModel().grant_user_group_permission(
186 repo=repo_name, group_name=self.ug1, perm=new_perm_gr)
254 repo=repo_name, group_name=self.ug1, perm=new_perm_gr)
187 Session().commit()
255 Session().commit()
188
256
189 assert repo_perms(self.u1)[repo_name] == new_perm
257 assert repo_perms(self.u1)[repo_name] == new_perm
190 assert group_perms(self.u1) == {}
258 assert group_perms(self.u1) == {}
191
259
192 def test_propagated_permission_from_users_group(self, repo_name):
260 def test_propagated_permission_from_users_group(self, repo_name):
193 # make group
261 # make group
194 self.ug1 = fixture.create_user_group('G1')
262 self.ug1 = fixture.create_user_group('G1')
195 UserGroupModel().add_user_to_group(self.ug1, self.u3)
263 UserGroupModel().add_user_to_group(self.ug1, self.u3)
196
264
197 # grant perm for group
265 # grant perm for group
198 # this should override default permission from user
266 # this should override default permission from user
199 new_perm_gr = 'repository.write'
267 new_perm_gr = 'repository.write'
200 RepoModel().grant_user_group_permission(
268 RepoModel().grant_user_group_permission(
201 repo=repo_name, group_name=self.ug1, perm=new_perm_gr)
269 repo=repo_name, group_name=self.ug1, perm=new_perm_gr)
202 Session().commit()
270 Session().commit()
203
271
204 assert repo_perms(self.u3)[repo_name] == new_perm_gr
272 assert repo_perms(self.u3)[repo_name] == new_perm_gr
205 assert group_perms(self.u3) == {}
273 assert group_perms(self.u3) == {}
206
274
207 def test_propagated_permission_from_users_group_lower_weight(
275 def test_propagated_permission_from_users_group_lower_weight(
208 self, repo_name):
276 self, repo_name):
209 # make group with user
277 # make group with user
210 self.ug1 = fixture.create_user_group('G1')
278 self.ug1 = fixture.create_user_group('G1')
211 UserGroupModel().add_user_to_group(self.ug1, self.u1)
279 UserGroupModel().add_user_to_group(self.ug1, self.u1)
212
280
213 # set permission to lower
281 # set permission to lower
214 new_perm_h = 'repository.write'
282 new_perm_h = 'repository.write'
215 RepoModel().grant_user_permission(
283 RepoModel().grant_user_permission(
216 repo=repo_name, user=self.u1, perm=new_perm_h)
284 repo=repo_name, user=self.u1, perm=new_perm_h)
217 Session().commit()
285 Session().commit()
218
286
219 assert repo_perms(self.u1)[repo_name] == new_perm_h
287 assert repo_perms(self.u1)[repo_name] == new_perm_h
220
288
221 # grant perm for group this should NOT override permission from user
289 # grant perm for group this should NOT override permission from user
222 # since it's lower than granted
290 # since it's lower than granted
223 new_perm_l = 'repository.read'
291 new_perm_l = 'repository.read'
224 RepoModel().grant_user_group_permission(
292 RepoModel().grant_user_group_permission(
225 repo=repo_name, group_name=self.ug1, perm=new_perm_l)
293 repo=repo_name, group_name=self.ug1, perm=new_perm_l)
226 Session().commit()
294 Session().commit()
227
295
228 assert repo_perms(self.u1)[repo_name] == new_perm_h
296 assert repo_perms(self.u1)[repo_name] == new_perm_h
229 assert group_perms(self.u1) == {}
297 assert group_perms(self.u1) == {}
230
298
231 def test_repo_in_group_permissions(self):
299 def test_repo_in_group_permissions(self):
232 self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
300 self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
233 self.g2 = fixture.create_repo_group('group2', skip_if_exists=True)
301 self.g2 = fixture.create_repo_group('group2', skip_if_exists=True)
234 # both perms should be read !
302 # both perms should be read !
235 assert group_perms(self.u1) == \
303 assert group_perms(self.u1) == \
236 {u'group1': u'group.read', u'group2': u'group.read'}
304 {u'group1': u'group.read', u'group2': u'group.read'}
237
305
238 assert group_perms(self.anon) == \
306 assert group_perms(self.anon) == \
239 {u'group1': u'group.read', u'group2': u'group.read'}
307 {u'group1': u'group.read', u'group2': u'group.read'}
240
308
241 # Change perms to none for both groups
309 # Change perms to none for both groups
242 RepoGroupModel().grant_user_permission(
310 RepoGroupModel().grant_user_permission(
243 repo_group=self.g1, user=self.anon, perm='group.none')
311 repo_group=self.g1, user=self.anon, perm='group.none')
244 RepoGroupModel().grant_user_permission(
312 RepoGroupModel().grant_user_permission(
245 repo_group=self.g2, user=self.anon, perm='group.none')
313 repo_group=self.g2, user=self.anon, perm='group.none')
246
314
247 assert group_perms(self.u1) == \
315 assert group_perms(self.u1) == \
248 {u'group1': u'group.none', u'group2': u'group.none'}
316 {u'group1': u'group.none', u'group2': u'group.none'}
249 assert group_perms(self.anon) == \
317 assert group_perms(self.anon) == \
250 {u'group1': u'group.none', u'group2': u'group.none'}
318 {u'group1': u'group.none', u'group2': u'group.none'}
251
319
252 # add repo to group
320 # add repo to group
253 name = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm'])
321 name = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm'])
254 self.test_repo = fixture.create_repo(name=name,
322 self.test_repo = fixture.create_repo(name=name,
255 repo_type='hg',
323 repo_type='hg',
256 repo_group=self.g1,
324 repo_group=self.g1,
257 cur_user=self.u1,)
325 cur_user=self.u1,)
258
326
259 assert group_perms(self.u1) == \
327 assert group_perms(self.u1) == \
260 {u'group1': u'group.none', u'group2': u'group.none'}
328 {u'group1': u'group.none', u'group2': u'group.none'}
261 assert group_perms(self.anon) == \
329 assert group_perms(self.anon) == \
262 {u'group1': u'group.none', u'group2': u'group.none'}
330 {u'group1': u'group.none', u'group2': u'group.none'}
263
331
264 # grant permission for u2 !
332 # grant permission for u2 !
265 RepoGroupModel().grant_user_permission(
333 RepoGroupModel().grant_user_permission(
266 repo_group=self.g1, user=self.u2, perm='group.read')
334 repo_group=self.g1, user=self.u2, perm='group.read')
267 RepoGroupModel().grant_user_permission(
335 RepoGroupModel().grant_user_permission(
268 repo_group=self.g2, user=self.u2, perm='group.read')
336 repo_group=self.g2, user=self.u2, perm='group.read')
269 Session().commit()
337 Session().commit()
270 assert self.u1 != self.u2
338 assert self.u1 != self.u2
271
339
272 # u1 and anon should have not change perms while u2 should !
340 # u1 and anon should have not change perms while u2 should !
273 assert group_perms(self.u1) == \
341 assert group_perms(self.u1) == \
274 {u'group1': u'group.none', u'group2': u'group.none'}
342 {u'group1': u'group.none', u'group2': u'group.none'}
275 assert group_perms(self.u2) == \
343 assert group_perms(self.u2) == \
276 {u'group1': u'group.read', u'group2': u'group.read'}
344 {u'group1': u'group.read', u'group2': u'group.read'}
277 assert group_perms(self.anon) == \
345 assert group_perms(self.anon) == \
278 {u'group1': u'group.none', u'group2': u'group.none'}
346 {u'group1': u'group.none', u'group2': u'group.none'}
279
347
280 def test_repo_group_user_as_user_group_member(self):
348 def test_repo_group_user_as_user_group_member(self):
281 # create Group1
349 # create Group1
282 self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
350 self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
283 assert group_perms(self.anon) == {u'group1': u'group.read'}
351 assert group_perms(self.anon) == {u'group1': u'group.read'}
284
352
285 # set default permission to none
353 # set default permission to none
286 RepoGroupModel().grant_user_permission(
354 RepoGroupModel().grant_user_permission(
287 repo_group=self.g1, user=self.anon, perm='group.none')
355 repo_group=self.g1, user=self.anon, perm='group.none')
288 Session().commit()
356 Session().commit()
289
357
290 # make group
358 # make group
291 self.ug1 = fixture.create_user_group('G1')
359 self.ug1 = fixture.create_user_group('G1')
292 # add user to group
360 # add user to group
293 UserGroupModel().add_user_to_group(self.ug1, self.u1)
361 UserGroupModel().add_user_to_group(self.ug1, self.u1)
294 Session().commit()
362 Session().commit()
295
363
296 # check if user is in the group
364 # check if user is in the group
297 ug1 = UserGroupModel().get(self.ug1.users_group_id)
365 ug1 = UserGroupModel().get(self.ug1.users_group_id)
298 members = [x.user_id for x in ug1.members]
366 members = [x.user_id for x in ug1.members]
299 assert members == [self.u1.user_id]
367 assert members == [self.u1.user_id]
300 # add some user to that group
368 # add some user to that group
301
369
302 # check his permissions
370 # check his permissions
303 assert group_perms(self.anon) == {u'group1': u'group.none'}
371 assert group_perms(self.anon) == {u'group1': u'group.none'}
304 assert group_perms(self.u1) == {u'group1': u'group.none'}
372 assert group_perms(self.u1) == {u'group1': u'group.none'}
305
373
306 # grant ug1 read permissions for
374 # grant ug1 read permissions for
307 RepoGroupModel().grant_user_group_permission(
375 RepoGroupModel().grant_user_group_permission(
308 repo_group=self.g1, group_name=self.ug1, perm='group.read')
376 repo_group=self.g1, group_name=self.ug1, perm='group.read')
309 Session().commit()
377 Session().commit()
310
378
311 # check if the
379 # check if the
312 obj = Session().query(UserGroupRepoGroupToPerm)\
380 obj = Session().query(UserGroupRepoGroupToPerm)\
313 .filter(UserGroupRepoGroupToPerm.group == self.g1)\
381 .filter(UserGroupRepoGroupToPerm.group == self.g1)\
314 .filter(UserGroupRepoGroupToPerm.users_group == self.ug1)\
382 .filter(UserGroupRepoGroupToPerm.users_group == self.ug1)\
315 .scalar()
383 .scalar()
316 assert obj.permission.permission_name == 'group.read'
384 assert obj.permission.permission_name == 'group.read'
317
385
318 assert group_perms(self.anon) == {u'group1': u'group.none'}
386 assert group_perms(self.anon) == {u'group1': u'group.none'}
319 assert group_perms(self.u1) == {u'group1': u'group.read'}
387 assert group_perms(self.u1) == {u'group1': u'group.read'}
320
388
321 def test_inherited_permissions_from_default_on_user_enabled(self):
389 def test_inherited_permissions_from_default_on_user_enabled(self):
322 # enable fork and create on default user
390 # enable fork and create on default user
323 _form_result = {
391 _form_result = {
324 'default_repo_create': 'hg.create.repository',
392 'default_repo_create': 'hg.create.repository',
325 'default_fork_create': 'hg.fork.repository'
393 'default_fork_create': 'hg.fork.repository'
326 }
394 }
327 PermissionModel().set_new_user_perms(
395 PermissionModel().set_new_user_perms(
328 User.get_default_user(), _form_result)
396 User.get_default_user(), _form_result)
329 Session().commit()
397 Session().commit()
330
398
331 # make sure inherit flag is turned on
399 # make sure inherit flag is turned on
332 self.u1.inherit_default_permissions = True
400 self.u1.inherit_default_permissions = True
333 Session().commit()
401 Session().commit()
334
402
335 # this user will have inherited permissions from default user
403 # this user will have inherited permissions from default user
336 assert global_perms(self.u1) == default_perms()
404 assert global_perms(self.u1) == default_perms()
337
405
338 def test_inherited_permissions_from_default_on_user_disabled(self):
406 def test_inherited_permissions_from_default_on_user_disabled(self):
339 # disable fork and create on default user
407 # disable fork and create on default user
340 _form_result = {
408 _form_result = {
341 'default_repo_create': 'hg.create.none',
409 'default_repo_create': 'hg.create.none',
342 'default_fork_create': 'hg.fork.none'
410 'default_fork_create': 'hg.fork.none'
343 }
411 }
344 PermissionModel().set_new_user_perms(
412 PermissionModel().set_new_user_perms(
345 User.get_default_user(), _form_result)
413 User.get_default_user(), _form_result)
346 Session().commit()
414 Session().commit()
347
415
348 # make sure inherit flag is turned on
416 # make sure inherit flag is turned on
349 self.u1.inherit_default_permissions = True
417 self.u1.inherit_default_permissions = True
350 Session().commit()
418 Session().commit()
351
419
352 # this user will have inherited permissions from default user
420 # this user will have inherited permissions from default user
353 expected_perms = default_perms(
421 expected_perms = default_perms(
354 added=['hg.create.none', 'hg.fork.none'],
422 added=['hg.create.none', 'hg.fork.none'],
355 removed=['hg.create.repository', 'hg.fork.repository'])
423 removed=['hg.create.repository', 'hg.fork.repository'])
356 assert global_perms(self.u1) == expected_perms
424 assert global_perms(self.u1) == expected_perms
357
425
358 def test_non_inherited_permissions_from_default_on_user_enabled(self):
426 def test_non_inherited_permissions_from_default_on_user_enabled(self):
359 user_model = UserModel()
427 user_model = UserModel()
360 # enable fork and create on default user
428 # enable fork and create on default user
361 usr = User.DEFAULT_USER
429 usr = User.DEFAULT_USER
362 user_model.revoke_perm(usr, 'hg.create.none')
430 user_model.revoke_perm(usr, 'hg.create.none')
363 user_model.grant_perm(usr, 'hg.create.repository')
431 user_model.grant_perm(usr, 'hg.create.repository')
364 user_model.revoke_perm(usr, 'hg.fork.none')
432 user_model.revoke_perm(usr, 'hg.fork.none')
365 user_model.grant_perm(usr, 'hg.fork.repository')
433 user_model.grant_perm(usr, 'hg.fork.repository')
366
434
367 # disable global perms on specific user
435 # disable global perms on specific user
368 user_model.revoke_perm(self.u1, 'hg.create.repository')
436 user_model.revoke_perm(self.u1, 'hg.create.repository')
369 user_model.grant_perm(self.u1, 'hg.create.none')
437 user_model.grant_perm(self.u1, 'hg.create.none')
370 user_model.revoke_perm(self.u1, 'hg.fork.repository')
438 user_model.revoke_perm(self.u1, 'hg.fork.repository')
371 user_model.grant_perm(self.u1, 'hg.fork.none')
439 user_model.grant_perm(self.u1, 'hg.fork.none')
372
440
373 # TODO(marcink): check branch permissions now ?
441 # TODO(marcink): check branch permissions now ?
374
442
375 # make sure inherit flag is turned off
443 # make sure inherit flag is turned off
376 self.u1.inherit_default_permissions = False
444 self.u1.inherit_default_permissions = False
377 Session().commit()
445 Session().commit()
378
446
379 # this user will have non inherited permissions from he's
447 # this user will have non inherited permissions from he's
380 # explicitly set permissions
448 # explicitly set permissions
381 assert global_perms(self.u1) == {
449 assert global_perms(self.u1) == {
382 'hg.create.none',
450 'hg.create.none',
383 'hg.fork.none',
451 'hg.fork.none',
384 'hg.register.manual_activate',
452 'hg.register.manual_activate',
385 'hg.password_reset.enabled',
453 'hg.password_reset.enabled',
386 'hg.extern_activate.auto',
454 'hg.extern_activate.auto',
387 'repository.read',
455 'repository.read',
388 'group.read',
456 'group.read',
389 'usergroup.read',
457 'usergroup.read',
390 'branch.push_force',
458 'branch.push_force',
391 }
459 }
392
460
393 def test_non_inherited_permissions_from_default_on_user_disabled(self):
461 def test_non_inherited_permissions_from_default_on_user_disabled(self):
394 user_model = UserModel()
462 user_model = UserModel()
395 # disable fork and create on default user
463 # disable fork and create on default user
396 usr = User.DEFAULT_USER
464 usr = User.DEFAULT_USER
397 user_model.revoke_perm(usr, 'hg.create.repository')
465 user_model.revoke_perm(usr, 'hg.create.repository')
398 user_model.grant_perm(usr, 'hg.create.none')
466 user_model.grant_perm(usr, 'hg.create.none')
399 user_model.revoke_perm(usr, 'hg.fork.repository')
467 user_model.revoke_perm(usr, 'hg.fork.repository')
400 user_model.grant_perm(usr, 'hg.fork.none')
468 user_model.grant_perm(usr, 'hg.fork.none')
401
469
402 # enable global perms on specific user
470 # enable global perms on specific user
403 user_model.revoke_perm(self.u1, 'hg.create.none')
471 user_model.revoke_perm(self.u1, 'hg.create.none')
404 user_model.grant_perm(self.u1, 'hg.create.repository')
472 user_model.grant_perm(self.u1, 'hg.create.repository')
405 user_model.revoke_perm(self.u1, 'hg.fork.none')
473 user_model.revoke_perm(self.u1, 'hg.fork.none')
406 user_model.grant_perm(self.u1, 'hg.fork.repository')
474 user_model.grant_perm(self.u1, 'hg.fork.repository')
407
475
408 # make sure inherit flag is turned off
476 # make sure inherit flag is turned off
409 self.u1.inherit_default_permissions = False
477 self.u1.inherit_default_permissions = False
410 Session().commit()
478 Session().commit()
411
479
412 # TODO(marcink): check branch perms
480 # TODO(marcink): check branch perms
413
481
414 # this user will have non inherited permissions from he's
482 # this user will have non inherited permissions from he's
415 # explicitly set permissions
483 # explicitly set permissions
416 assert global_perms(self.u1) == {
484 assert global_perms(self.u1) == {
417 'hg.create.repository',
485 'hg.create.repository',
418 'hg.fork.repository',
486 'hg.fork.repository',
419 'hg.register.manual_activate',
487 'hg.register.manual_activate',
420 'hg.password_reset.enabled',
488 'hg.password_reset.enabled',
421 'hg.extern_activate.auto',
489 'hg.extern_activate.auto',
422 'repository.read',
490 'repository.read',
423 'group.read',
491 'group.read',
424 'usergroup.read',
492 'usergroup.read',
425 'branch.push_force',
493 'branch.push_force',
426 }
494 }
427
495
428 @pytest.mark.parametrize('perm, expected_perm', [
496 @pytest.mark.parametrize('perm, expected_perm', [
429 ('hg.inherit_default_perms.false', 'repository.none', ),
497 ('hg.inherit_default_perms.false', 'repository.none', ),
430 ('hg.inherit_default_perms.true', 'repository.read', ),
498 ('hg.inherit_default_perms.true', 'repository.read', ),
431 ])
499 ])
432 def test_inherited_permissions_on_objects(self, perm, expected_perm):
500 def test_inherited_permissions_on_objects(self, perm, expected_perm):
433 _form_result = {
501 _form_result = {
434 'default_inherit_default_permissions': perm,
502 'default_inherit_default_permissions': perm,
435 }
503 }
436 PermissionModel().set_new_user_perms(
504 PermissionModel().set_new_user_perms(
437 User.get_default_user(), _form_result)
505 User.get_default_user(), _form_result)
438 Session().commit()
506 Session().commit()
439
507
440 # make sure inherit flag is turned on
508 # make sure inherit flag is turned on
441 self.u1.inherit_default_permissions = True
509 self.u1.inherit_default_permissions = True
442 Session().commit()
510 Session().commit()
443
511
444 # TODO(marcink): check branch perms
512 # TODO(marcink): check branch perms
445
513
446 # this user will have inherited permissions from default user
514 # this user will have inherited permissions from default user
447 assert global_perms(self.u1) == {
515 assert global_perms(self.u1) == {
448 'hg.create.none',
516 'hg.create.none',
449 'hg.fork.none',
517 'hg.fork.none',
450 'hg.register.manual_activate',
518 'hg.register.manual_activate',
451 'hg.password_reset.enabled',
519 'hg.password_reset.enabled',
452 'hg.extern_activate.auto',
520 'hg.extern_activate.auto',
453 'repository.read',
521 'repository.read',
454 'group.read',
522 'group.read',
455 'usergroup.read',
523 'usergroup.read',
456 'branch.push_force',
524 'branch.push_force',
457 'hg.create.write_on_repogroup.true',
525 'hg.create.write_on_repogroup.true',
458 'hg.usergroup.create.false',
526 'hg.usergroup.create.false',
459 'hg.repogroup.create.false',
527 'hg.repogroup.create.false',
460 perm
528 perm
461 }
529 }
462
530
463 assert set(repo_perms(self.u1).values()) == set([expected_perm])
531 assert set(repo_perms(self.u1).values()) == set([expected_perm])
464
532
465 def test_repo_owner_permissions_not_overwritten_by_group(self):
533 def test_repo_owner_permissions_not_overwritten_by_group(self):
466 # create repo as USER,
534 # create repo as USER,
467 self.test_repo = fixture.create_repo(name='myownrepo',
535 self.test_repo = fixture.create_repo(name='myownrepo',
468 repo_type='hg',
536 repo_type='hg',
469 cur_user=self.u1)
537 cur_user=self.u1)
470
538
471 # he has permissions of admin as owner
539 # he has permissions of admin as owner
472 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
540 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
473
541
474 # set his permission as user group, he should still be admin
542 # set his permission as user group, he should still be admin
475 self.ug1 = fixture.create_user_group('G1')
543 self.ug1 = fixture.create_user_group('G1')
476 UserGroupModel().add_user_to_group(self.ug1, self.u1)
544 UserGroupModel().add_user_to_group(self.ug1, self.u1)
477 RepoModel().grant_user_group_permission(
545 RepoModel().grant_user_group_permission(
478 self.test_repo,
546 self.test_repo,
479 group_name=self.ug1,
547 group_name=self.ug1,
480 perm='repository.none')
548 perm='repository.none')
481 Session().commit()
549 Session().commit()
482
550
483 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
551 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
484
552
485 def test_repo_owner_permissions_not_overwritten_by_others(self):
553 def test_repo_owner_permissions_not_overwritten_by_others(self):
486 # create repo as USER,
554 # create repo as USER,
487 self.test_repo = fixture.create_repo(name='myownrepo',
555 self.test_repo = fixture.create_repo(name='myownrepo',
488 repo_type='hg',
556 repo_type='hg',
489 cur_user=self.u1)
557 cur_user=self.u1)
490
558
491 # he has permissions of admin as owner
559 # he has permissions of admin as owner
492 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
560 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
493
561
494 # set his permission as user, he should still be admin
562 # set his permission as user, he should still be admin
495 RepoModel().grant_user_permission(
563 RepoModel().grant_user_permission(
496 self.test_repo, user=self.u1, perm='repository.none')
564 self.test_repo, user=self.u1, perm='repository.none')
497 Session().commit()
565 Session().commit()
498
566
499 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
567 assert repo_perms(self.u1)['myownrepo'] == 'repository.admin'
500
568
501 def test_repo_group_owner_permissions_not_overwritten_by_group(self):
569 def test_repo_group_owner_permissions_not_overwritten_by_group(self):
502 # "u1" shall be owner without any special permission assigned
570 # "u1" shall be owner without any special permission assigned
503 self.g1 = fixture.create_repo_group('test1')
571 self.g1 = fixture.create_repo_group('test1')
504
572
505 # Make user group and grant a permission to user group
573 # Make user group and grant a permission to user group
506 self.ug1 = fixture.create_user_group('G1')
574 self.ug1 = fixture.create_user_group('G1')
507 UserGroupModel().add_user_to_group(self.ug1, self.u1)
575 UserGroupModel().add_user_to_group(self.ug1, self.u1)
508 RepoGroupModel().grant_user_group_permission(
576 RepoGroupModel().grant_user_group_permission(
509 repo_group=self.g1, group_name=self.ug1, perm='group.write')
577 repo_group=self.g1, group_name=self.ug1, perm='group.write')
510 Session().commit()
578 Session().commit()
511
579
512 # Verify that user does not get any special permission if he is not
580 # Verify that user does not get any special permission if he is not
513 # owner
581 # owner
514 assert group_perms(self.u1) == {'test1': 'group.write'}
582 assert group_perms(self.u1) == {'test1': 'group.write'}
515
583
516 # Make him owner of the repo group
584 # Make him owner of the repo group
517 self.g1.user = self.u1
585 self.g1.user = self.u1
518 assert group_perms(self.u1) == {'test1': 'group.admin'}
586 assert group_perms(self.u1) == {'test1': 'group.admin'}
519
587
520 def test_repo_group_owner_permissions_not_overwritten_by_others(self):
588 def test_repo_group_owner_permissions_not_overwritten_by_others(self):
521 # "u1" shall be owner without any special permission assigned
589 # "u1" shall be owner without any special permission assigned
522 self.g1 = fixture.create_repo_group('test1')
590 self.g1 = fixture.create_repo_group('test1')
523 RepoGroupModel().grant_user_permission(
591 RepoGroupModel().grant_user_permission(
524 repo_group=self.g1, user=self.u1, perm='group.write')
592 repo_group=self.g1, user=self.u1, perm='group.write')
525 Session().commit()
593 Session().commit()
526
594
527 # Verify that user does not get any special permission if he is not
595 # Verify that user does not get any special permission if he is not
528 # owner
596 # owner
529 assert group_perms(self.u1) == {'test1': 'group.write'}
597 assert group_perms(self.u1) == {'test1': 'group.write'}
530
598
531 # Make him owner of the repo group
599 # Make him owner of the repo group
532 self.g1.user = self.u1
600 self.g1.user = self.u1
533 assert group_perms(self.u1) == {u'test1': 'group.admin'}
601 assert group_perms(self.u1) == {u'test1': 'group.admin'}
534
602
535 def assert_user_perm_equal(
603 def assert_user_perm_equal(
536 self, user, change_factor=0, compare_keys=None):
604 self, user, change_factor=0, compare_keys=None):
537 perms = UserToPerm.query().filter(UserToPerm.user == user).all()
605 perms = UserToPerm.query().filter(UserToPerm.user == user).all()
538 assert len(perms) == \
606 assert len(perms) == \
539 len(Permission.DEFAULT_USER_PERMISSIONS) + change_factor
607 len(Permission.DEFAULT_USER_PERMISSIONS) + change_factor
540 if compare_keys:
608 if compare_keys:
541 assert set(
609 assert set(
542 x.permissions.permission_name for x in perms) == compare_keys
610 x.permissions.permission_name for x in perms) == compare_keys
543
611
544 def assert_def_user_group_perm_equal(
612 def assert_def_user_group_perm_equal(
545 self, user_group, change_factor=0, compare_keys=None):
613 self, user_group, change_factor=0, compare_keys=None):
546 perms = UserGroupToPerm.query().filter(
614 perms = UserGroupToPerm.query().filter(
547 UserGroupToPerm.users_group == user_group).all()
615 UserGroupToPerm.users_group == user_group).all()
548 assert len(perms) == \
616 assert len(perms) == \
549 len(Permission.DEFAULT_USER_PERMISSIONS) + change_factor
617 len(Permission.DEFAULT_USER_PERMISSIONS) + change_factor
550 if compare_keys:
618 if compare_keys:
551 assert set(
619 assert set(
552 x.permissions.permission_name for x in perms) == compare_keys
620 x.permissions.permission_name for x in perms) == compare_keys
553
621
554 def test_set_default_permissions(self):
622 def test_set_default_permissions(self):
555 PermissionModel().create_default_user_permissions(user=self.u1)
623 PermissionModel().create_default_user_permissions(user=self.u1)
556 self.assert_user_perm_equal(user=self.u1)
624 self.assert_user_perm_equal(user=self.u1)
557
625
558 def test_set_default_permissions_after_one_is_missing(self):
626 def test_set_default_permissions_after_one_is_missing(self):
559 PermissionModel().create_default_user_permissions(user=self.u1)
627 PermissionModel().create_default_user_permissions(user=self.u1)
560 self.assert_user_perm_equal(user=self.u1)
628 self.assert_user_perm_equal(user=self.u1)
561 # now we delete one, it should be re-created after another call
629 # now we delete one, it should be re-created after another call
562 perms = UserToPerm.query().filter(UserToPerm.user == self.u1).all()
630 perms = UserToPerm.query().filter(UserToPerm.user == self.u1).all()
563 Session().delete(perms[0])
631 Session().delete(perms[0])
564 Session().commit()
632 Session().commit()
565
633
566 self.assert_user_perm_equal(user=self.u1, change_factor=-1)
634 self.assert_user_perm_equal(user=self.u1, change_factor=-1)
567
635
568 # create missing one !
636 # create missing one !
569 PermissionModel().create_default_user_permissions(user=self.u1)
637 PermissionModel().create_default_user_permissions(user=self.u1)
570 self.assert_user_perm_equal(user=self.u1)
638 self.assert_user_perm_equal(user=self.u1)
571
639
572 @pytest.mark.parametrize("perm, modify_to", [
640 @pytest.mark.parametrize("perm, modify_to", [
573 ('repository.read', 'repository.none'),
641 ('repository.read', 'repository.none'),
574 ('group.read', 'group.none'),
642 ('group.read', 'group.none'),
575 ('usergroup.read', 'usergroup.none'),
643 ('usergroup.read', 'usergroup.none'),
576 ('hg.create.repository', 'hg.create.none'),
644 ('hg.create.repository', 'hg.create.none'),
577 ('hg.fork.repository', 'hg.fork.none'),
645 ('hg.fork.repository', 'hg.fork.none'),
578 ('hg.register.manual_activate', 'hg.register.auto_activate',)
646 ('hg.register.manual_activate', 'hg.register.auto_activate',)
579 ])
647 ])
580 def test_set_default_permissions_after_modification(self, perm, modify_to):
648 def test_set_default_permissions_after_modification(self, perm, modify_to):
581 PermissionModel().create_default_user_permissions(user=self.u1)
649 PermissionModel().create_default_user_permissions(user=self.u1)
582 self.assert_user_perm_equal(user=self.u1)
650 self.assert_user_perm_equal(user=self.u1)
583
651
584 old = Permission.get_by_key(perm)
652 old = Permission.get_by_key(perm)
585 new = Permission.get_by_key(modify_to)
653 new = Permission.get_by_key(modify_to)
586 assert old is not None
654 assert old is not None
587 assert new is not None
655 assert new is not None
588
656
589 # now modify permissions
657 # now modify permissions
590 p = UserToPerm.query().filter(
658 p = UserToPerm.query().filter(
591 UserToPerm.user == self.u1).filter(
659 UserToPerm.user == self.u1).filter(
592 UserToPerm.permission == old).one()
660 UserToPerm.permission == old).one()
593 p.permission = new
661 p.permission = new
594 Session().add(p)
662 Session().add(p)
595 Session().commit()
663 Session().commit()
596
664
597 PermissionModel().create_default_user_permissions(user=self.u1)
665 PermissionModel().create_default_user_permissions(user=self.u1)
598 self.assert_user_perm_equal(user=self.u1)
666 self.assert_user_perm_equal(user=self.u1)
599
667
600 def test_clear_user_perms(self):
668 def test_clear_user_perms(self):
601 PermissionModel().create_default_user_permissions(user=self.u1)
669 PermissionModel().create_default_user_permissions(user=self.u1)
602 self.assert_user_perm_equal(user=self.u1)
670 self.assert_user_perm_equal(user=self.u1)
603
671
604 # now clear permissions
672 # now clear permissions
605 cleared = PermissionModel()._clear_user_perms(self.u1.user_id)
673 cleared = PermissionModel()._clear_user_perms(self.u1.user_id)
606 self.assert_user_perm_equal(user=self.u1,
674 self.assert_user_perm_equal(user=self.u1,
607 change_factor=len(cleared)*-1)
675 change_factor=len(cleared)*-1)
608
676
609 def test_clear_user_group_perms(self):
677 def test_clear_user_group_perms(self):
610 self.ug1 = fixture.create_user_group('G1')
678 self.ug1 = fixture.create_user_group('G1')
611 PermissionModel().create_default_user_group_permissions(
679 PermissionModel().create_default_user_group_permissions(
612 user_group=self.ug1)
680 user_group=self.ug1)
613 self.assert_def_user_group_perm_equal(user_group=self.ug1)
681 self.assert_def_user_group_perm_equal(user_group=self.ug1)
614
682
615 # now clear permissions
683 # now clear permissions
616 cleared = PermissionModel()._clear_user_group_perms(
684 cleared = PermissionModel()._clear_user_group_perms(
617 self.ug1.users_group_id)
685 self.ug1.users_group_id)
618 self.assert_def_user_group_perm_equal(user_group=self.ug1,
686 self.assert_def_user_group_perm_equal(user_group=self.ug1,
619 change_factor=len(cleared)*-1)
687 change_factor=len(cleared)*-1)
620
688
621 @pytest.mark.parametrize("form_result", [
689 @pytest.mark.parametrize("form_result", [
622 {},
690 {},
623 {'default_repo_create': 'hg.create.repository'},
691 {'default_repo_create': 'hg.create.repository'},
624 {'default_repo_create': 'hg.create.repository',
692 {'default_repo_create': 'hg.create.repository',
625 'default_repo_perm': 'repository.read'},
693 'default_repo_perm': 'repository.read'},
626 {'default_repo_create': 'hg.create.none',
694 {'default_repo_create': 'hg.create.none',
627 'default_repo_perm': 'repository.write',
695 'default_repo_perm': 'repository.write',
628 'default_fork_create': 'hg.fork.none'},
696 'default_fork_create': 'hg.fork.none'},
629 ])
697 ])
630 def test_set_new_user_permissions(self, form_result):
698 def test_set_new_user_permissions(self, form_result):
631 _form_result = {}
699 _form_result = {}
632 _form_result.update(form_result)
700 _form_result.update(form_result)
633 PermissionModel().set_new_user_perms(self.u1, _form_result)
701 PermissionModel().set_new_user_perms(self.u1, _form_result)
634 Session().commit()
702 Session().commit()
635 change_factor = -1 * (len(Permission.DEFAULT_USER_PERMISSIONS)
703 change_factor = -1 * (len(Permission.DEFAULT_USER_PERMISSIONS)
636 - len(form_result.keys()))
704 - len(form_result.keys()))
637 self.assert_user_perm_equal(
705 self.assert_user_perm_equal(
638 self.u1, change_factor=change_factor)
706 self.u1, change_factor=change_factor)
639
707
640 @pytest.mark.parametrize("form_result", [
708 @pytest.mark.parametrize("form_result", [
641 {},
709 {},
642 {'default_repo_create': 'hg.create.repository'},
710 {'default_repo_create': 'hg.create.repository'},
643 {'default_repo_create': 'hg.create.repository',
711 {'default_repo_create': 'hg.create.repository',
644 'default_repo_perm': 'repository.read'},
712 'default_repo_perm': 'repository.read'},
645 {'default_repo_create': 'hg.create.none',
713 {'default_repo_create': 'hg.create.none',
646 'default_repo_perm': 'repository.write',
714 'default_repo_perm': 'repository.write',
647 'default_fork_create': 'hg.fork.none'},
715 'default_fork_create': 'hg.fork.none'},
648 ])
716 ])
649 def test_set_new_user_group_permissions(self, form_result):
717 def test_set_new_user_group_permissions(self, form_result):
650 _form_result = {}
718 _form_result = {}
651 _form_result.update(form_result)
719 _form_result.update(form_result)
652 self.ug1 = fixture.create_user_group('G1')
720 self.ug1 = fixture.create_user_group('G1')
653 PermissionModel().set_new_user_group_perms(self.ug1, _form_result)
721 PermissionModel().set_new_user_group_perms(self.ug1, _form_result)
654 Session().commit()
722 Session().commit()
655 change_factor = -1 * (len(Permission.DEFAULT_USER_PERMISSIONS)
723 change_factor = -1 * (len(Permission.DEFAULT_USER_PERMISSIONS)
656 - len(form_result.keys()))
724 - len(form_result.keys()))
657 self.assert_def_user_group_perm_equal(
725 self.assert_def_user_group_perm_equal(
658 self.ug1, change_factor=change_factor)
726 self.ug1, change_factor=change_factor)
659
727
660 @pytest.mark.parametrize("group_active, expected_perm", [
728 @pytest.mark.parametrize("group_active, expected_perm", [
661 (True, 'repository.admin'),
729 (True, 'repository.admin'),
662 (False, 'repository.read'),
730 (False, 'repository.read'),
663 ])
731 ])
664 def test_get_default_repo_perms_from_user_group_with_active_group(
732 def test_get_default_repo_perms_from_user_group_with_active_group(
665 self, backend, user_util, group_active, expected_perm):
733 self, backend, user_util, group_active, expected_perm):
666 repo = backend.create_repo()
734 repo = backend.create_repo()
667 user = user_util.create_user()
735 user = user_util.create_user()
668 user_group = user_util.create_user_group(
736 user_group = user_util.create_user_group(
669 members=[user], users_group_active=group_active)
737 members=[user], users_group_active=group_active)
670
738
671 user_util.grant_user_group_permission_to_repo(
739 user_util.grant_user_group_permission_to_repo(
672 repo, user_group, 'repository.admin')
740 repo, user_group, 'repository.admin')
673 permissions = repo_perms(user)
741 permissions = repo_perms(user)
674 repo_permission = permissions.get(repo.repo_name)
742 repo_permission = permissions.get(repo.repo_name)
675 assert repo_permission == expected_perm
743 assert repo_permission == expected_perm
676
744
677 @pytest.mark.parametrize("group_active, expected_perm", [
745 @pytest.mark.parametrize("group_active, expected_perm", [
678 (True, 'group.admin'),
746 (True, 'group.admin'),
679 (False, 'group.read')
747 (False, 'group.read')
680 ])
748 ])
681 def test_get_default_group_perms_from_user_group_with_active_group(
749 def test_get_default_group_perms_from_user_group_with_active_group(
682 self, user_util, group_active, expected_perm):
750 self, user_util, group_active, expected_perm):
683 user = user_util.create_user()
751 user = user_util.create_user()
684 repo_group = user_util.create_repo_group()
752 repo_group = user_util.create_repo_group()
685 user_group = user_util.create_user_group(
753 user_group = user_util.create_user_group(
686 members=[user], users_group_active=group_active)
754 members=[user], users_group_active=group_active)
687
755
688 user_util.grant_user_group_permission_to_repo_group(
756 user_util.grant_user_group_permission_to_repo_group(
689 repo_group, user_group, 'group.admin')
757 repo_group, user_group, 'group.admin')
690 permissions = group_perms(user)
758 permissions = group_perms(user)
691 group_permission = permissions.get(repo_group.name)
759 group_permission = permissions.get(repo_group.name)
692 assert group_permission == expected_perm
760 assert group_permission == expected_perm
693
761
694 @pytest.mark.parametrize("group_active, expected_perm", [
762 @pytest.mark.parametrize("group_active, expected_perm", [
695 (True, 'usergroup.admin'),
763 (True, 'usergroup.admin'),
696 (False, 'usergroup.read')
764 (False, 'usergroup.read')
697 ])
765 ])
698 def test_get_default_user_group_perms_from_user_group_with_active_group(
766 def test_get_default_user_group_perms_from_user_group_with_active_group(
699 self, user_util, group_active, expected_perm):
767 self, user_util, group_active, expected_perm):
700 user = user_util.create_user()
768 user = user_util.create_user()
701 user_group = user_util.create_user_group(
769 user_group = user_util.create_user_group(
702 members=[user], users_group_active=group_active)
770 members=[user], users_group_active=group_active)
703 target_user_group = user_util.create_user_group()
771 target_user_group = user_util.create_user_group()
704
772
705 user_util.grant_user_group_permission_to_user_group(
773 user_util.grant_user_group_permission_to_user_group(
706 target_user_group, user_group, 'usergroup.admin')
774 target_user_group, user_group, 'usergroup.admin')
707 permissions = user_group_perms(user)
775 permissions = user_group_perms(user)
708 group_permission = permissions.get(target_user_group.users_group_name)
776 group_permission = permissions.get(target_user_group.users_group_name)
709 assert group_permission == expected_perm
777 assert group_permission == expected_perm
710
778
711
779
712 def repo_perms(user):
780 def repo_perms(user):
713 auth_user = AuthUser(user_id=user.user_id)
781 auth_user = AuthUser(user_id=user.user_id)
714 return auth_user.permissions['repositories']
782 return auth_user.permissions['repositories']
715
783
716
784
717 def branch_perms(user):
785 def branch_perms(user):
718 auth_user = AuthUser(user_id=user.user_id)
786 auth_user = AuthUser(user_id=user.user_id)
719 return auth_user.permissions['repository_branches']
787 return auth_user.permissions['repository_branches']
720
788
721
789
722 def group_perms(user):
790 def group_perms(user):
723 auth_user = AuthUser(user_id=user.user_id)
791 auth_user = AuthUser(user_id=user.user_id)
724 return auth_user.permissions['repositories_groups']
792 return auth_user.permissions['repositories_groups']
725
793
726
794
727 def user_group_perms(user):
795 def user_group_perms(user):
728 auth_user = AuthUser(user_id=user.user_id)
796 auth_user = AuthUser(user_id=user.user_id)
729 return auth_user.permissions['user_groups']
797 return auth_user.permissions['user_groups']
730
798
731
799
732 def global_perms(user):
800 def global_perms(user):
733 auth_user = AuthUser(user_id=user.user_id)
801 auth_user = AuthUser(user_id=user.user_id)
734 return auth_user.permissions['global']
802 return auth_user.permissions['global']
735
803
736
804
737 def default_perms(added=None, removed=None):
805 def default_perms(added=None, removed=None):
738 expected_perms = set(Permission.DEFAULT_USER_PERMISSIONS)
806 expected_perms = set(Permission.DEFAULT_USER_PERMISSIONS)
739 if removed:
807 if removed:
740 expected_perms.difference_update(removed)
808 expected_perms.difference_update(removed)
741 if added:
809 if added:
742 expected_perms.update(added)
810 expected_perms.update(added)
743 return expected_perms
811 return expected_perms
General Comments 0
You need to be logged in to leave comments. Login now