
# Copyright (C) 2010-2023 RhodeCode GmbH
#
# 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/

"""
Test suite for making push/pull operations, on specially modified INI files

.. important::

   You must have git >= 1.8.5 for tests to work fine. With 68b939b git started
   to redirect things to stderr instead of stdout.
"""

import pytest

from rhodecode.model.auth_token import AuthTokenModel
from rhodecode.model.db import Repository
from rhodecode.model.meta import Session
from rhodecode.tests import (GIT_REPO, HG_REPO)

from rhodecode.tests.vcs_operations import (Command, _check_proper_clone)


@pytest.mark.usefixtures("disable_locking", "disable_anonymous_user")
class TestVCSOperations(object):
    def test_clone_by_auth_token(
            self, rc_web_server, tmpdir, user_util, enable_auth_plugins):

        enable_auth_plugins.enable([
            'egg:rhodecode-enterprise-ce#token',
            'egg:rhodecode-enterprise-ce#rhodecode'
        ])

        user = user_util.create_user()
        token = user.auth_tokens[1]

        clone_url = rc_web_server.repo_clone_url(
            HG_REPO, user=user.username, passwd=token)

        stdout, stderr = Command('/tmp').execute(
            'hg clone', clone_url, tmpdir.strpath)

        _check_proper_clone(stdout, stderr, 'hg')

    def test_clone_by_auth_token_expired(
            self, rc_web_server, tmpdir, user_util, enable_auth_plugins):
        enable_auth_plugins.enable([
            'egg:rhodecode-enterprise-ce#token',
            'egg:rhodecode-enterprise-ce#rhodecode'
        ])

        user = user_util.create_user()
        auth_token = AuthTokenModel().create(
            user.user_id, 'test-token', -10, AuthTokenModel.cls.ROLE_VCS)
        token = auth_token.api_key

        clone_url = rc_web_server.repo_clone_url(
            HG_REPO, user=user.username, passwd=token)

        stdout, stderr = Command('/tmp').execute(
            'hg clone', clone_url, tmpdir.strpath)
        assert 'abort: authorization failed' in stderr

        msg = 'reason: bad or inactive token.'
        rc_web_server.assert_message_in_server_logs(msg)

    def test_clone_by_auth_token_bad_role(
            self, rc_web_server, tmpdir, user_util, enable_auth_plugins):
        enable_auth_plugins.enable([
            'egg:rhodecode-enterprise-ce#token',
            'egg:rhodecode-enterprise-ce#rhodecode'
        ])

        user = user_util.create_user()
        auth_token = AuthTokenModel().create(
            user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_API)
        token = auth_token.api_key

        clone_url = rc_web_server.repo_clone_url(
            HG_REPO, user=user.username, passwd=token)

        stdout, stderr = Command('/tmp').execute(
            'hg clone', clone_url, tmpdir.strpath)
        assert 'abort: authorization failed' in stderr

    def test_clone_by_auth_token_user_disabled(
            self, rc_web_server, tmpdir, user_util, enable_auth_plugins):
        enable_auth_plugins.enable([
            'egg:rhodecode-enterprise-ce#token',
            'egg:rhodecode-enterprise-ce#rhodecode'
        ])

        user = user_util.create_user()
        user.active = False
        Session().add(user)
        Session().commit()
        token = user.auth_tokens[1]

        clone_url = rc_web_server.repo_clone_url(
            HG_REPO, user=user.username, passwd=token)

        stdout, stderr = Command('/tmp').execute(
            'hg clone', clone_url, tmpdir.strpath)
        assert 'abort: authorization failed' in stderr

        msg = 'reason: account not active.'
        rc_web_server.assert_message_in_server_logs(msg)

    def test_clone_by_auth_token_with_scope(
            self, rc_web_server, tmpdir, user_util, enable_auth_plugins):
        enable_auth_plugins.enable([
            'egg:rhodecode-enterprise-ce#token',
            'egg:rhodecode-enterprise-ce#rhodecode'
        ])

        user = user_util.create_user()
        auth_token = AuthTokenModel().create(
            user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_VCS)
        token = auth_token.api_key

        # manually set scope
        auth_token.repo = Repository.get_by_repo_name(HG_REPO)
        Session().add(auth_token)
        Session().commit()

        clone_url = rc_web_server.repo_clone_url(
            HG_REPO, user=user.username, passwd=token)

        stdout, stderr = Command('/tmp').execute(
            'hg clone', clone_url, tmpdir.strpath)
        _check_proper_clone(stdout, stderr, 'hg')

    def test_clone_by_auth_token_with_wrong_scope(
            self, rc_web_server, tmpdir, user_util, enable_auth_plugins):
        enable_auth_plugins.enable([
            'egg:rhodecode-enterprise-ce#token',
            'egg:rhodecode-enterprise-ce#rhodecode'
        ])

        user = user_util.create_user()
        auth_token = AuthTokenModel().create(
            user.user_id, 'test-token', -1, AuthTokenModel.cls.ROLE_VCS)
        token = auth_token.api_key

        # manually set scope
        auth_token.repo = Repository.get_by_repo_name(GIT_REPO)
        Session().add(auth_token)
        Session().commit()

        clone_url = rc_web_server.repo_clone_url(
            HG_REPO, user=user.username, passwd=token)

        stdout, stderr = Command('/tmp').execute(
            'hg clone', clone_url, tmpdir.strpath)

        assert 'abort: authorization failed' in stderr

        msg = 'reason: bad or inactive token.'
        rc_web_server.assert_message_in_server_logs(msg)
