316 lines
12 KiB
Python
316 lines
12 KiB
Python
from odoo.exceptions import AccessError
|
|
|
|
from .common import CommonTest
|
|
|
|
|
|
class TestProject(CommonTest):
|
|
"""Test class for git project."""
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
# Remove user bob from all groups
|
|
cls.remove_from_group(
|
|
cls.user_bob,
|
|
[
|
|
"cetmix_tower_server.group_user",
|
|
"cetmix_tower_server.group_manager",
|
|
"cetmix_tower_server.group_root",
|
|
],
|
|
)
|
|
|
|
# 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 as root
|
|
cls.project = cls.GitProject.create(
|
|
{
|
|
"name": "Test Project",
|
|
}
|
|
)
|
|
|
|
def test_user_access(self):
|
|
"""Test that regular users have no access to git projects"""
|
|
user_project = self.GitProject.with_user(self.user)
|
|
|
|
# Test CRUD operations
|
|
with self.assertRaises(AccessError):
|
|
user_project.create({"name": "New Project"})
|
|
with self.assertRaises(AccessError):
|
|
user_project.browse(self.project.id).read(["name"])
|
|
with self.assertRaises(AccessError):
|
|
user_project.browse(self.project.id).write({"name": "Updated Name"})
|
|
with self.assertRaises(AccessError):
|
|
user_project.browse(self.project.id).unlink()
|
|
|
|
def test_manager_read_access(self):
|
|
"""Test manager read access rules"""
|
|
manager_project = self.GitProject.with_user(self.manager)
|
|
|
|
# Manager not in user_ids or manager_ids - should not read
|
|
with self.assertRaises(AccessError):
|
|
manager_project.browse(self.project.id).read(["name"])
|
|
|
|
# Add manager to user_ids - should read
|
|
self.project.write({"user_ids": [(4, self.manager.id)]})
|
|
self.assertEqual(manager_project.browse(self.project.id).name, "Test Project")
|
|
|
|
# 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)]}
|
|
)
|
|
self.assertEqual(manager_project.browse(self.project.id).name, "Test Project")
|
|
|
|
def test_manager_write_access(self):
|
|
"""Test manager write/create access rules"""
|
|
manager_project = self.GitProject.with_user(self.manager)
|
|
|
|
# Create - should succeed as manager is added by default
|
|
new_project = manager_project.create({"name": "New Project"})
|
|
self.assertTrue(new_project.exists())
|
|
self.assertIn(self.manager, new_project.manager_ids)
|
|
|
|
# Write - not in manager_ids, should fail
|
|
with self.assertRaises(AccessError):
|
|
manager_project.browse(self.project.id).write({"name": "Updated Name"})
|
|
|
|
# Add to manager_ids - should write
|
|
self.project.write({"manager_ids": [(4, self.manager.id)]})
|
|
manager_project.browse(self.project.id).write({"name": "Updated Name"})
|
|
self.assertEqual(self.project.name, "Updated Name")
|
|
|
|
def test_manager_unlink_access(self):
|
|
"""Test manager unlink access rules"""
|
|
# Create project as manager_2
|
|
project = self.GitProject.with_user(self.manager_2).create(
|
|
{"name": "Project to Delete"}
|
|
)
|
|
manager_project = self.GitProject.with_user(self.manager)
|
|
|
|
# Try delete as different manager - should fail
|
|
with self.assertRaises(AccessError):
|
|
manager_project.browse(project.id).unlink()
|
|
|
|
# Add to manager_ids but not creator - should fail
|
|
project.write({"manager_ids": [(4, self.manager.id)]})
|
|
with self.assertRaises(AccessError):
|
|
manager_project.browse(project.id).unlink()
|
|
|
|
# Create as manager and try delete - should succeed
|
|
own_project = manager_project.create({"name": "Own Project"})
|
|
self.assertTrue(own_project.exists())
|
|
own_project.unlink()
|
|
self.assertFalse(own_project.exists())
|
|
|
|
def test_root_access(self):
|
|
"""Test root access rules"""
|
|
root_project = self.GitProject.with_user(self.root)
|
|
|
|
# Create
|
|
new_project = root_project.create({"name": "Root Project"})
|
|
self.assertTrue(new_project.exists())
|
|
|
|
# Read
|
|
self.assertEqual(root_project.browse(self.project.id).name, "Test Project")
|
|
|
|
# Write
|
|
root_project.browse(self.project.id).write({"name": "Updated by Root"})
|
|
self.assertEqual(self.project.name, "Updated by Root")
|
|
|
|
# Delete
|
|
new_project.unlink()
|
|
self.assertFalse(new_project.exists())
|
|
|
|
def test_compute_user_ids(self):
|
|
"""Test computation of user_ids and manager_ids for git projects"""
|
|
# Add users "Bob" and "user" to the group "cetmix_tower_server.group_manager"
|
|
self.add_to_group(self.user_bob, "cetmix_tower_server.group_manager")
|
|
self.add_to_group(self.user, "cetmix_tower_server.group_manager")
|
|
|
|
# -- 1 --
|
|
# Create project as manager
|
|
project_as_manager = self.GitProject.with_user(self.manager).create(
|
|
{
|
|
"name": "Project As Manager",
|
|
}
|
|
)
|
|
# Check that manager is added to both user_ids and manager_ids by default
|
|
self.assertEqual(len(project_as_manager.user_ids), 1)
|
|
self.assertIn(self.manager, project_as_manager.user_ids)
|
|
self.assertEqual(len(project_as_manager.manager_ids), 1)
|
|
self.assertIn(self.manager, project_as_manager.manager_ids)
|
|
|
|
# -- 2 --
|
|
# Create servers with multiple users and managers
|
|
server_1 = self.Server.create(
|
|
{
|
|
"name": "Test Server 1",
|
|
"ip_v4_address": "localhost",
|
|
"ssh_username": "admin",
|
|
"ssh_password": "password",
|
|
"os_id": self.os_debian_10.id,
|
|
"user_ids": [(6, 0, [self.user_bob.id, self.user.id])], # Two users
|
|
"manager_ids": [
|
|
(6, 0, [self.manager.id, self.manager_2.id])
|
|
], # Two managers
|
|
}
|
|
)
|
|
|
|
server_2 = self.Server.create(
|
|
{
|
|
"name": "Test Server 2",
|
|
"ip_v4_address": "localhost",
|
|
"ssh_username": "admin",
|
|
"ssh_password": "password",
|
|
"os_id": self.os_debian_10.id,
|
|
"user_ids": [
|
|
(6, 0, [self.user_bob.id, self.user.id])
|
|
], # Same two users
|
|
"manager_ids": [
|
|
(6, 0, [self.manager.id, self.manager_2.id])
|
|
], # Same two managers
|
|
}
|
|
)
|
|
|
|
# Create project and link servers
|
|
project = self.GitProject.create(
|
|
{
|
|
"name": "Test Project",
|
|
}
|
|
)
|
|
|
|
# Create files and link them to the project
|
|
for server in [server_1, server_2]:
|
|
file = self.File.create(
|
|
{
|
|
"name": f"test_file_{server.name}",
|
|
"server_id": server.id,
|
|
}
|
|
)
|
|
self.GitProjectRel.create(
|
|
{
|
|
"server_id": server.id,
|
|
"file_id": file.id,
|
|
"git_project_id": project.id,
|
|
"project_format": "git_aggregator",
|
|
}
|
|
)
|
|
|
|
# Invalidate cache to ensure computed fields are updated
|
|
project.invalidate_recordset(["server_ids", "user_ids", "manager_ids"])
|
|
|
|
# -- 3 --
|
|
# Test computed values with linked servers
|
|
# Each user/manager should be counted only once even if present in both servers
|
|
self.assertEqual(len(project.server_ids), 2)
|
|
self.assertEqual(len(project.user_ids), 2) # Two unique users
|
|
self.assertIn(self.user_bob, project.user_ids)
|
|
self.assertIn(self.user, project.user_ids)
|
|
self.assertEqual(len(project.manager_ids), 2) # Two unique managers
|
|
self.assertIn(self.manager, project.manager_ids)
|
|
self.assertIn(self.manager_2, project.manager_ids)
|
|
|
|
# -- 4 --
|
|
# Add server with different users/managers
|
|
server_3 = self.Server.create(
|
|
{
|
|
"name": "Test Server 3",
|
|
"ip_v4_address": "localhost",
|
|
"ssh_username": "admin",
|
|
"ssh_password": "password",
|
|
"os_id": self.os_debian_10.id,
|
|
"user_ids": [(6, 0, [self.user_bob.id])], # Only one user
|
|
"manager_ids": [(6, 0, [self.manager_2.id])], # Only second manager
|
|
}
|
|
)
|
|
file_3 = self.File.create(
|
|
{
|
|
"name": "test_file_3",
|
|
"server_id": server_3.id,
|
|
}
|
|
)
|
|
self.GitProjectRel.create(
|
|
{
|
|
"server_id": server_3.id,
|
|
"file_id": file_3.id,
|
|
"git_project_id": project.id,
|
|
"project_format": "git_aggregator",
|
|
}
|
|
)
|
|
|
|
# Invalidate cache to ensure computed fields are updated
|
|
project.invalidate_recordset(["server_ids", "user_ids", "manager_ids"])
|
|
|
|
# Test that computed values are updated correctly
|
|
# Only users/managers present in all servers should remain
|
|
self.assertEqual(len(project.server_ids), 3)
|
|
self.assertEqual(len(project.user_ids), 1) # Only bob is in all servers
|
|
self.assertIn(self.user_bob, project.user_ids)
|
|
self.assertEqual(
|
|
len(project.manager_ids), 1
|
|
) # Only manager_2 is in all servers
|
|
self.assertIn(self.manager_2, project.manager_ids)
|
|
|
|
# -- 5 --
|
|
# Verify that first manager can still access the project
|
|
project_as_manager_1 = self.GitProject.with_user(self.manager).browse(
|
|
project.id
|
|
)
|
|
self.assertTrue(project_as_manager_1.exists())
|
|
self.assertEqual(project_as_manager_1.name, "Test Project")
|
|
|
|
def test_manager_server_based_access(self):
|
|
"""Test manager access through server relationships"""
|
|
manager_project = self.GitProject.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)],
|
|
}
|
|
)
|
|
|
|
# Create a file and 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 project through server relationship
|
|
self.assertEqual(manager_project.browse(self.project.id).name, "Test Project")
|
|
|
|
# Remove manager from server users
|
|
server.write({"user_ids": [(3, self.manager.id)]})
|
|
|
|
# Manager should not be able to read project anymore
|
|
with self.assertRaises(AccessError):
|
|
manager_project.browse(self.project.id).read(["name"])
|
|
|
|
# Add manager to server managers
|
|
server.write({"manager_ids": [(4, self.manager.id)]})
|
|
|
|
# Manager should be able to read project again
|
|
self.assertEqual(manager_project.browse(self.project.id).name, "Test Project")
|