Pull request !2298 From Tue, 30 Apr 2019 20:44:58
Shadow repository data not available.
Closed, Under Review - calculated based on 4 reviewers votes

In Mercurial 5.0 the section for permissions will be renamed from narrowhgacl to narrowacl.
This change will make rhodecode work with both, prioritizing 5.0.

Pull request versions not available.
Author of this pull request
Pull request reviewers
Time Author Commit Description
105 commits hidden, show them
Add another comment
TODOs: 0 unresolved 0 Resolved
COMMENTS: 4 General, 0 Inline (0 Outdated)
@@ -0,0 +1,47
1 |RCE| 4.16.1 |RNS|
2 ------------------
3
4 Release Date
5 ^^^^^^^^^^^^
6
7 - 2019-03-07
8
9
10 New Features
11 ^^^^^^^^^^^^
12
13
14
15 General
16 ^^^^^^^
17
18 - Docs: added missing reference for the user bookmarks feature.
19
20
21 Security
22 ^^^^^^^^
23
24 - Comments: prevent from allowing to resolve TODO comments across projects. In certain
25 conditions users could resolve TODOs not belonging to the same project.
26
27
28 Performance
29 ^^^^^^^^^^^
30
31
32
33 Fixes
34 ^^^^^
35
36 - Downloads: fixed archive links from file tree view.
37 - Markdown: fixed sanitization of checkbox extensions that removed "checked" attribute.
38 - Upgrade: fixed upgrades from older versions of RhodeCode.
39 - Pull Requests: handle non-ascii branches from short branch selector via URL.
40 - Hooks: fixed again unicode problems with new pull request link generator.
41
42
43
44 Upgrade notes
45 ^^^^^^^^^^^^^
46
47 - Scheduled release addressing problems in 4.16.X releases.
@@ -0,0 +1,41
1 |RCE| 4.16.2 |RNS|
2 ------------------
3
4 Release Date
5 ^^^^^^^^^^^^
6
7 - 2019-04-02
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 Fixes
31 ^^^^^
32
33 - Integrations: fixed missing template variable for fork reference checks.
34 - Permissions: fixed server error when showing permissions for user groups.
35 - Pull requests: fixed a bug in removal of multiple reviewers at once.
36
37
38 Upgrade notes
39 ^^^^^^^^^^^^^
40
41 - Scheduled release addressing problems in 4.16.X releases.
@@ -0,0 +1,19
1 # contains not directly required libraries we want to pin the version.
2
3 atomicwrites==1.2.1
4 attrs==18.2.0
5 billiard==3.5.0.3
6 chameleon==2.24
7 cffi==1.12.2
8 ecdsa==0.13
9 hupper==1.6.1
10 gnureadline==6.3.8
11 jinja2==2.9.6
12 jsonschema==2.6.0
13 pathlib2==2.3.3
14 pyramid-jinja2==2.7
15 setproctitle==1.1.10
16 scandir==1.10.0
17 tempita==0.5.2
18 vine==1.3.0
19 configparser==3.7.4 No newline at end of file
@@ -0,0 +1,93
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import pytest
22 from rhodecode.tests import HG_REPO
23 from rhodecode.api.tests.utils import (
24 build_data, api_call, assert_error, assert_ok)
25
26
27 @pytest.mark.usefixtures("testuser_api", "app")
28 class TestApiSearch(object):
29
30 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
31 ('todo', 23, [
32 'vcs/backends/hg/inmemory.py',
33 'vcs/tests/test_git.py']),
34 ('extension:rst installation', 6, [
35 'docs/index.rst',
36 'docs/installation.rst']),
37 ('def repo', 87, [
38 'vcs/tests/test_git.py',
39 'vcs/tests/test_changesets.py']),
40 ('repository:%s def test' % HG_REPO, 18, [
41 'vcs/tests/test_git.py',
42 'vcs/tests/test_changesets.py']),
43 ('"def main"', 9, [
44 'vcs/__init__.py',
45 'vcs/tests/__init__.py',
46 'vcs/utils/progressbar.py']),
47 ('owner:test_admin', 358, [
48 'vcs/tests/base.py',
49 'MANIFEST.in',
50 'vcs/utils/termcolors.py',
51 'docs/theme/ADC/static/documentation.png']),
52 ('owner:test_admin def main', 72, [
53 'vcs/__init__.py',
54 'vcs/tests/test_utils_filesize.py',
55 'vcs/tests/test_cli.py']),
56 ('owner:michał test', 0, []),
57 ])
58 def test_search_content_results(self, query, expected_hits, expected_paths):
59 id_, params = build_data(
60 self.apikey_regular, 'search',
61 search_query=query,
62 search_type='content')
63
64 response = api_call(self.app, params)
65 json_response = response.json
66
67 assert json_response['result']['item_count'] == expected_hits
68 paths = [x['f_path'] for x in json_response['result']['results']]
69
70 for expected_path in expected_paths:
71 assert expected_path in paths
72
73 @pytest.mark.parametrize("query, expected_hits, expected_paths", [
74 ('readme.rst', 3, []),
75 ('test*', 75, []),
76 ('*model*', 1, []),
77 ('extension:rst', 48, []),
78 ('extension:rst api', 24, []),
79 ])
80 def test_search_file_paths(self, query, expected_hits, expected_paths):
81 id_, params = build_data(
82 self.apikey_regular, 'search',
83 search_query=query,
84 search_type='path')
85
86 response = api_call(self.app, params)
87 json_response = response.json
88
89 assert json_response['result']['item_count'] == expected_hits
90 paths = [x['f_path'] for x in json_response['result']['results']]
91
92 for expected_path in expected_paths:
93 assert expected_path in paths
@@ -0,0 +1,112
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23
24 from rhodecode.api import jsonrpc_method
25 from rhodecode.api.exc import JSONRPCValidationError
26 from rhodecode.api.utils import Optional
27 from rhodecode.lib.index import searcher_from_config
28 from rhodecode.model import validation_schema
29 from rhodecode.model.validation_schema.schemas import search_schema
30
31 log = logging.getLogger(__name__)
32
33
34 @jsonrpc_method()
35 def search(request, apiuser, search_query, search_type, page_limit=Optional(10),
36 page=Optional(1), search_sort=Optional('newfirst'),
37 repo_name=Optional(None), repo_group_name=Optional(None)):
38 """
39 Fetch Full Text Search results using API.
40
41 :param apiuser: This is filled automatically from the |authtoken|.
42 :type apiuser: AuthUser
43 :param search_query: Search query.
44 :type search_query: str
45 :param search_type: Search type. The following are valid options:
46 * commit
47 * content
48 * path
49 :type search_type: str
50 :param page_limit: Page item limit, from 1 to 500. Default 10 items.
51 :type page_limit: Optional(int)
52 :param page: Page number. Default first page.
53 :type page: Optional(int)
54 :param search_sort: Search sort order. Default newfirst. The following are valid options:
55 * newfirst
56 * oldfirst
57 :type search_sort: Optional(str)
58 :param repo_name: Filter by one repo. Default is all.
59 :type repo_name: Optional(str)
60 :param repo_group_name: Filter by one repo group. Default is all.
61 :type repo_group_name: Optional(str)
62 """
63
64 data = {'execution_time': ''}
65 repo_name = Optional.extract(repo_name)
66 repo_group_name = Optional.extract(repo_group_name)
67
68 schema = search_schema.SearchParamsSchema()
69
70 try:
71 search_params = schema.deserialize(
72 dict(search_query=search_query,
73 search_type=search_type,
74 search_sort=Optional.extract(search_sort),
75 page_limit=Optional.extract(page_limit),
76 requested_page=Optional.extract(page))
77 )
78 except validation_schema.Invalid as err:
79 raise JSONRPCValidationError(colander_exc=err)
80
81 search_query = search_params.get('search_query')
82 search_type = search_params.get('search_type')
83 search_sort = search_params.get('search_sort')
84
85 if search_params.get('search_query'):
86 page_limit = search_params['page_limit']
87 requested_page = search_params['requested_page']
88
89 searcher = searcher_from_config(request.registry.settings)
90
91 try:
92 search_result = searcher.search(
93 search_query, search_type, apiuser, repo_name, repo_group_name,
94 requested_page=requested_page, page_limit=page_limit, sort=search_sort)
95
96 data.update(dict(
97 results=list(search_result['results']), page=requested_page,
98 item_count=search_result['count'],
99 items_per_page=page_limit))
100 finally:
101 searcher.cleanup()
102
103 if not search_result['error']:
104 data['execution_time'] = '%s results (%.3f seconds)' % (
105 search_result['count'],
106 search_result['runtime'])
107 else:
108 node = schema['search_query']
109 raise JSONRPCValidationError(
110 colander_exc=validation_schema.Invalid(node, search_result['error']))
111
112 return data
@@ -0,0 +1,54
1 # -*- coding: utf-8 -*-
2
3 import logging
4
5 from alembic.migration import MigrationContext
6 from alembic.operations import Operations
7 from sqlalchemy import String, Column
8 from sqlalchemy.sql import text
9
10 from rhodecode.lib.dbmigrate.versions import _reset_base
11 from rhodecode.model import meta, init_model_encryption
12 from rhodecode.model.db import RepoGroup
13
14
15 log = logging.getLogger(__name__)
16
17
18 def upgrade(migrate_engine):
19 """
20 Upgrade operations go here.
21 Don't create your own engine; bind migrate_engine to your metadata
22 """
23 _reset_base(migrate_engine)
24 from rhodecode.lib.dbmigrate.schema import db_4_16_0_2
25
26 init_model_encryption(db_4_16_0_2)
27
28 context = MigrationContext.configure(migrate_engine.connect())
29 op = Operations(context)
30
31 repo_group = db_4_16_0_2.RepoGroup.__table__
32
33 with op.batch_alter_table(repo_group.name) as batch_op:
34 batch_op.add_column(
35 Column("repo_group_name_hash", String(1024), nullable=True, unique=False))
36
37 _generate_repo_group_name_hashes(db_4_16_0_2, op, meta.Session)
38
39
40 def downgrade(migrate_engine):
41 pass
42
43
44 def _generate_repo_group_name_hashes(models, op, session):
45 repo_groups = models.RepoGroup.get_all()
46 for repo_group in repo_groups:
47 print(repo_group.group_name)
48 hash_ = RepoGroup.hash_repo_group_name(repo_group.group_name)
49 params = {'hash': hash_, 'id': repo_group.group_id}
50 query = text(
51 'UPDATE groups SET repo_group_name_hash = :hash'
52 ' WHERE group_id = :id').bindparams(**params)
53 op.execute(query)
54 session().commit()
@@ -0,0 +1,39
1 # -*- coding: utf-8 -*-
2
3 import logging
4
5 from alembic.migration import MigrationContext
6 from alembic.operations import Operations
7
8 from rhodecode.lib.dbmigrate.versions import _reset_base
9 from rhodecode.model import init_model_encryption
10
11
12 log = logging.getLogger(__name__)
13
14
15 def upgrade(migrate_engine):
16 """
17 Upgrade operations go here.
18 Don't create your own engine; bind migrate_engine to your metadata
19 """
20 _reset_base(migrate_engine)
21 from rhodecode.lib.dbmigrate.schema import db_4_16_0_2
22
23 init_model_encryption(db_4_16_0_2)
24
25 context = MigrationContext.configure(migrate_engine.connect())
26 op = Operations(context)
27
28 repo_group = db_4_16_0_2.RepoGroup.__table__
29
30 with op.batch_alter_table(repo_group.name) as batch_op:
31 batch_op.alter_column("repo_group_name_hash", nullable=False)
32
33
34 def downgrade(migrate_engine):
35 pass
36
37
38 def _generate_repo_group_name_hashes(models, op, session):
39 pass
@@ -0,0 +1,69
1 import os
2 import base64
3 from cryptography.fernet import Fernet, InvalidToken
4 from cryptography.hazmat.backends import default_backend
5 from cryptography.hazmat.primitives import hashes
6 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
7
8
9 class Encryptor(object):
10 key_format = 'enc2$salt:{}$data:{}'
11 pref_len = 5 # salt:, data:
12
13 def __init__(self, enc_key):
14 self.enc_key = enc_key
15
16 def b64_encode(self, data):
17 return base64.urlsafe_b64encode(data)
18
19 def b64_decode(self, data):
20 return base64.urlsafe_b64decode(data)
21
22 def get_encryptor(self, salt):
23 """
24 Uses Fernet as encryptor with HMAC signature
25 :param salt: random salt used for encrypting the data
26 """
27 kdf = PBKDF2HMAC(
28 algorithm=hashes.SHA512(),
29 length=32,
30 salt=salt,
31 iterations=100000,
32 backend=default_backend()
33 )
34 key = self.b64_encode(kdf.derive(self.enc_key))
35 return Fernet(key)
36
37 def _get_parts(self, enc_data):
38 parts = enc_data.split('$', 3)
39 if len(parts) != 3:
40 raise ValueError('Encrypted Data has invalid format, expected {}'.format(self.key_format))
41 prefix, salt, enc_data = parts
42
43 try:
44 salt = self.b64_decode(salt[self.pref_len:])
45 except TypeError:
46 # bad base64
47 raise ValueError('Encrypted Data salt invalid format, expected base64 format')
48
49 enc_data = enc_data[self.pref_len:]
50 return prefix, salt, enc_data
51
52 def encrypt(self, data):
53 salt = os.urandom(64)
54 encryptor = self.get_encryptor(salt)
55 enc_data = encryptor.encrypt(data)
56 return self.key_format.format(self.b64_encode(salt), enc_data)
57
58 def decrypt(self, data, safe=True):
59 parts = self._get_parts(data)
60 salt = parts[1]
61 enc_data = parts[2]
62 encryptor = self.get_encryptor(salt)
63 try:
64 return encryptor.decrypt(enc_data)
65 except (InvalidToken,):
66 if safe:
67 return ''
68 else:
69 raise
@@ -1,5 +1,5
1 [bumpversion]
1 [bumpversion]
2 current_version = 4.16.0
2 current_version = 4.17.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]
@@ -49,3 +49,6
49 4b34ce0d2c3c10510626b3b65044939bb7a2cddf v4.15.0
49 4b34ce0d2c3c10510626b3b65044939bb7a2cddf v4.15.0
50 14502561d22e6b70613674cd675ae9a604b7989f v4.15.1
50 14502561d22e6b70613674cd675ae9a604b7989f v4.15.1
51 4aaa40b605b01af78a9f6882eca561c54b525ef0 v4.15.2
51 4aaa40b605b01af78a9f6882eca561c54b525ef0 v4.15.2
52 797744642eca86640ed20bef2cd77445780abaec v4.16.0
53 6c3452c7c25ed35ff269690929e11960ed6ad7d3 v4.16.1
54 5d8057df561c4b6b81b6401aed7d2f911e6e77f7 v4.16.2
@@ -53,3 +53,12
53
53
54 generate-pkgs:
54 generate-pkgs:
55 nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
55 nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses"
56
57 generate-js-pkgs:
58 rm -rf node_modules && \
59 nix-shell pkgs/shell-generate.nix --command "node2nix --input package.json -o pkgs/node-packages.nix -e pkgs/node-env.nix -c pkgs/node-default.nix -d --flatten --nodejs-8" && \
60 sed -i -e 's/http:\/\//https:\/\//g' pkgs/node-packages.nix
61
62 generate-license-meta:
63 nix-build pkgs/license-generate.nix -o result-license && \
64 cat result-license/licenses.json | python -m json.tool > rhodecode/config/licenses.json No newline at end of file
@@ -133,6 +133,11
133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
133 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
134 #rhodecode.encrypted_values.strict = false
134 #rhodecode.encrypted_values.strict = false
135
135
136 ## Pick algorithm for encryption. Either fernet (more secure) or aes (default)
137 ## fernet is safer, and we strongly recommend switching to it.
138 ## Due to backward compatibility aes is used as default.
139 #rhodecode.encrypted_values.algorithm = fernet
140
136 ## return gzipped responses from RhodeCode (static files/application)
141 ## return gzipped responses from RhodeCode (static files/application)
137 gzip_responses = false
142 gzip_responses = false
138
143
@@ -374,6 +379,10
374 beaker.session.type = file
379 beaker.session.type = file
375 beaker.session.data_dir = %(here)s/data/sessions
380 beaker.session.data_dir = %(here)s/data/sessions
376
381
382 ## redis sessions
383 #beaker.session.type = ext:redis
384 #beaker.session.url = redis://127.0.0.1:6379/2
385
377 ## db based session, fast, and allows easy management over logged in users