1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/documents/tests/test_security.py
2024-12-10 09:04:09 +07:00

502 lines
22 KiB
Python

# -*- coding: utf-8 -*-
import base64
from odoo import http
from odoo.addons.base.tests.common import HttpCaseWithUserDemo
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
from odoo.exceptions import AccessError, ValidationError
from odoo.tools import mute_logger
from psycopg2 import IntegrityError
GIF = b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs="
class TestCaseSecurity(TransactionCase):
def setUp(self):
super(TestCaseSecurity, self).setUp()
self.arbitrary_group = self.env['res.groups'].create({
'name': 'arbitrary_group',
'implied_ids': [(6, 0, [self.ref('base.group_user')])],
})
self.basic_user = self.env['res.users'].create({
'name': "documents test basic user",
'login': "dtbu",
'email': "dtbu@yourcompany.com",
'groups_id': [(6, 0, [self.ref('base.group_user')])]
})
self.document_user = self.env['res.users'].create({
'name': "documents test documents user",
'login': "dtdu",
'email': "dtdu@yourcompany.com",
'groups_id': [(6, 0, [self.ref('documents.group_documents_user')])]
})
self.test_group_user = self.env['res.users'].create({
'name': "documents test group user",
'login': "dtgu",
'email': "dtgu@yourcompany.com",
'groups_id': [(6, 0, [self.arbitrary_group.id])]
})
self.test_group_user2 = self.env['res.users'].create({
'name': "documents test group user2",
'login': "dtgu2",
'email': "dtgu2@yourcompany.com",
'groups_id': [(6, 0, [self.arbitrary_group.id])]
})
self.document_manager = self.env['res.users'].create({
'name': "documents test documents manager",
'login': "dtdm",
'email': "dtdm@yourcompany.com",
'groups_id': [(6, 0, [self.ref('documents.group_documents_manager')])]
})
def test_documents_access_default(self):
"""
Tests the access rights for a document where no access_group is specified
users should default in read/write.
"""
folder_d = self.env['documents.folder'].create({
'name': 'folder D',
})
document_d = self.env['documents.document'].create({
'name': 'document D',
'folder_id': folder_d.id,
})
expected_read_result = [{'id': document_d.id, 'name': 'document D'}]
basic_user_doc_d_read_result = document_d.with_user(self.basic_user).read(['name'])
self.assertEqual(basic_user_doc_d_read_result, expected_read_result,
'test_group_user should be able to read document_d')
doc_d_read_result = document_d.with_user(self.document_user).read(['name'])
self.assertEqual(doc_d_read_result, expected_read_result,
'document_user should be able to read document_d')
document_d.with_user(self.basic_user).write({'name': 'basic_user_write'})
self.assertEqual(document_d.name, 'basic_user_write')
document_d.with_user(self.document_user).write({'name': 'document_user_write'})
self.assertEqual(document_d.name, 'document_user_write')
document_d.with_user(self.test_group_user).write({'name': 'user_write'})
self.assertEqual(document_d.name, 'user_write')
document_d.with_user(self.document_manager).write({'name': 'document_manager_write'})
self.assertEqual(document_d.name, 'document_manager_write')
def test_documents_access_manager_read_write(self):
"""
Tests the access rights for a document where group_documents_manager is the only group with access (read/write).
"""
folder_a = self.env['documents.folder'].create({
'name': 'folder A',
'group_ids': [(6, 0, [self.ref('documents.group_documents_manager')])],
})
document_a = self.env['documents.document'].create({
'name': 'document A',
'folder_id': folder_a.id,
})
with self.assertRaises(AccessError):
document_a.with_user(self.basic_user).read()
with self.assertRaises(AccessError):
document_a.with_user(self.test_group_user).read()
with self.assertRaises(AccessError):
document_a.with_user(self.document_user).read()
with self.assertRaises(AccessError):
document_a.with_user(self.basic_user).write({'name': 'nameChangedA'})
with self.assertRaises(AccessError):
document_a.with_user(self.test_group_user).write({'name': 'nameChangedA'})
with self.assertRaises(AccessError):
document_a.with_user(self.document_user).write({'name': 'nameChangedA'})
document_a.with_user(self.document_manager).write({'name': 'nameChangedManagerA'})
self.assertEqual(document_a.name, 'nameChangedManagerA',
'document manager should be able to write document_a')
def test_documents_access_arbitrary_readonly(self):
"""
Tests the access rights for a document where arbitrary_group is the only group with access (read).
"""
folder_b = self.env['documents.folder'].create({
'name': 'folder B',
'read_group_ids': [(6, 0, [self.arbitrary_group.id])],
})
document_b = self.env['documents.document'].create({
'name': 'document B',
'folder_id': folder_b.id,
})
with self.assertRaises(AccessError):
document_b.with_user(self.basic_user).read()
with self.assertRaises(AccessError):
document_b.with_user(self.document_user).read()
with self.assertRaises(AccessError):
document_b.with_user(self.basic_user).write({'name': 'nameChangedB'})
with self.assertRaises(AccessError):
document_b.with_user(self.document_user).write({'name': 'nameChangedB'})
with self.assertRaises(AccessError):
document_b.with_user(self.test_group_user).write({'name': 'nameChangedB'})
document_b.with_user(self.test_group_user).toggle_favorited()
self.assertFalse(document_b.is_favorited)
test_group_user_document_b_name = document_b.with_user(self.test_group_user).read(['name'])
self.assertEqual(test_group_user_document_b_name, [{'id': document_b.id, 'name': 'document B'}],
'test_group_user should be able to read document_b')
def test_documents_arbitrary_read_write(self):
"""
Tests the access rights for a document where arbitrary_group is the only group with access (read/write).
The group_documents_manager always keeps the read/write access.
"""
folder_c = self.env['documents.folder'].create({
'name': 'folder C',
'group_ids': [(6, 0, [self.arbitrary_group.id])],
})
document_c = self.env['documents.document'].create({
'name': 'document C',
'folder_id': folder_c.id,
})
with self.assertRaises(AccessError):
document_c.with_user(self.basic_user).read()
with self.assertRaises(AccessError):
document_c.with_user(self.document_user).read()
with self.assertRaises(AccessError):
document_c.with_user(self.basic_user).write({'name': 'nameChangedC'})
with self.assertRaises(AccessError):
document_c.with_user(self.document_user).write({'name': 'nameChangedC'})
document_c.with_user(self.test_group_user).write({'name': 'nameChanged'})
self.assertEqual(document_c.name, 'nameChanged',
'test_group_user should be able to write document_c')
document_c.with_user(self.document_manager).write({'name': 'nameChangedManager'})
self.assertEqual(document_c.name, 'nameChangedManager',
'document manager should be able to write document_c')
def test_documents_access(self):
"""
Tests the access rights for a document where 'user_specific' is True.
Users should be limited to records for which they are the owner only if they are limited to read.
"""
arbitrary_group2 = self.env['res.groups'].create({
'name': 'arbitrary_group2',
'implied_ids': [(6, 0, [self.ref('base.group_user')])],
})
test_group2_user = self.env['res.users'].create({
'name': "documents test group user21",
'login': "dtgu21",
'email': "dtgu21@yourcompany.com",
'groups_id': [(6, 0, [arbitrary_group2.id])]
})
folder_owner = self.env['documents.folder'].create({
'name': 'folder owner',
'group_ids': [(6, 0, [self.arbitrary_group.id])],
'read_group_ids': [(6, 0, [arbitrary_group2.id])],
'user_specific': True,
})
document_owner = self.env['documents.document'].create({
'name': 'document owner',
'folder_id': folder_owner.id,
'owner_id': self.test_group_user.id,
})
document_owner2 = self.env['documents.document'].create({
'name': 'document owner2',
'folder_id': folder_owner.id,
'owner_id': self.test_group_user2.id,
})
document_not_owner = self.env['documents.document'].create({
'name': 'document not owner',
'folder_id': folder_owner.id,
})
document_read_owner = self.env['documents.document'].create({
'name': 'document read owner',
'folder_id': folder_owner.id,
'owner_id': test_group2_user.id,
})
# documents access by owner
with self.assertRaises(AccessError):
document_not_owner.with_user(self.basic_user).read()
with self.assertRaises(AccessError):
document_not_owner.with_user(test_group2_user).read()
with self.assertRaises(AccessError):
document_not_owner.with_user(self.document_user).read()
with self.assertRaises(AccessError):
document_not_owner.with_user(self.basic_user).write({'name': 'nameChangedA'})
with self.assertRaises(AccessError):
document_not_owner.with_user(self.document_user).write({'name': 'nameChangedA'})
with self.assertRaises(AccessError):
document_owner.with_user(self.basic_user).read()
with self.assertRaises(AccessError):
document_owner.with_user(self.document_user).read()
with self.assertRaises(AccessError):
document_owner.with_user(test_group2_user).read()
with self.assertRaises(AccessError):
document_owner.with_user(self.basic_user).write({'name': 'nameChangedA'})
with self.assertRaises(AccessError):
document_owner.with_user(self.document_user).write({'name': 'nameChangedA'})
with self.assertRaises(AccessError):
document_owner2.with_user(test_group2_user).read()
name_from_read_owner = document_read_owner.with_user(test_group2_user).name
self.assertEqual(name_from_read_owner, document_read_owner.name,
'test_group2_user should be able to read his own document')
document_owner.with_user(self.test_group_user).write({'name': 'nameChangedOwner'})
self.assertEqual(document_owner.name, 'nameChangedOwner',
'test_group_user should be able to write document_owner')
document_from_user = self.env['documents.document'].with_user(self.test_group_user).browse(
document_not_owner.id)
self.assertEqual(document_from_user.name, 'document not owner',
'test_group_user should be able to read document_not_owner as he is in the write group')
document_not_owner.with_user(self.test_group_user).write({'name': 'nameChangedA'})
self.assertEqual(document_not_owner.name, 'nameChangedA',
'test_group_user should be able to write document_not_owner as he is in the write group')
# We now set the document to user_specific for write permissions.
folder_owner.user_specific_write = True
# since the user is not in the folder's write group, they will not be able to write the documents
with self.assertRaises(AccessError):
document_read_owner.with_user(test_group2_user).write({'name': 'nameChange'})
# the first user is in the write groups but is not the owner of the document
with self.assertRaises(AccessError):
document_read_owner.with_user(self.test_group_user).write({'name': 'nameChange'})
# Now give the right group to test_group2_user.
test_group2_user.groups_id += self.arbitrary_group
# they should now be able to write on the document
document_read_owner.with_user(test_group2_user).write({'name': 'nameChangedC'})
def test_share_link_access(self):
"""
Tests access rights for share links when the access rights of the folder is changed after the creation of the link.
"""
folder_share = self.env['documents.folder'].create({
'name': 'folder share',
})
document = self.env['documents.document'].create({
'datas': b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
'name': 'file.gif',
'mimetype': 'image/gif',
'folder_id': folder_share.id,
})
test_share = self.env['documents.share'].with_user(self.document_user).create({
'folder_id': folder_share.id,
'type': 'ids',
'document_ids': [(6, 0, [document.id])]
})
available_documents = test_share._get_documents_and_check_access(test_share.access_token, operation='read')
self.assertEqual(len(available_documents), 1,
'This method should indicate that the create_uid has access to the folder')
folder_share.write({'group_ids': [(6, 0, [self.ref('documents.group_documents_manager')])]})
available_documents = test_share._get_documents_and_check_access(test_share.access_token, operation='read')
self.assertEqual(len(available_documents), 0,
'This method should indicate that the create_uid doesnt have access to the folder anymore')
def test_share_link_dynamic_access(self):
"""
Test the dynamic change of documents available from share links when access conditions change.
"""
TEXT = base64.b64encode(bytes("TEST", 'utf-8'))
folder_share = self.env['documents.folder'].create({
'name': 'folder share',
'read_group_ids': [(6, 0, [self.ref('documents.group_documents_user')])]
})
document_a = self.env['documents.document'].create({
'datas': b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
'owner_id': self.document_manager.id,
'name': 'filea.gif',
'mimetype': 'image/gif',
'folder_id': folder_share.id,
})
document_b = self.env['documents.document'].create({
'datas': TEXT,
'owner_id': self.document_manager.id,
'name': 'fileb.gif',
'mimetype': 'image/gif',
'folder_id': folder_share.id,
})
document_c = self.env['documents.document'].create({
'datas': TEXT,
'owner_id': self.document_user.id,
'name': 'filec.gif',
'mimetype': 'image/gif',
'folder_id': folder_share.id,
})
test_share = self.env['documents.share'].with_user(self.document_user).create({
'folder_id': folder_share.id,
'type': 'ids',
'document_ids': [(6, 0, [document_a.id, document_b.id, document_c.id])]
})
available_documents = test_share._get_documents_and_check_access(test_share.access_token, operation='read')
self.assertEqual(len(available_documents), 3, "there should be 3 available documents")
folder_share.write({'user_specific': True})
available_documents = test_share._get_documents_and_check_access(test_share.access_token, operation='read')
self.assertEqual(len(available_documents), 1, "there should be 1 available document")
self.assertEqual(available_documents.name, 'filec.gif', "the document C should be available")
def test_share_parent_folder_with_ids(self):
"""
Tests the access rights of a share link when the parent folder is shared with ids.
"""
TEXT = base64.b64encode(bytes("TEST", 'utf-8'))
folder_share_parent = self.env['documents.folder'].create({
'name': 'folder share',
'read_group_ids': [(6, 0, [self.ref('documents.group_documents_user')])]
})
folder_share_child_a = self.env['documents.folder'].create({
'name': 'folder share',
'parent_folder_id': folder_share_parent.id,
'read_group_ids': [(6, 0, [self.ref('documents.group_documents_user')])]
})
folder_share_child_b = self.env['documents.folder'].create({
'name': 'folder share',
'parent_folder_id': folder_share_parent.id,
'read_group_ids': [(6, 0, [self.ref('documents.group_documents_user')])]
})
document_a = self.env['documents.document'].create({
'datas': b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
'owner_id': self.document_manager.id,
'name': 'filea.gif',
'mimetype': 'image/gif',
'folder_id': folder_share_child_a.id,
})
document_b = self.env['documents.document'].create({
'datas': TEXT,
'owner_id': self.document_manager.id,
'name': 'fileb.gif',
'mimetype': 'image/gif',
'folder_id': folder_share_child_b.id,
})
test_share = self.env['documents.share'].with_user(self.document_user).create({
'folder_id': folder_share_parent.id,
'type': 'ids',
'document_ids': [(6, 0, [document_a.id, document_b.id])]
})
available_documents = test_share._get_documents_and_check_access(test_share.access_token, operation='read')
self.assertEqual(len(available_documents), 2, "there should be 2 available documents")
def test_folder_user_specific_write(self):
"""
Tests that `user_specific_write` is disabled when `user_specific` is disabled
"""
folder = self.env['documents.folder'].create({
'name': 'Test Folder',
'user_specific': True,
'user_specific_write': True,
})
folder.user_specific = False
self.assertFalse(folder.user_specific_write)
with mute_logger('odoo.sql_db'):
with self.assertRaises(IntegrityError):
with self.cr.savepoint():
folder.write({'user_specific_write': True})
def test_folder_has_write_access(self):
"""
Tests that user has right write access for folder using `has_write_access`.
"""
# No groups on folder
folder = self.env['documents.folder'].create({
'name': 'Test Folder',
})
self.assertTrue(folder.with_user(self.document_manager).has_write_access, "Document manager should have write access on folder")
self.assertTrue(folder.with_user(self.document_user).has_write_access, "Document user should have write access on folder")
# manager can write and arbitary group can read
folder.write({
'group_ids': [(6, 0, [self.ref('documents.group_documents_manager')])],
'read_group_ids': [(6, 0, [self.arbitrary_group.id])],
})
self.assertTrue(folder.with_user(self.document_manager).has_write_access, "Document manager should have write access on folder")
self.assertFalse(folder.with_user(self.document_user).has_write_access, "Document user should not have write access on folder")
def test_link_constrains(self):
folder = self.env['documents.folder'].create({'name': 'folder'})
for url in ("wrong URL format", "https:/ example.com", "test https://example.com"):
with self.assertRaises(ValidationError):
self.env['documents.document'].create({
'name': 'Test Document',
'folder_id': folder.id,
'url': url,
})
@tagged('post_install', '-at_install')
class TestCaseSecurityRoutes(HttpCaseWithUserDemo):
@mute_logger('odoo.http')
def test_documents_zip_access(self):
user_folder, admin_folder = self.env['documents.folder'].create([
{
'name': 'User Folder',
'group_ids': [(6, 0, [self.ref('base.group_user')])],
'read_group_ids': [(6, 0, [self.ref('base.group_user')])],
},
{
'name': 'Folder',
'group_ids': [(6, 0, [self.ref('base.group_system')])],
'read_group_ids': [(6, 0, [self.ref('base.group_system')])],
}
])
user_attachment, admin_attachment = self.env['ir.attachment'].create([
{
'datas': GIF,
'name': 'attachmentGif_A.gif',
'res_model': 'documents.document',
'res_id': 0,
},
{
'datas': GIF,
'name': 'attachmentGif_B.gif',
'res_model': 'documents.document',
'res_id': 0,
}
])
user_document, admin_document = self.env['documents.document'].create([
{
'folder_id': user_folder.id,
'name': 'new name A',
'attachment_id': user_attachment.id,
},
{
'folder_id': admin_folder.id,
'name': 'new name B',
'attachment_id': admin_attachment.id,
}
])
self.env['res.users'].create({
'name': "user",
'login': "user",
'password': "useruser",
'email': "user@yourcompany.com",
'groups_id': [(6, 0, [self.ref('documents.group_documents_user')])]
})
self.authenticate('user', 'useruser')
response = self.url_open('/document/zip', data={
'file_ids': ','.join(map(str, [user_document.id, admin_document.id])),
'zip_name': 'testZip.zip',
'csrf_token': http.Request.csrf_token(self),
})
self.assertNotEqual(response.status_code, 200)