Tower: upload cetmix_tower_server 16.0.2.2.9 (via marketplace)
This commit is contained in:
255
addons/cetmix_tower_server/tests/test_plan_line_action.py
Normal file
255
addons/cetmix_tower_server/tests/test_plan_line_action.py
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
# Copyright (C) 2025 Cetmix OÜ
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo.exceptions import AccessError
|
||||||
|
|
||||||
|
from .common import TestTowerCommon
|
||||||
|
|
||||||
|
|
||||||
|
class TestTowerPlanLineAction(TestTowerCommon):
|
||||||
|
"""Test the cx.tower.plan.line.action model access rights."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
|
||||||
|
# Create a test server
|
||||||
|
cls.server = cls.Server.create(
|
||||||
|
{
|
||||||
|
"name": "Test Server",
|
||||||
|
"ip_v4_address": "localhost",
|
||||||
|
"ssh_username": "test",
|
||||||
|
"ssh_password": "test",
|
||||||
|
"ssh_port": 22,
|
||||||
|
"user_ids": [(6, 0, [cls.user.id])],
|
||||||
|
"manager_ids": [(6, 0, [cls.manager.id])],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a test plan with access level 1 for user tests
|
||||||
|
cls.test_plan = cls.Plan.create(
|
||||||
|
{
|
||||||
|
"name": "Test Access Plan",
|
||||||
|
"access_level": "1",
|
||||||
|
"user_ids": [(6, 0, [cls.user.id])],
|
||||||
|
"manager_ids": [(6, 0, [cls.manager.id])],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a test plan line
|
||||||
|
cls.test_plan_line = cls.plan_line.create(
|
||||||
|
{
|
||||||
|
"plan_id": cls.test_plan.id,
|
||||||
|
"command_id": cls.command_create_dir.id,
|
||||||
|
"sequence": 10,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a test action
|
||||||
|
cls.test_action = cls.plan_line_action.create(
|
||||||
|
{
|
||||||
|
"line_id": cls.test_plan_line.id,
|
||||||
|
"condition": "==",
|
||||||
|
"value_char": "0",
|
||||||
|
"action": "n",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_user_read_access(self):
|
||||||
|
"""Test user read access to plan line actions"""
|
||||||
|
# Case 1: User should be able to read action when:
|
||||||
|
# - access_level == "1"
|
||||||
|
# - user is in plan's user_ids OR server's user_ids
|
||||||
|
recs = self.plan_line_action.with_user(self.user).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"User should be able to read action when conditions are met",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 2: User should not be able to read when access_level > "1"
|
||||||
|
self.test_plan.access_level = "2"
|
||||||
|
recs = self.plan_line_action.with_user(self.user).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"User should not be able to read action when access_level > '1'",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 3: User should not be able to read when not in user_ids
|
||||||
|
self.test_plan.access_level = "1"
|
||||||
|
self.test_plan.user_ids = [(5, 0, 0)] # Remove all users
|
||||||
|
recs = self.plan_line_action.with_user(self.user).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"User should not be able to read action when not in user_ids",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 4: User should be able to read when in server's user_ids
|
||||||
|
self.test_plan.server_ids = [(6, 0, [self.server.id])]
|
||||||
|
recs = self.plan_line_action.with_user(self.user).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"User should be able to read action when in server's user_ids",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_user_write_create_unlink_access(self):
|
||||||
|
"""Test user write/create/unlink access restrictions"""
|
||||||
|
# Users should not be able to create actions
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
self.plan_line_action.with_user(self.user).create(
|
||||||
|
{
|
||||||
|
"line_id": self.test_plan_line.id,
|
||||||
|
"condition": "==",
|
||||||
|
"value_char": "0",
|
||||||
|
"action": "n",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Users should not be able to write actions
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
self.test_action.with_user(self.user).write({"value_char": "1"})
|
||||||
|
|
||||||
|
# Users should not be able to unlink actions
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
self.test_action.with_user(self.user).unlink()
|
||||||
|
|
||||||
|
def test_manager_read_access(self):
|
||||||
|
"""Test manager read access to plan line actions"""
|
||||||
|
# Case 1: Manager should be able to read when:
|
||||||
|
# - access_level <= "2"
|
||||||
|
# - manager is in plan's manager_ids
|
||||||
|
recs = self.plan_line_action.with_user(self.manager).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"Manager should be able to read action when conditions are met",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 2: Manager should not be able to read when access_level > "2"
|
||||||
|
self.test_plan.access_level = "3"
|
||||||
|
recs = self.plan_line_action.with_user(self.manager).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertNotIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"Manager should not be able to read action when access_level > '2'",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 3: Manager should be able to read when in server's manager_ids
|
||||||
|
self.test_plan.access_level = "2"
|
||||||
|
self.test_plan.manager_ids = [(5, 0, 0)] # Remove all managers
|
||||||
|
self.test_plan.server_ids = [(6, 0, [self.server.id])]
|
||||||
|
recs = self.plan_line_action.with_user(self.manager).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"Manager should be able to read when in server's manager_ids",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_manager_write_create_access(self):
|
||||||
|
"""Test manager write/create access to plan line actions"""
|
||||||
|
# Case 1: Manager should be able to create/write when:
|
||||||
|
# - access_level <= "2"
|
||||||
|
# - manager is in plan's manager_ids
|
||||||
|
try:
|
||||||
|
# Test create
|
||||||
|
self.plan_line_action.with_user(self.manager).create(
|
||||||
|
{
|
||||||
|
"line_id": self.test_plan_line.id,
|
||||||
|
"condition": "==",
|
||||||
|
"value_char": "1",
|
||||||
|
"action": "n",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# Test write
|
||||||
|
self.test_action.with_user(self.manager).write({"value_char": "2"})
|
||||||
|
except AccessError:
|
||||||
|
self.fail("Manager should be able to create/write when conditions are met")
|
||||||
|
|
||||||
|
# Case 2: Manager should not be able to create/write when access_level > "2"
|
||||||
|
self.test_plan.access_level = "3"
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
self.plan_line_action.with_user(self.manager).create(
|
||||||
|
{
|
||||||
|
"line_id": self.test_plan_line.id,
|
||||||
|
"condition": "==",
|
||||||
|
"value_char": "1",
|
||||||
|
"action": "n",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
self.test_action.with_user(self.manager).write({"value_char": "3"})
|
||||||
|
|
||||||
|
def test_manager_unlink_access(self):
|
||||||
|
"""Test manager unlink access to plan line actions"""
|
||||||
|
# Create action as manager to test unlink rights
|
||||||
|
action = self.plan_line_action.with_user(self.manager).create(
|
||||||
|
{
|
||||||
|
"line_id": self.test_plan_line.id,
|
||||||
|
"condition": "==",
|
||||||
|
"value_char": "0",
|
||||||
|
"action": "n",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 1: Manager should be able to unlink when:
|
||||||
|
# - access_level <= "2"
|
||||||
|
# - manager is the creator
|
||||||
|
# - manager is in plan's manager_ids
|
||||||
|
try:
|
||||||
|
action.unlink()
|
||||||
|
except AccessError:
|
||||||
|
self.fail("Manager should be able to unlink when conditions are met")
|
||||||
|
|
||||||
|
# Case 2: Manager should not be able to unlink actions created by others
|
||||||
|
action = self.test_action # Created by admin in setUp
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
action.with_user(self.manager).unlink()
|
||||||
|
|
||||||
|
def test_root_unrestricted_access(self):
|
||||||
|
"""Test root user unrestricted access"""
|
||||||
|
# Root should have full access regardless of conditions
|
||||||
|
try:
|
||||||
|
# Test read
|
||||||
|
recs = self.plan_line_action.with_user(self.root).search(
|
||||||
|
[("id", "=", self.test_action.id)]
|
||||||
|
)
|
||||||
|
self.assertIn(
|
||||||
|
self.test_action,
|
||||||
|
recs,
|
||||||
|
"Root should be able to read action without restrictions",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test create
|
||||||
|
new_action = self.plan_line_action.with_user(self.root).create(
|
||||||
|
{
|
||||||
|
"line_id": self.test_plan_line.id,
|
||||||
|
"condition": "==",
|
||||||
|
"value_char": "1",
|
||||||
|
"action": "n",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test write
|
||||||
|
self.test_action.with_user(self.root).write({"value_char": "2"})
|
||||||
|
|
||||||
|
# Test unlink
|
||||||
|
new_action.unlink()
|
||||||
|
except AccessError:
|
||||||
|
self.fail("Root user should have unrestricted access")
|
||||||
Reference in New Issue
Block a user