463 lines
15 KiB
Python
463 lines
15 KiB
Python
from odoo.exceptions import AccessError
|
|
|
|
from .common import CommonTest
|
|
|
|
|
|
class TestRemote(CommonTest):
|
|
"""Test class for git remote."""
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
# Create another manager for testing
|
|
cls.manager_2 = cls.Users.create(
|
|
{
|
|
"name": "Second Manager",
|
|
"login": "manager2",
|
|
"email": "manager2@test.com",
|
|
"groups_id": [(4, cls.env.ref("cetmix_tower_server.group_manager").id)],
|
|
}
|
|
)
|
|
|
|
# Create test project and source as root
|
|
cls.project = cls.GitProject.create(
|
|
{
|
|
"name": "Test Project",
|
|
}
|
|
)
|
|
cls.source = cls.GitSource.create(
|
|
{
|
|
"name": "Test Source",
|
|
"git_project_id": cls.project.id,
|
|
}
|
|
)
|
|
cls.repo_cetmix_tower = cls.Repo.create(
|
|
{
|
|
"name": "Cetmix Tower",
|
|
"url": "https://github.com/cetmix-test/cetmix-tower.git",
|
|
}
|
|
)
|
|
cls.remote = cls.GitRemote.create(
|
|
{
|
|
"repo_id": cls.repo_cetmix_tower.id,
|
|
"source_id": cls.source.id,
|
|
"head_type": "branch",
|
|
"head": "main",
|
|
}
|
|
)
|
|
cls.repo_test = cls.Repo.create(
|
|
{
|
|
"name": "Test Repository",
|
|
"url": "https://github.com/cetmix-test/test.git",
|
|
}
|
|
)
|
|
|
|
def test_user_access(self):
|
|
"""Test that regular users have no access to git remotes"""
|
|
user_remote = self.GitRemote.with_user(self.user)
|
|
|
|
# Test CRUD operations
|
|
with self.assertRaises(AccessError):
|
|
user_remote.create(
|
|
{
|
|
"repo_id": self.repo_test.id,
|
|
"url_protocol": "https",
|
|
"source_id": self.source.id,
|
|
"head": "main",
|
|
}
|
|
)
|
|
with self.assertRaises(AccessError):
|
|
user_remote.search([("id", "=", self.remote.id)])
|
|
with self.assertRaises(AccessError):
|
|
self.remote.with_user(self.user).write({"head": "dev"})
|
|
with self.assertRaises(AccessError):
|
|
self.remote.with_user(self.user).unlink()
|
|
|
|
def test_manager_read_access(self):
|
|
"""Test manager read access rules"""
|
|
manager_remote = self.GitRemote.with_user(self.manager)
|
|
|
|
# Manager not in project user_ids or manager_ids - should not read
|
|
self.assertFalse(manager_remote.search([("id", "=", self.remote.id)]))
|
|
|
|
# Add manager to project user_ids - should read
|
|
self.project.write({"user_ids": [(4, self.manager.id)]})
|
|
remote = manager_remote.search([("id", "=", self.remote.id)])
|
|
self.assertTrue(remote)
|
|
self.assertEqual(remote.head, "main")
|
|
|
|
# Remove from user_ids, add to manager_ids - should read
|
|
self.project.write(
|
|
{"user_ids": [(3, self.manager.id)], "manager_ids": [(4, self.manager.id)]}
|
|
)
|
|
remote = manager_remote.search([("id", "=", self.remote.id)])
|
|
self.assertTrue(remote.exists())
|
|
|
|
def test_manager_write_access(self):
|
|
"""Test manager write/create access rules"""
|
|
manager_remote = self.GitRemote.with_user(self.manager)
|
|
|
|
# Create project as manager - should be added to manager_ids automatically
|
|
project = self.GitProject.with_user(self.manager).create(
|
|
{
|
|
"name": "Manager Project",
|
|
}
|
|
)
|
|
source = self.GitSource.create(
|
|
{
|
|
"name": "Manager Source",
|
|
"git_project_id": project.id,
|
|
}
|
|
)
|
|
|
|
# Create remote in own project - should succeed
|
|
new_remote = manager_remote.create(
|
|
{
|
|
"repo_id": self.repo_test.id,
|
|
"url_protocol": "https",
|
|
"source_id": source.id,
|
|
"head_type": "branch",
|
|
"head": "main",
|
|
}
|
|
)
|
|
self.assertTrue(new_remote.exists())
|
|
|
|
# Write to own remote - should succeed
|
|
new_remote.write({"head": "dev"})
|
|
self.assertEqual(new_remote.head, "dev")
|
|
|
|
# Write to other's remote - should fail
|
|
with self.assertRaises(AccessError):
|
|
self.remote.with_user(self.manager).write({"head": "dev"})
|
|
|
|
def test_manager_unlink_access(self):
|
|
"""Test manager unlink access rules"""
|
|
# Create project and remote as manager_2
|
|
project = self.GitProject.with_user(self.manager_2).create(
|
|
{
|
|
"name": "Manager 2 Project",
|
|
}
|
|
)
|
|
source = self.GitSource.create(
|
|
{
|
|
"name": "Manager 2 Source",
|
|
"git_project_id": project.id,
|
|
}
|
|
)
|
|
remote = self.GitRemote.with_user(self.manager_2).create(
|
|
{
|
|
"repo_id": self.repo_test.id,
|
|
"url_protocol": "https",
|
|
"source_id": source.id,
|
|
"head_type": "branch",
|
|
"head": "main",
|
|
}
|
|
)
|
|
|
|
# Try delete as different manager - should fail even if added to manager_ids
|
|
project.write({"manager_ids": [(4, self.manager.id)]})
|
|
with self.assertRaises(AccessError):
|
|
remote.with_user(self.manager).unlink()
|
|
|
|
# Create remote as manager and try delete - should succeed
|
|
own_remote = self.GitRemote.with_user(self.manager).create(
|
|
{
|
|
"repo_id": self.repo_test.id,
|
|
"url_protocol": "https",
|
|
"source_id": source.id,
|
|
"head_type": "branch",
|
|
"head": "main",
|
|
}
|
|
)
|
|
self.assertTrue(own_remote.exists())
|
|
own_remote.with_user(self.manager).unlink()
|
|
self.assertFalse(own_remote.exists())
|
|
|
|
def test_root_access(self):
|
|
"""Test root access rules"""
|
|
root_remote = self.GitRemote.with_user(self.root)
|
|
|
|
# Create
|
|
new_remote = root_remote.create(
|
|
{
|
|
"repo_id": self.repo_test.id,
|
|
"url_protocol": "https",
|
|
"source_id": self.source.id,
|
|
"head_type": "branch",
|
|
"head": "main",
|
|
}
|
|
)
|
|
self.assertTrue(new_remote.exists())
|
|
|
|
# Read
|
|
remote = root_remote.search([("id", "=", self.remote.id)])
|
|
self.assertTrue(remote)
|
|
self.assertEqual(remote.head, "main")
|
|
|
|
# Write
|
|
self.remote.with_user(self.root).write({"head": "dev"})
|
|
self.assertEqual(self.remote.head, "dev")
|
|
|
|
# Delete
|
|
new_remote.with_user(self.root).unlink()
|
|
self.assertFalse(new_remote.exists())
|
|
|
|
def test_remote_provider_protocol_and_name(self):
|
|
"""Test if remote provider is detected correctly"""
|
|
|
|
# -- 1--
|
|
# GitHub + https
|
|
# Check if remote provider is detected correctly
|
|
self.assertEqual(
|
|
self.remote_github_https.repo_provider,
|
|
"github",
|
|
"Provider is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_github_https.url_protocol,
|
|
"https",
|
|
"Protocol is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_github_https.name,
|
|
"remote_1",
|
|
"Name is not prepared correctly",
|
|
)
|
|
|
|
# -- 2 --
|
|
# GitLab + ssh
|
|
# Check if remote provider is detected correctly
|
|
self.assertEqual(
|
|
self.remote_gitlab_ssh.repo_provider,
|
|
"gitlab",
|
|
"Provider is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_gitlab_ssh.url_protocol,
|
|
"ssh",
|
|
"Protocol is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_gitlab_ssh.name,
|
|
"remote_3",
|
|
"Name is not prepared correctly",
|
|
)
|
|
|
|
# -- 3 --
|
|
# Bitbucket + https
|
|
# Check if remote provider is detected correctly
|
|
self.assertEqual(
|
|
self.remote_bitbucket_https.repo_provider,
|
|
"bitbucket",
|
|
"Provider is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_bitbucket_https.url_protocol,
|
|
"https",
|
|
"Protocol is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_bitbucket_https.name,
|
|
"remote_1",
|
|
"Name is not prepared correctly",
|
|
)
|
|
|
|
# -- 4 --
|
|
# Other + ssh
|
|
# Check if remote provider is detected correctly
|
|
self.assertEqual(
|
|
self.remote_other_ssh.repo_provider,
|
|
"gitlab", # this is how giturlparse detects the provider
|
|
"Provider is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_other_ssh.url_protocol,
|
|
"ssh",
|
|
"Protocol is not detected correctly",
|
|
)
|
|
self.assertEqual(
|
|
self.remote_other_ssh.name,
|
|
"remote_2",
|
|
"Name is not prepared correctly",
|
|
)
|
|
|
|
def test_git_aggregator_prepare_url(self):
|
|
"""Test if url is prepared correctly"""
|
|
|
|
# -- 1 --
|
|
# GitHub + https
|
|
self.remote_github_https.repo_id.is_private = False
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_url(),
|
|
self.remote_github_https.repo_id.url,
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
# -- 2 --
|
|
# GitHub + https -> private
|
|
self.remote_github_https.repo_id.is_private = True
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_url(),
|
|
"https://$GITHUB_TOKEN:x-oauth-basic@github.com/cetmix-test/cetmix-tower-test.git",
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
# -- 3 --
|
|
# Gitlab + https
|
|
self.remote_gitlab_https.repo_id.is_private = False
|
|
self.assertEqual(
|
|
self.remote_gitlab_https._git_aggregator_prepare_url(),
|
|
self.remote_gitlab_https.repo_id.url,
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
# -- 4 --
|
|
# Gitlab + https -> private
|
|
self.remote_gitlab_https.repo_id.is_private = True
|
|
self.assertEqual(
|
|
self.remote_gitlab_https._git_aggregator_prepare_url(),
|
|
"https://$GITLAB_TOKEN_NAME:$GITLAB_TOKEN@my.gitlab.com/cetmix-test/cetmix-tower-test.git",
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
# -- 5 --
|
|
# Bitbucket + https
|
|
self.remote_bitbucket_https.repo_id.is_private = False
|
|
self.assertEqual(
|
|
self.remote_bitbucket_https._git_aggregator_prepare_url(),
|
|
self.remote_bitbucket_https.repo_id.url,
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
# -- 6 --
|
|
# Bitbucket + https -> private
|
|
self.remote_bitbucket_https.repo_id.is_private = True
|
|
self.assertEqual(
|
|
self.remote_bitbucket_https._git_aggregator_prepare_url(),
|
|
"https://x-token-auth:$BITBUCKET_TOKEN@bitbucket.com/cetmix-test/cetmix-tower-test-enterprise.git",
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
# -- 7 --
|
|
# Other + ssh
|
|
self.remote_other_ssh.repo_id.is_private = False
|
|
self.assertEqual(
|
|
self.remote_other_ssh._git_aggregator_prepare_url(),
|
|
self.remote_other_ssh.repo_id.url_ssh,
|
|
"URL is not prepared correctly",
|
|
)
|
|
|
|
def test_git_aggregator_prepare_head(self):
|
|
"""Test if head is prepared correctly"""
|
|
|
|
# -- 1 --
|
|
# GitHub + PR/MR as link
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_head(),
|
|
"refs/pull/123/head",
|
|
"Head is not prepared correctly",
|
|
)
|
|
|
|
# -- 2 --
|
|
# GitHub + PR/MR as number
|
|
self.remote_github_https.write({"head": "123", "head_type": "pr"})
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_head(),
|
|
"refs/pull/123/head",
|
|
"Head is not prepared correctly",
|
|
)
|
|
|
|
# -- 3 --
|
|
# GitHub + branch as name
|
|
self.remote_github_https.write({"head": "main", "head_type": "branch"})
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_head(),
|
|
self.remote_github_https.head,
|
|
"Head is not prepared correctly",
|
|
)
|
|
|
|
# -- 4 --
|
|
# GitHub + branch as link
|
|
self.remote_github_https.write(
|
|
{
|
|
"head": "https://github.com/cetmix-test/cetmix-tower/tree/14.0-demo-branch",
|
|
"head_type": "branch",
|
|
}
|
|
)
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_head(),
|
|
"14.0-demo-branch",
|
|
"Head is not prepared correctly",
|
|
)
|
|
|
|
# -- 5 --
|
|
# GitHub + commit as number
|
|
self.remote_github_https.write({"head": "1234567890", "head_type": "commit"})
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_head(),
|
|
"1234567890",
|
|
"Head is not prepared correctly",
|
|
)
|
|
|
|
# -- 6 --
|
|
# GitHub + commit as link
|
|
self.remote_github_https.head = (
|
|
"https://github.com/cetmix-test/cetmix-tower/commit/1234567890"
|
|
)
|
|
self.assertEqual(
|
|
self.remote_github_https._git_aggregator_prepare_head(),
|
|
"1234567890",
|
|
"Head is not prepared correctly",
|
|
)
|
|
|
|
def test_manager_server_based_access(self):
|
|
"""Test manager access to remotes through server relationships"""
|
|
manager_remote = self.GitRemote.with_user(self.manager)
|
|
|
|
# Create a server where manager is a user
|
|
server = self.Server.create(
|
|
{
|
|
"name": "Test Server",
|
|
"ip_v4_address": "localhost",
|
|
"ssh_username": "admin",
|
|
"ssh_password": "password",
|
|
"os_id": self.os_debian_10.id,
|
|
"user_ids": [(4, self.manager.id)],
|
|
}
|
|
)
|
|
|
|
# Link project to server
|
|
file = self.File.create(
|
|
{
|
|
"name": "test_file",
|
|
"server_id": server.id,
|
|
}
|
|
)
|
|
self.GitProjectRel.create(
|
|
{
|
|
"server_id": server.id,
|
|
"file_id": file.id,
|
|
"git_project_id": self.project.id,
|
|
"project_format": "git_aggregator",
|
|
}
|
|
)
|
|
|
|
# Manager should be able to read remote through server relationship
|
|
remote = manager_remote.search([("id", "=", self.remote.id)])
|
|
self.assertTrue(remote)
|
|
self.assertEqual(remote.head, "main")
|
|
|
|
# Remove manager from server users
|
|
server.write({"user_ids": [(3, self.manager.id)]})
|
|
|
|
# Manager should not be able to read remote anymore
|
|
self.assertFalse(manager_remote.search([("id", "=", self.remote.id)]))
|
|
|
|
# Add manager to server managers
|
|
server.write({"manager_ids": [(4, self.manager.id)]})
|
|
|
|
# Manager should be able to read remote again
|
|
remote = manager_remote.search([("id", "=", self.remote.id)])
|
|
self.assertTrue(remote)
|
|
self.assertEqual(remote.head, "main")
|