##// END OF EJS Templates
fix(permissions): fixed security problem with apply-to-children functionality breaking permissions for private repositories...
fix(permissions): fixed security problem with apply-to-children functionality breaking permissions for private repositories fixes: RCCE-141

File last commit:

r5173:95a4b30f default
r5550:cb083474 default
Show More
test_admin_gists.py
365 lines | 14.3 KiB | text/x-python | PythonLexer
/ rhodecode / apps / gist / tests / test_admin_gists.py
copyrights: updated for 2023
r5088 # Copyright (C) 2010-2023 RhodeCode GmbH
dan
gists: migrated gists controller to pyramid view.
r1891 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import mock
import pytest
from rhodecode.lib import helpers as h
from rhodecode.model.db import User, Gist
from rhodecode.model.gist import GistModel
from rhodecode.model.meta import Session
from rhodecode.tests import (
TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
TestController, assert_session_flash)
tests: refactor code to use a single test url generator
r5173 from rhodecode.tests.routes import route_path
dan
gists: migrated gists controller to pyramid view.
r1891
class GistUtility(object):
def __init__(self):
self._gist_ids = []
def __call__(
tests: fixed all tests for python3 BIG changes
r5087 self, f_name: bytes, content: bytes = b'some gist', lifetime=-1,
dan
gists: migrated gists controller to pyramid view.
r1891 description='gist-desc', gist_type='public',
acl_level=Gist.GIST_PUBLIC, owner=TEST_USER_ADMIN_LOGIN):
gist_mapping = {
f_name: {'content': content}
}
user = User.get_by_username(owner)
gist = GistModel().create(
description, owner=user, gist_mapping=gist_mapping,
gist_type=gist_type, lifetime=lifetime, gist_acl_level=acl_level)
Session().commit()
self._gist_ids.append(gist.gist_id)
return gist
def cleanup(self):
for gist_id in self._gist_ids:
gist = Gist.get(gist_id)
if gist:
Session().delete(gist)
Session().commit()
pytest: use consistent way of creating a fixture by using pytest.fixture()
r3946 @pytest.fixture()
dan
gists: migrated gists controller to pyramid view.
r1891 def create_gist(request):
gist_utility = GistUtility()
request.addfinalizer(gist_utility.cleanup)
return gist_utility
class TestGistsController(TestController):
def test_index_empty(self, create_gist):
self.log_user()
response = self.app.get(route_path('gists_show'))
tests: fixed all tests for python3 BIG changes
r5087 response.mustcontain('var gist_data = [];')
dan
gists: migrated gists controller to pyramid view.
r1891
def test_index(self, create_gist):
self.log_user()
tests: fixed all tests for python3 BIG changes
r5087 g1 = create_gist(b'gist1')
g2 = create_gist(b'gist2', lifetime=1400)
g3 = create_gist(b'gist3', description='gist3-desc')
g4 = create_gist(b'gist4', gist_type='private').gist_access_id
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(route_path('gists_show'))
dan
gists: cleanup UI and make the gist access id use monospace
r4193 response.mustcontain(g1.gist_access_id)
response.mustcontain(g2.gist_access_id)
response.mustcontain(g3.gist_access_id)
dan
gists: migrated gists controller to pyramid view.
r1891 response.mustcontain('gist3-desc')
dan
gists: cleanup UI and make the gist access id use monospace
r4193 response.mustcontain(no=[g4])
dan
gists: migrated gists controller to pyramid view.
r1891
# Expiration information should be visible
tests: fixed all tests for python3 BIG changes
r5087 expires_tag = str(h.age_component(h.time_to_utcdatetime(g2.gist_expires)))
dan
gists: migrated gists controller to pyramid view.
r1891 response.mustcontain(expires_tag.replace('"', '\\"'))
def test_index_private_gists(self, create_gist):
self.log_user()
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist5', gist_type='private')
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(route_path('gists_show', params=dict(private=1)))
# and privates
dan
gists: cleanup UI and make the gist access id use monospace
r4193 response.mustcontain(gist.gist_access_id)
dan
gists: migrated gists controller to pyramid view.
r1891
def test_index_show_all(self, create_gist):
self.log_user()
tests: fixed all tests for python3 BIG changes
r5087 create_gist(b'gist1')
create_gist(b'gist2', lifetime=1400)
create_gist(b'gist3', description='gist3-desc')
create_gist(b'gist4', gist_type='private')
dan
gists: migrated gists controller to pyramid view.
r1891
response = self.app.get(route_path('gists_show', params=dict(all=1)))
assert len(GistModel.get_all()) == 4
# and privates
for gist in GistModel.get_all():
dan
gists: cleanup UI and make the gist access id use monospace
r4193 response.mustcontain(gist.gist_access_id)
dan
gists: migrated gists controller to pyramid view.
r1891
def test_index_show_all_hidden_from_regular(self, create_gist):
self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
tests: fixed all tests for python3 BIG changes
r5087 create_gist(b'gist2', gist_type='private')
create_gist(b'gist3', gist_type='private')
create_gist(b'gist4', gist_type='private')
dan
gists: migrated gists controller to pyramid view.
r1891
response = self.app.get(route_path('gists_show', params=dict(all=1)))
assert len(GistModel.get_all()) == 3
# since we don't have access to private in this view, we
# should see nothing
for gist in GistModel.get_all():
dan
gists: cleanup UI and make the gist access id use monospace
r4193 response.mustcontain(no=[gist.gist_access_id])
dan
gists: migrated gists controller to pyramid view.
r1891
def test_create(self):
self.log_user()
response = self.app.post(
route_path('gists_create'),
params={'lifetime': -1,
'content': 'gist test',
'filename': 'foo',
gists: removed private/public gist buttons and replaced them with radio group...
r4083 'gist_type': 'public',
dan
gists: migrated gists controller to pyramid view.
r1891 'gist_acl_level': Gist.ACL_LEVEL_PUBLIC,
'csrf_token': self.csrf_token},
status=302)
response = response.follow()
response.mustcontain('added file: foo')
response.mustcontain('gist test')
def test_create_with_path_with_dirs(self):
self.log_user()
response = self.app.post(
route_path('gists_create'),
params={'lifetime': -1,
'content': 'gist test',
'filename': '/home/foo',
gists: removed private/public gist buttons and replaced them with radio group...
r4083 'gist_type': 'public',
dan
gists: migrated gists controller to pyramid view.
r1891 'gist_acl_level': Gist.ACL_LEVEL_PUBLIC,
'csrf_token': self.csrf_token},
status=200)
response.mustcontain('Filename /home/foo cannot be inside a directory')
def test_access_expired_gist(self, create_gist):
self.log_user()
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'never-see-me')
dan
gists: migrated gists controller to pyramid view.
r1891 gist.gist_expires = 0 # 1970
Session().add(gist)
Session().commit()
self.app.get(route_path('gist_show', gist_id=gist.gist_access_id),
status=404)
def test_create_private(self):
self.log_user()
response = self.app.post(
route_path('gists_create'),
params={'lifetime': -1,
'content': 'private gist test',
'filename': 'private-foo',
gists: removed private/public gist buttons and replaced them with radio group...
r4083 'gist_type': 'private',
dan
gists: migrated gists controller to pyramid view.
r1891 'gist_acl_level': Gist.ACL_LEVEL_PUBLIC,
'csrf_token': self.csrf_token},
status=302)
response = response.follow()
response.mustcontain('added file: private-foo<')
response.mustcontain('private gist test')
response.mustcontain('Private Gist')
# Make sure private gists are not indexed by robots
response.mustcontain(
'<meta name="robots" content="noindex, nofollow">')
def test_create_private_acl_private(self):
self.log_user()
response = self.app.post(
route_path('gists_create'),
params={'lifetime': -1,
'content': 'private gist test',
'filename': 'private-foo',
gists: removed private/public gist buttons and replaced them with radio group...
r4083 'gist_type': 'private',
dan
gists: migrated gists controller to pyramid view.
r1891 'gist_acl_level': Gist.ACL_LEVEL_PRIVATE,
'csrf_token': self.csrf_token},
status=302)
response = response.follow()
response.mustcontain('added file: private-foo<')
response.mustcontain('private gist test')
response.mustcontain('Private Gist')
# Make sure private gists are not indexed by robots
response.mustcontain(
'<meta name="robots" content="noindex, nofollow">')
def test_create_with_description(self):
self.log_user()
response = self.app.post(
route_path('gists_create'),
params={'lifetime': -1,
'content': 'gist test',
'filename': 'foo-desc',
'description': 'gist-desc',
gists: removed private/public gist buttons and replaced them with radio group...
r4083 'gist_type': 'public',
dan
gists: migrated gists controller to pyramid view.
r1891 'gist_acl_level': Gist.ACL_LEVEL_PUBLIC,
'csrf_token': self.csrf_token},
status=302)
response = response.follow()
response.mustcontain('added file: foo-desc')
response.mustcontain('gist test')
response.mustcontain('gist-desc')
def test_create_public_with_anonymous_access(self):
self.log_user()
params = {
'lifetime': -1,
'content': 'gist test',
'filename': 'foo-desc',
'description': 'gist-desc',
gists: removed private/public gist buttons and replaced them with radio group...
r4083 'gist_type': 'public',
dan
gists: migrated gists controller to pyramid view.
r1891 'gist_acl_level': Gist.ACL_LEVEL_PUBLIC,
'csrf_token': self.csrf_token
}
response = self.app.post(
route_path('gists_create'), params=params, status=302)
self.logout_user()
response = response.follow()
response.mustcontain('added file: foo-desc')
response.mustcontain('gist test')
response.mustcontain('gist-desc')
def test_new(self):
self.log_user()
self.app.get(route_path('gists_new'))
def test_delete(self, create_gist):
self.log_user()
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'delete-me')
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.post(
route_path('gist_delete', gist_id=gist.gist_id),
params={'csrf_token': self.csrf_token})
assert_session_flash(response, 'Deleted gist %s' % gist.gist_id)
def test_delete_normal_user_his_gist(self, create_gist):
self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'delete-me', owner=TEST_USER_REGULAR_LOGIN)
dan
gists: migrated gists controller to pyramid view.
r1891
response = self.app.post(
route_path('gist_delete', gist_id=gist.gist_id),
params={'csrf_token': self.csrf_token})
assert_session_flash(response, 'Deleted gist %s' % gist.gist_id)
def test_delete_normal_user_not_his_own_gist(self, create_gist):
self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'delete-me-2')
dan
gists: migrated gists controller to pyramid view.
r1891
self.app.post(
route_path('gist_delete', gist_id=gist.gist_id),
params={'csrf_token': self.csrf_token}, status=404)
def test_show(self, create_gist):
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-show-me')
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(route_path('gist_show', gist_id=gist.gist_access_id))
response.mustcontain('added file: gist-show-me<')
assert_response = response.assert_response()
assert_response.element_equals_to(
'div.rc-user span.user',
dan
tests: fixed some tests after recent changes.
r4422 '<a href="/_profiles/test_admin">test_admin</a>')
dan
gists: migrated gists controller to pyramid view.
r1891
response.mustcontain('gist-desc')
def test_show_without_hg(self, create_gist):
with mock.patch(
'rhodecode.lib.vcs.settings.ALIASES', ['git']):
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-show-me-again')
dan
gists: migrated gists controller to pyramid view.
r1891 self.app.get(
route_path('gist_show', gist_id=gist.gist_access_id), status=200)
def test_show_acl_private(self, create_gist):
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-show-me-only-when-im-logged-in',
dan
gists: migrated gists controller to pyramid view.
r1891 acl_level=Gist.ACL_LEVEL_PRIVATE)
self.app.get(
route_path('gist_show', gist_id=gist.gist_access_id), status=404)
# now we log-in we should see thi gist
self.log_user()
response = self.app.get(
route_path('gist_show', gist_id=gist.gist_access_id))
response.mustcontain('added file: gist-show-me-only-when-im-logged-in')
assert_response = response.assert_response()
assert_response.element_equals_to(
'div.rc-user span.user',
dan
tests: fixed some tests after recent changes.
r4422 '<a href="/_profiles/test_admin">test_admin</a>')
dan
gists: migrated gists controller to pyramid view.
r1891 response.mustcontain('gist-desc')
def test_show_as_raw(self, create_gist):
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-show-me', content=b'GIST CONTENT')
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(
route_path('gist_show_formatted',
gist_id=gist.gist_access_id, revision='tip',
format='raw'))
gists: fixes for tests and cleanup code that is now handled by the form deserializer
r4996 assert response.text == 'GIST CONTENT'
dan
gists: migrated gists controller to pyramid view.
r1891
def test_show_as_raw_individual_file(self, create_gist):
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-show-me-raw', content=b'GIST BODY')
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(
route_path('gist_show_formatted_path',
gist_id=gist.gist_access_id, format='raw',
revision='tip', f_path='gist-show-me-raw'))
gists: fixes for tests and cleanup code that is now handled by the form deserializer
r4996 assert response.text == 'GIST BODY'
dan
gists: migrated gists controller to pyramid view.
r1891
def test_edit_page(self, create_gist):
self.log_user()
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-for-edit', content=b'GIST EDIT BODY')
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(route_path('gist_edit', gist_id=gist.gist_access_id))
response.mustcontain('GIST EDIT BODY')
def test_edit_page_non_logged_user(self, create_gist):
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-for-edit', content=b'GIST EDIT BODY')
dan
gists: migrated gists controller to pyramid view.
r1891 self.app.get(route_path('gist_edit', gist_id=gist.gist_access_id),
status=302)
def test_edit_normal_user_his_gist(self, create_gist):
self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'gist-for-edit', owner=TEST_USER_REGULAR_LOGIN)
dan
gists: migrated gists controller to pyramid view.
r1891 self.app.get(route_path('gist_edit', gist_id=gist.gist_access_id,
status=200))
def test_edit_normal_user_not_his_own_gist(self, create_gist):
self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
tests: fixed all tests for python3 BIG changes
r5087 gist = create_gist(b'delete-me')
dan
gists: migrated gists controller to pyramid view.
r1891 self.app.get(route_path('gist_edit', gist_id=gist.gist_access_id),
status=404)
def test_user_first_name_is_escaped(self, user_util, create_gist):
xss_atack_string = '"><script>alert(\'First Name\')</script>'
xss_escaped_string = h.html_escape(h.escape(xss_atack_string))
password = 'test'
user = user_util.create_user(
firstname=xss_atack_string, password=password)
tests: fixed all tests for python3 BIG changes
r5087 create_gist(b'gist', gist_type='public', owner=user.username)
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(route_path('gists_show'))
response.mustcontain(xss_escaped_string)
def test_user_last_name_is_escaped(self, user_util, create_gist):
xss_atack_string = '"><script>alert(\'Last Name\')</script>'
xss_escaped_string = h.html_escape(h.escape(xss_atack_string))
password = 'test'
user = user_util.create_user(
lastname=xss_atack_string, password=password)
tests: fixed all tests for python3 BIG changes
r5087 create_gist(b'gist', gist_type='public', owner=user.username)
dan
gists: migrated gists controller to pyramid view.
r1891 response = self.app.get(route_path('gists_show'))
response.mustcontain(xss_escaped_string)