Show More
@@ -0,0 +1,40 b'' | |||||
|
1 | |RCE| 5.2.1 |RNS| | |||
|
2 | ----------------- | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2024-09-16 | |||
|
8 | ||||
|
9 | ||||
|
10 | New Features | |||
|
11 | ^^^^^^^^^^^^ | |||
|
12 | ||||
|
13 | ||||
|
14 | ||||
|
15 | General | |||
|
16 | ^^^^^^^ | |||
|
17 | ||||
|
18 | ||||
|
19 | ||||
|
20 | Security | |||
|
21 | ^^^^^^^^ | |||
|
22 | ||||
|
23 | ||||
|
24 | ||||
|
25 | Performance | |||
|
26 | ^^^^^^^^^^^ | |||
|
27 | ||||
|
28 | ||||
|
29 | ||||
|
30 | ||||
|
31 | Fixes | |||
|
32 | ^^^^^ | |||
|
33 | ||||
|
34 | - Fixed problems with incorrect user agent errors | |||
|
35 | ||||
|
36 | ||||
|
37 | Upgrade notes | |||
|
38 | ^^^^^^^^^^^^^ | |||
|
39 | ||||
|
40 | - RhodeCode 5.2.1 is unscheduled bugfix release to address some build issues with 5.2 images |
@@ -0,0 +1,45 b'' | |||||
|
1 | |RCE| 5.3.0 |RNS| | |||
|
2 | ----------------- | |||
|
3 | ||||
|
4 | Release Date | |||
|
5 | ^^^^^^^^^^^^ | |||
|
6 | ||||
|
7 | - 2024-09-17 | |||
|
8 | ||||
|
9 | ||||
|
10 | New Features | |||
|
11 | ^^^^^^^^^^^^ | |||
|
12 | ||||
|
13 | - System-info: expose rhodecode config for better visibility of set settings for RhodeCode system. | |||
|
14 | ||||
|
15 | ||||
|
16 | General | |||
|
17 | ^^^^^^^ | |||
|
18 | ||||
|
19 | ||||
|
20 | ||||
|
21 | Security | |||
|
22 | ^^^^^^^^ | |||
|
23 | ||||
|
24 | - Permissions: fixed security problem with apply-to-children from a repo group functionality breaking | |||
|
25 | permissions for private repositories exposing them despite repo being private. | |||
|
26 | - Git-lfs: fixed security problem with allowing off-chain attacks to replace OID data without validating hash for already present oids. | |||
|
27 | This allowed to replace an LFS OID content with malicious request tailored to open RhodeCode server. | |||
|
28 | ||||
|
29 | ||||
|
30 | Performance | |||
|
31 | ^^^^^^^^^^^ | |||
|
32 | ||||
|
33 | ||||
|
34 | ||||
|
35 | ||||
|
36 | Fixes | |||
|
37 | ^^^^^ | |||
|
38 | ||||
|
39 | - Fixed problems with incorrect user agent errors | |||
|
40 | ||||
|
41 | ||||
|
42 | Upgrade notes | |||
|
43 | ^^^^^^^^^^^^^ | |||
|
44 | ||||
|
45 | - RhodeCode 5.3.0 is unscheduled security release to address some build issues with 5.X images |
@@ -1,5 +1,5 b'' | |||||
1 | [bumpversion] |
|
1 | [bumpversion] | |
2 |
current_version = 5. |
|
2 | current_version = 5.3.0 | |
3 | message = release: Bump version {current_version} to {new_version} |
|
3 | message = release: Bump version {current_version} to {new_version} | |
4 |
|
4 | |||
5 | [bumpversion:file:rhodecode/VERSION] |
|
5 | [bumpversion:file:rhodecode/VERSION] |
@@ -71,6 +71,9 b' use = egg:rhodecode-enterprise-ce' | |||||
71 | ; enable proxy prefix middleware, defined above |
|
71 | ; enable proxy prefix middleware, defined above | |
72 | #filter-with = proxy-prefix |
|
72 | #filter-with = proxy-prefix | |
73 |
|
73 | |||
|
74 | ; control if environmental variables to be expanded into the .ini settings | |||
|
75 | #rhodecode.env_expand = true | |||
|
76 | ||||
74 | ; ############# |
|
77 | ; ############# | |
75 | ; DEBUG OPTIONS |
|
78 | ; DEBUG OPTIONS | |
76 | ; ############# |
|
79 | ; ############# |
@@ -71,6 +71,9 b' use = egg:rhodecode-enterprise-ce' | |||||
71 | ; enable proxy prefix middleware, defined above |
|
71 | ; enable proxy prefix middleware, defined above | |
72 | #filter-with = proxy-prefix |
|
72 | #filter-with = proxy-prefix | |
73 |
|
73 | |||
|
74 | ; control if environmental variables to be expanded into the .ini settings | |||
|
75 | #rhodecode.env_expand = true | |||
|
76 | ||||
74 | ; encryption key used to encrypt social plugin tokens, |
|
77 | ; encryption key used to encrypt social plugin tokens, | |
75 | ; remote_urls with credentials etc, if not set it defaults to |
|
78 | ; remote_urls with credentials etc, if not set it defaults to | |
76 | ; `beaker.session.secret` |
|
79 | ; `beaker.session.secret` |
@@ -9,6 +9,8 b' Release Notes' | |||||
9 | .. toctree:: |
|
9 | .. toctree:: | |
10 | :maxdepth: 1 |
|
10 | :maxdepth: 1 | |
11 |
|
11 | |||
|
12 | release-notes-5.3.0.rst | |||
|
13 | release-notes-5.2.1.rst | |||
12 | release-notes-5.2.0.rst |
|
14 | release-notes-5.2.0.rst | |
13 | release-notes-5.1.2.rst |
|
15 | release-notes-5.1.2.rst | |
14 | release-notes-5.1.1.rst |
|
16 | release-notes-5.1.1.rst |
@@ -199,8 +199,12 b' class AdminSystemInfoSettingsView(BaseAp' | |||||
199 |
|
199 | |||
200 | ] |
|
200 | ] | |
201 |
|
201 | |||
|
202 | c.rhodecode_data_items = [ | |||
|
203 | (k, v) for k, v in sorted((val('rhodecode_server_config') or {}).items(), key=lambda x: x[0].lower()) | |||
|
204 | ] | |||
|
205 | ||||
202 | c.vcsserver_data_items = [ |
|
206 | c.vcsserver_data_items = [ | |
203 | (k, v) for k, v in (val('vcs_server_config') or {}).items() |
|
207 | (k, v) for k, v in sorted((val('vcs_server_config') or {}).items(), key=lambda x: x[0].lower()) | |
204 | ] |
|
208 | ] | |
205 |
|
209 | |||
206 | if snapshot: |
|
210 | if snapshot: |
@@ -100,22 +100,16 b' class RepoSettingsPermissionsView(RepoAp' | |||||
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") |
@@ -109,6 +109,9 b' class SettingsMaker:' | |||||
109 | return envvar_value |
|
109 | return envvar_value | |
110 |
|
110 | |||
111 | def env_expand(self): |
|
111 | def env_expand(self): | |
|
112 | if self.settings.get('rhodecode.env_expand') == 'false': | |||
|
113 | return | |||
|
114 | ||||
112 | replaced = {} |
|
115 | replaced = {} | |
113 | for k, v in self.settings.items(): |
|
116 | for k, v in self.settings.items(): | |
114 | if k not in set_keys: |
|
117 | if k not in set_keys: |
@@ -167,7 +167,8 b' def _is_request_chunked(environ):' | |||||
167 | def _maybe_stream_request(environ): |
|
167 | def _maybe_stream_request(environ): | |
168 | path = get_path_info(environ) |
|
168 | path = get_path_info(environ) | |
169 | stream = _is_request_chunked(environ) |
|
169 | stream = _is_request_chunked(environ) | |
170 | log.debug('handling request `%s` with stream support: %s', path, stream) |
|
170 | req_method = environ['REQUEST_METHOD'] | |
|
171 | log.debug('handling scm request: %s `%s` with stream support: %s', req_method, path, stream) | |||
171 |
|
172 | |||
172 | if stream: |
|
173 | if stream: | |
173 | # set stream by 256k |
|
174 | # set stream by 256k |
@@ -665,6 +665,32 b' def vcs_server_config():' | |||||
665 |
|
665 | |||
666 | return SysInfoRes(value=value, state=state, human_value=human_value) |
|
666 | return SysInfoRes(value=value, state=state, human_value=human_value) | |
667 |
|
667 | |||
|
668 | @register_sysinfo | |||
|
669 | def rhodecode_server_config(): | |||
|
670 | import rhodecode | |||
|
671 | ||||
|
672 | state = STATE_OK_DEFAULT | |||
|
673 | config = rhodecode.CONFIG.copy() | |||
|
674 | ||||
|
675 | secrets_lits = [ | |||
|
676 | f'rhodecode_{LicenseModel.LICENSE_DB_KEY}', | |||
|
677 | 'sqlalchemy.db1.url', | |||
|
678 | 'channelstream.secret', | |||
|
679 | 'beaker.session.secret', | |||
|
680 | 'rhodecode.encrypted_values.secret', | |||
|
681 | 'appenlight.api_key', | |||
|
682 | 'smtp_password', | |||
|
683 | 'file_store.objectstore.secret', | |||
|
684 | 'archive_cache.objectstore.secret', | |||
|
685 | 'app.service_api.token', | |||
|
686 | ] | |||
|
687 | for k in secrets_lits: | |||
|
688 | if k in config: | |||
|
689 | config[k] = '**OBFUSCATED**' | |||
|
690 | ||||
|
691 | value = human_value = config | |||
|
692 | return SysInfoRes(value=value, state=state, human_value=human_value) | |||
|
693 | ||||
668 |
|
694 | |||
669 | @register_sysinfo |
|
695 | @register_sysinfo | |
670 | def rhodecode_app_info(): |
|
696 | def rhodecode_app_info(): | |
@@ -851,6 +877,7 b' def get_system_info(environ):' | |||||
851 | 'vcs_server': SysInfo(vcs_server)(), |
|
877 | 'vcs_server': SysInfo(vcs_server)(), | |
852 |
|
878 | |||
853 | 'vcs_server_config': SysInfo(vcs_server_config)(), |
|
879 | 'vcs_server_config': SysInfo(vcs_server_config)(), | |
|
880 | 'rhodecode_server_config': SysInfo(rhodecode_server_config)(), | |||
854 |
|
881 | |||
855 | 'git': SysInfo(git_info)(), |
|
882 | 'git': SysInfo(git_info)(), | |
856 | 'hg': SysInfo(hg_info)(), |
|
883 | 'hg': SysInfo(hg_info)(), |
@@ -452,15 +452,24 b' class RepoModel(BaseModel):' | |||||
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) |
@@ -1,4 +1,4 b'' | |||||
1 |
# Copyright (C) 2011-202 |
|
1 | # Copyright (C) 2011-2024 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 | |
@@ -30,7 +30,6 b' import time' | |||||
30 | import traceback |
|
30 | import traceback | |
31 | import string |
|
31 | import string | |
32 |
|
32 | |||
33 | from zope.cachedescriptors.property import Lazy as LazyProperty |
|
|||
34 |
|
33 | |||
35 | from rhodecode import events |
|
34 | from rhodecode import events | |
36 | from rhodecode.model import BaseModel |
|
35 | from rhodecode.model import BaseModel | |
@@ -38,7 +37,7 b' from rhodecode.model.db import (_hash_ke' | |||||
38 | Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm, |
|
37 | Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm, | |
39 | UserGroup, Repository) |
|
38 | UserGroup, Repository) | |
40 | from rhodecode.model.permission import PermissionModel |
|
39 | from rhodecode.model.permission import PermissionModel | |
41 |
from rhodecode.model.settings import |
|
40 | from rhodecode.model.settings import SettingsModel | |
42 | from rhodecode.lib.caching_query import FromCache |
|
41 | from rhodecode.lib.caching_query import FromCache | |
43 | from rhodecode.lib.utils2 import action_logger_generic |
|
42 | from rhodecode.lib.utils2 import action_logger_generic | |
44 |
|
43 | |||
@@ -350,46 +349,45 b' class RepoGroupModel(BaseModel):' | |||||
350 | 'default_user_changed': None |
|
349 | 'default_user_changed': None | |
351 | } |
|
350 | } | |
352 |
|
351 | |||
353 | def _set_perm_user(obj, user, perm): |
|
352 | def _set_perm_user(_obj: RepoGroup | Repository, _user_obj: User, _perm): | |
354 | if isinstance(obj, RepoGroup): |
|
353 | ||
355 | self.grant_user_permission( |
|
354 | if isinstance(_obj, RepoGroup): | |
356 |
|
|
355 | self.grant_user_permission(repo_group=_obj, user=_user_obj, perm=_perm) | |
357 | elif isinstance(obj, Repository): |
|
356 | elif isinstance(_obj, Repository): | |
358 | # private repos will not allow to change the default |
|
357 | # private repos will not allow to change the default | |
359 | # permissions using recursive mode |
|
358 | # permissions using recursive mode | |
360 | if obj.private and user == User.DEFAULT_USER: |
|
359 | if _obj.private and _user_obj.username == User.DEFAULT_USER: | |
|
360 | log.debug('Skipping private repo %s for user %s', _obj, _user_obj) | |||
361 | return |
|
361 | return | |
362 |
|
362 | |||
363 |
# we set group permission |
|
363 | # we set group permission, we have to switch to repo permission definition | |
364 | # permission |
|
364 | new_perm = _perm.replace('group.', 'repository.') | |
365 | perm = perm.replace('group.', 'repository.') |
|
365 | RepoModel().grant_user_permission(repo=_obj, user=_user_obj, perm=new_perm) | |
366 | RepoModel().grant_user_permission( |
|
366 | ||
367 | repo=obj, user=user, perm=perm) |
|
367 | def _set_perm_group(_obj: RepoGroup | Repository, users_group: UserGroup, _perm): | |
|
368 | if isinstance(_obj, RepoGroup): | |||
|
369 | self.grant_user_group_permission(repo_group=_obj, group_name=users_group, perm=_perm) | |||
|
370 | elif isinstance(_obj, Repository): | |||
|
371 | # we set group permission, we have to switch to repo permission definition | |||
|
372 | new_perm = _perm.replace('group.', 'repository.') | |||
|
373 | RepoModel().grant_user_group_permission(repo=_obj, group_name=users_group, perm=new_perm) | |||
368 |
|
374 | |||
369 | def _set_perm_group(obj, users_group, perm): |
|
375 | def _revoke_perm_user(_obj: RepoGroup | Repository, _user_obj: User): | |
370 | if isinstance(obj, RepoGroup): |
|
376 | if isinstance(_obj, RepoGroup): | |
371 |
self. |
|
377 | self.revoke_user_permission(repo_group=_obj, user=_user_obj) | |
372 | repo_group=obj, group_name=users_group, perm=perm) |
|
378 | elif isinstance(_obj, Repository): | |
373 | elif isinstance(obj, Repository): |
|
379 | # private repos will not allow to change the default | |
374 | # we set group permission but we have to switch to repo |
|
380 | # permissions using recursive mode, also there's no revocation fo default user, just update | |
375 | # permission |
|
381 | if _user_obj.username == User.DEFAULT_USER: | |
376 | perm = perm.replace('group.', 'repository.') |
|
382 | log.debug('Skipping private repo %s for user %s', _obj, _user_obj) | |
377 | RepoModel().grant_user_group_permission( |
|
383 | return | |
378 | repo=obj, group_name=users_group, perm=perm) |
|
384 | RepoModel().revoke_user_permission(repo=_obj, user=_user_obj) | |
379 |
|
385 | |||
380 |
def _revoke_perm_ |
|
386 | def _revoke_perm_group(_obj: RepoGroup | Repository, user_group: UserGroup): | |
381 | if isinstance(obj, RepoGroup): |
|
387 | if isinstance(_obj, RepoGroup): | |
382 |
self.revoke_user_permission(repo_group=obj, |
|
388 | self.revoke_user_group_permission(repo_group=_obj, group_name=user_group) | |
383 | elif isinstance(obj, Repository): |
|
389 | elif isinstance(_obj, Repository): | |
384 |
RepoModel().revoke_user_permission(repo=obj, |
|
390 | RepoModel().revoke_user_group_permission(repo=_obj, group_name=user_group) | |
385 |
|
||||
386 | def _revoke_perm_group(obj, user_group): |
|
|||
387 | if isinstance(obj, RepoGroup): |
|
|||
388 | self.revoke_user_group_permission( |
|
|||
389 | repo_group=obj, group_name=user_group) |
|
|||
390 | elif isinstance(obj, Repository): |
|
|||
391 | RepoModel().revoke_user_group_permission( |
|
|||
392 | repo=obj, group_name=user_group) |
|
|||
393 |
|
391 | |||
394 | # start updates |
|
392 | # start updates | |
395 | log.debug('Now updating permissions for %s in recursive mode:%s', |
|
393 | log.debug('Now updating permissions for %s in recursive mode:%s', | |
@@ -423,7 +421,8 b' class RepoGroupModel(BaseModel):' | |||||
423 | for member_id, perm, member_type in perm_updates: |
|
421 | for member_id, perm, member_type in perm_updates: | |
424 | member_id = int(member_id) |
|
422 | member_id = int(member_id) | |
425 | if member_type == 'user': |
|
423 | if member_type == 'user': | |
426 |
member_ |
|
424 | member_obj = User.get(member_id) | |
|
425 | member_name = member_obj.username | |||
427 | if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER: |
|
426 | if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER: | |
428 | # NOTE(dan): detect if we changed permissions for default user |
|
427 | # NOTE(dan): detect if we changed permissions for default user | |
429 | perm_obj = self.sa.query(UserRepoGroupToPerm) \ |
|
428 | perm_obj = self.sa.query(UserRepoGroupToPerm) \ | |
@@ -434,15 +433,16 b' class RepoGroupModel(BaseModel):' | |||||
434 | changes['default_user_changed'] = True |
|
433 | changes['default_user_changed'] = True | |
435 |
|
434 | |||
436 | # this updates also current one if found |
|
435 | # this updates also current one if found | |
437 |
_set_perm_user(obj, |
|
436 | _set_perm_user(obj, member_obj, perm) | |
438 | elif member_type == 'user_group': |
|
437 | elif member_type == 'user_group': | |
439 |
member_ |
|
438 | member_obj = UserGroup.get(member_id) | |
440 | if not check_perms or has_group_perm(member_name, |
|
439 | member_name = member_obj.users_group_name | |
441 | user=cur_user): |
|
440 | if not check_perms or has_group_perm(member_name, user=cur_user): | |
442 |
_set_perm_group(obj, |
|
441 | _set_perm_group(obj, member_obj, perm) | |
443 | else: |
|
442 | else: | |
444 |
raise ValueError( |
|
443 | raise ValueError( | |
445 | "got {} instead".format(member_type)) |
|
444 | f"member_type must be 'user' or 'user_group' got {member_type} instead" | |
|
445 | ) | |||
446 |
|
446 | |||
447 | changes['updated'].append( |
|
447 | changes['updated'].append( | |
448 | {'change_obj': change_obj, 'type': member_type, |
|
448 | {'change_obj': change_obj, 'type': member_type, | |
@@ -452,17 +452,19 b' class RepoGroupModel(BaseModel):' | |||||
452 | for member_id, perm, member_type in perm_additions: |
|
452 | for member_id, perm, member_type in perm_additions: | |
453 | member_id = int(member_id) |
|
453 | member_id = int(member_id) | |
454 | if member_type == 'user': |
|
454 | if member_type == 'user': | |
455 |
member_ |
|
455 | member_obj = User.get(member_id) | |
456 | _set_perm_user(obj, user=member_id, perm=perm) |
|
456 | member_name = member_obj.username | |
|
457 | _set_perm_user(obj, member_obj, perm) | |||
457 | elif member_type == 'user_group': |
|
458 | elif member_type == 'user_group': | |
458 | # check if we have permissions to alter this usergroup |
|
459 | # check if we have permissions to alter this usergroup | |
459 |
member_ |
|
460 | member_obj = UserGroup.get(member_id) | |
460 | if not check_perms or has_group_perm(member_name, |
|
461 | member_name = member_obj.users_group_name | |
461 | user=cur_user): |
|
462 | if not check_perms or has_group_perm(member_name, user=cur_user): | |
462 |
_set_perm_group(obj, |
|
463 | _set_perm_group(obj, member_obj, perm) | |
463 | else: |
|
464 | else: | |
464 |
raise ValueError( |
|
465 | raise ValueError( | |
465 | "got {} instead".format(member_type)) |
|
466 | f"member_type must be 'user' or 'user_group' got {member_type} instead" | |
|
467 | ) | |||
466 |
|
468 | |||
467 | changes['added'].append( |
|
469 | changes['added'].append( | |
468 | {'change_obj': change_obj, 'type': member_type, |
|
470 | {'change_obj': change_obj, 'type': member_type, | |
@@ -472,18 +474,19 b' class RepoGroupModel(BaseModel):' | |||||
472 | for member_id, perm, member_type in perm_deletions: |
|
474 | for member_id, perm, member_type in perm_deletions: | |
473 | member_id = int(member_id) |
|
475 | member_id = int(member_id) | |
474 | if member_type == 'user': |
|
476 | if member_type == 'user': | |
475 |
member_ |
|
477 | member_obj = User.get(member_id) | |
476 | _revoke_perm_user(obj, user=member_id) |
|
478 | member_name = member_obj.username | |
|
479 | _revoke_perm_user(obj, member_obj) | |||
477 | elif member_type == 'user_group': |
|
480 | elif member_type == 'user_group': | |
478 | # check if we have permissions to alter this usergroup |
|
481 | # check if we have permissions to alter this usergroup | |
479 |
member_ |
|
482 | member_obj = UserGroup.get(member_id) | |
480 | if not check_perms or has_group_perm(member_name, |
|
483 | member_name = member_obj.users_group_name | |
481 | user=cur_user): |
|
484 | if not check_perms or has_group_perm(member_name, user=cur_user): | |
482 |
_revoke_perm_group(obj, |
|
485 | _revoke_perm_group(obj, member_obj) | |
483 | else: |
|
486 | else: | |
484 |
raise ValueError( |
|
487 | raise ValueError( | |
485 | "got {} instead".format(member_type)) |
|
488 | f"member_type must be 'user' or 'user_group' got {member_type} instead" | |
486 |
|
489 | ) | ||
487 | changes['deleted'].append( |
|
490 | changes['deleted'].append( | |
488 | {'change_obj': change_obj, 'type': member_type, |
|
491 | {'change_obj': change_obj, 'type': member_type, | |
489 | 'id': member_id, 'name': member_name, 'new_perm': perm}) |
|
492 | 'id': member_id, 'name': member_name, 'new_perm': perm}) |
@@ -42,7 +42,7 b' class UpdateModel(BaseModel):' | |||||
42 | ver = rhodecode.__version__ |
|
42 | ver = rhodecode.__version__ | |
43 | log.debug('Checking for upgrade on `%s` server', update_url) |
|
43 | log.debug('Checking for upgrade on `%s` server', update_url) | |
44 | opener = urllib.request.build_opener() |
|
44 | opener = urllib.request.build_opener() | |
45 |
opener.addheaders = [('User-agent', 'RhodeCode-SCM/ |
|
45 | opener.addheaders = [('User-agent', f'RhodeCode-SCM/{ver.strip()}')] | |
46 | response = opener.open(update_url) |
|
46 | response = opener.open(update_url) | |
47 | response_data = response.read() |
|
47 | response_data = response.read() | |
48 | data = json.loads(response_data) |
|
48 | data = json.loads(response_data) |
@@ -29,7 +29,21 b'' | |||||
29 |
|
29 | |||
30 | <div class="panel panel-default"> |
|
30 | <div class="panel panel-default"> | |
31 | <div class="panel-heading"> |
|
31 | <div class="panel-heading"> | |
32 |
<h3 class="panel-title">${_(' |
|
32 | <h3 class="panel-title">${_('RhodeCode Server Config')}</h3> | |
|
33 | </div> | |||
|
34 | <div class="panel-body"> | |||
|
35 | <dl class="dl-horizontal settings dt-400"> | |||
|
36 | % for dt, dd in c.rhodecode_data_items: | |||
|
37 | <dt>${dt}${':' if dt else '---'}</dt> | |||
|
38 | <dd>${dd}${'' if dt else '---'}</dd> | |||
|
39 | % endfor | |||
|
40 | </dl> | |||
|
41 | </div> | |||
|
42 | </div> | |||
|
43 | ||||
|
44 | <div class="panel panel-default"> | |||
|
45 | <div class="panel-heading"> | |||
|
46 | <h3 class="panel-title">${_('VCS Server Config')}</h3> | |||
33 | </div> |
|
47 | </div> | |
34 | <div class="panel-body"> |
|
48 | <div class="panel-body"> | |
35 | <dl class="dl-horizontal settings dt-400"> |
|
49 | <dl class="dl-horizontal settings dt-400"> |
@@ -166,6 +166,74 b' class TestPermissions(object):' | |||||
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 |
@@ -71,6 +71,9 b' use = egg:rhodecode-enterprise-ce' | |||||
71 | ; enable proxy prefix middleware, defined above |
|
71 | ; enable proxy prefix middleware, defined above | |
72 | #filter-with = proxy-prefix |
|
72 | #filter-with = proxy-prefix | |
73 |
|
73 | |||
|
74 | ; control if environmental variables to be expanded into the .ini settings | |||
|
75 | rhodecode.env_expand = false | |||
|
76 | ||||
74 | ; encryption key used to encrypt social plugin tokens, |
|
77 | ; encryption key used to encrypt social plugin tokens, | |
75 | ; remote_urls with credentials etc, if not set it defaults to |
|
78 | ; remote_urls with credentials etc, if not set it defaults to | |
76 | ; `beaker.session.secret` |
|
79 | ; `beaker.session.secret` | |
@@ -225,6 +228,13 b' license_token = abra-cada-bra1-rce3' | |||||
225 | ; This flag hides sensitive information on the license page such as token, and license data |
|
228 | ; This flag hides sensitive information on the license page such as token, and license data | |
226 | license.hide_license_info = false |
|
229 | license.hide_license_info = false | |
227 |
|
230 | |||
|
231 | ; Import EE license from this license path | |||
|
232 | #license.import_path = %(here)s/rhodecode_enterprise.license | |||
|
233 | ||||
|
234 | ; import license 'if-missing' or 'force' (always override) | |||
|
235 | ; if-missing means apply license if it doesn't exist. 'force' option always overrides it | |||
|
236 | license.import_path_mode = if-missing | |||
|
237 | ||||
228 | ; supervisor connection uri, for managing supervisor and logs. |
|
238 | ; supervisor connection uri, for managing supervisor and logs. | |
229 | supervisor.uri = |
|
239 | supervisor.uri = | |
230 |
|
240 | |||
@@ -658,6 +668,12 b' vcs.connection_timeout = 3600' | |||||
658 | ; It uses cache_region `cache_repo` |
|
668 | ; It uses cache_region `cache_repo` | |
659 | vcs.methods.cache = false |
|
669 | vcs.methods.cache = false | |
660 |
|
670 | |||
|
671 | ; Filesystem location where Git lfs objects should be stored | |||
|
672 | vcs.git.lfs.storage_location = /var/opt/rhodecode_repo_store/.cache/git_lfs_store | |||
|
673 | ||||
|
674 | ; Filesystem location where Mercurial largefile objects should be stored | |||
|
675 | vcs.hg.largefiles.storage_location = /var/opt/rhodecode_repo_store/.cache/hg_largefiles_store | |||
|
676 | ||||
661 | ; #################################################### |
|
677 | ; #################################################### | |
662 | ; Subversion proxy support (mod_dav_svn) |
|
678 | ; Subversion proxy support (mod_dav_svn) | |
663 | ; Maps RhodeCode repo groups into SVN paths for Apache |
|
679 | ; Maps RhodeCode repo groups into SVN paths for Apache |
General Comments 0
You need to be logged in to leave comments.
Login now