odoo-addon-dms 16.0.1.8.0.3__py3-none-any.whl → 17.0.1.0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/dms/README.rst +132 -78
- odoo/addons/dms/__manifest__.py +34 -16
- odoo/addons/dms/actions/file.xml +1 -3
- odoo/addons/dms/controllers/main.py +0 -34
- odoo/addons/dms/controllers/portal.py +178 -92
- odoo/addons/dms/data/onboarding_data.xml +77 -0
- odoo/addons/dms/demo/access_group.xml +3 -9
- odoo/addons/dms/i18n/de.po +13 -117
- odoo/addons/dms/i18n/dms.pot +137 -174
- odoo/addons/dms/i18n/es.po +15 -58
- odoo/addons/dms/i18n/fr.po +296 -450
- odoo/addons/dms/i18n/he_IL.po +13 -117
- odoo/addons/dms/i18n/it.po +15 -131
- odoo/addons/dms/i18n/nl.po +13 -117
- odoo/addons/dms/i18n/pt.po +13 -121
- odoo/addons/dms/i18n/pt_BR.po +28 -147
- odoo/addons/dms/i18n/ru.po +13 -117
- odoo/addons/dms/models/__init__.py +7 -1
- odoo/addons/dms/models/abstract_dms_mixin.py +1 -1
- odoo/addons/dms/models/access_groups.py +18 -11
- odoo/addons/dms/models/base.py +10 -2
- odoo/addons/dms/models/directory.py +46 -75
- odoo/addons/dms/models/{category.py → dms_category.py} +10 -42
- odoo/addons/dms/models/dms_file.py +125 -147
- odoo/addons/dms/models/dms_security_mixin.py +26 -22
- odoo/addons/dms/models/ir_attachment.py +0 -1
- odoo/addons/dms/models/ir_binary.py +19 -0
- odoo/addons/dms/models/mail_thread.py +2 -4
- odoo/addons/dms/models/mixins_thumbnail.py +13 -8
- odoo/addons/dms/models/onboarding_onboarding.py +16 -0
- odoo/addons/dms/models/onboarding_onboarding_step.py +50 -0
- odoo/addons/dms/models/res_company.py +22 -47
- odoo/addons/dms/models/res_config_settings.py +0 -1
- odoo/addons/dms/models/storage.py +4 -24
- odoo/addons/dms/models/tag.py +1 -1
- odoo/addons/dms/readme/CONFIGURE.md +59 -0
- odoo/addons/dms/readme/CONTRIBUTORS.md +14 -0
- odoo/addons/dms/readme/CREDITS.md +6 -0
- odoo/addons/dms/readme/DESCRIPTION.md +9 -0
- odoo/addons/dms/readme/INSTALL.md +4 -0
- odoo/addons/dms/readme/ROADMAP.md +19 -0
- odoo/addons/dms/readme/USAGE.md +11 -0
- odoo/addons/dms/security/security.xml +1 -0
- odoo/addons/dms/static/description/icon.png +0 -0
- odoo/addons/dms/static/description/icon.svg +4 -1
- odoo/addons/dms/static/description/index.html +133 -88
- odoo/addons/dms/static/description/portal_icon.svg +12 -0
- odoo/addons/dms/static/src/js/fields/{path_owl.esm.js → path_json/path_owl.esm.js} +22 -4
- odoo/addons/dms/static/src/js/fields/{path_owl.xml → path_json/path_owl.xml} +7 -4
- odoo/addons/dms/static/src/js/fields/preview_binary/preview_record.esm.js +47 -0
- odoo/addons/dms/static/src/js/{views/fields/binary → fields/preview_binary}/preview_record.xml +5 -4
- odoo/addons/dms/static/src/js/views/dms_file_upload.esm.js +155 -148
- odoo/addons/dms/static/src/js/views/file_kanban_controller.xml +0 -1
- odoo/addons/dms/static/src/js/views/file_kanban_record.esm.js +26 -27
- odoo/addons/dms/static/src/js/views/file_kanban_renderer.esm.js +1 -2
- odoo/addons/dms/static/src/js/views/file_kanban_renderer.xml +12 -16
- odoo/addons/dms/static/src/js/views/file_kanban_view.esm.js +11 -9
- odoo/addons/dms/static/src/js/views/file_list_controller.esm.js +1 -1
- odoo/addons/dms/static/src/js/views/file_list_renderer.xml +1 -7
- odoo/addons/dms/static/src/js/views/file_list_view.esm.js +11 -9
- odoo/addons/dms/static/src/js/views/search_panel.esm.js +9 -10
- odoo/addons/dms/static/src/models/attachment.esm.js +83 -82
- odoo/addons/dms/static/src/models/attachment_image.esm.js +30 -28
- odoo/addons/dms/static/src/models/attachment_viewer_viewable.esm.js +27 -25
- odoo/addons/dms/static/src/scss/directory_kanban.scss +28 -73
- odoo/addons/dms/static/src/scss/dms_common.scss +69 -0
- odoo/addons/dms/static/src/scss/file_kanban.scss +22 -34
- odoo/addons/dms/static/src/scss/portal.scss +12 -0
- odoo/addons/dms/static/tests/tours/dms_portal_tour.esm.js +46 -0
- odoo/addons/dms/{views/dms_portal_templates.xml → template/portal.xml} +13 -3
- odoo/addons/dms/tests/common.py +20 -4
- odoo/addons/dms/tests/data/mail01.eml +2 -2
- odoo/addons/dms/tests/data/mail02.eml +2 -2
- odoo/addons/dms/tests/test_benchmark.py +16 -21
- odoo/addons/dms/tests/test_directory.py +128 -40
- odoo/addons/dms/tests/test_file.py +112 -30
- odoo/addons/dms/tests/test_file_database.py +50 -24
- odoo/addons/dms/tests/test_portal.py +50 -37
- odoo/addons/dms/tests/test_storage_attachment.py +85 -63
- odoo/addons/dms/tests/test_storage_database.py +89 -35
- odoo/addons/dms/tools/file.py +63 -11
- odoo/addons/dms/views/dms_access_groups_views.xml +2 -17
- odoo/addons/dms/views/{category.xml → dms_category.xml} +4 -9
- odoo/addons/dms/views/{directory.xml → dms_directory.xml} +168 -176
- odoo/addons/dms/views/dms_file.xml +170 -191
- odoo/addons/dms/views/{tag.xml → dms_tag.xml} +50 -53
- odoo/addons/dms/views/menu.xml +52 -21
- odoo/addons/dms/views/res_config_settings.xml +31 -82
- odoo/addons/dms/views/storage.xml +7 -13
- odoo_addon_dms-17.0.1.0.0.2.dist-info/METADATA +257 -0
- {odoo_addon_dms-16.0.1.8.0.3.dist-info → odoo_addon_dms-17.0.1.0.0.2.dist-info}/RECORD +93 -93
- {odoo_addon_dms-16.0.1.8.0.3.dist-info → odoo_addon_dms-17.0.1.0.0.2.dist-info}/WHEEL +1 -1
- odoo_addon_dms-17.0.1.0.0.2.dist-info/top_level.txt +1 -0
- odoo/addons/dms/readme/CONFIGURE.rst +0 -40
- odoo/addons/dms/readme/CONTRIBUTORS.rst +0 -16
- odoo/addons/dms/readme/CREDITS.rst +0 -6
- odoo/addons/dms/readme/DESCRIPTION.rst +0 -6
- odoo/addons/dms/readme/INSTALL.rst +0 -9
- odoo/addons/dms/readme/ROADMAP.rst +0 -8
- odoo/addons/dms/readme/USAGE.rst +0 -8
- odoo/addons/dms/static/src/js/components/path/path.esm.js +0 -0
- odoo/addons/dms/static/src/js/dms_portal_tour.js +0 -57
- odoo/addons/dms/static/src/js/fields/path.js +0 -81
- odoo/addons/dms/static/src/js/views/fields/binary/preview_record.esm.js +0 -35
- odoo/addons/dms/static/src/js/views/many_drop_target.js +0 -98
- odoo/addons/dms/static/src/scss/variables.scss +0 -9
- odoo/addons/dms/static/src/xml/views.xml +0 -72
- odoo/addons/dms/template/assets.xml +0 -44
- odoo/addons/dms/template/onboarding.xml +0 -97
- odoo_addon_dms-16.0.1.8.0.3.dist-info/METADATA +0 -203
- odoo_addon_dms-16.0.1.8.0.3.dist-info/top_level.txt +0 -1
@@ -23,78 +23,156 @@ class FileFilestoreTestCase(StorageFileBaseCase):
|
|
23
23
|
def setUpClass(cls):
|
24
24
|
super().setUpClass()
|
25
25
|
cls.user_a = new_test_user(cls.env, login="user-a", groups="dms.group_dms_user")
|
26
|
+
cls.directory_group_a = cls.create_directory(storage=cls.storage)
|
27
|
+
cls.inaccessible_directory = cls.create_directory(storage=cls.storage)
|
28
|
+
cls.inaccessible_file = cls.create_file(directory=cls.inaccessible_directory)
|
29
|
+
cls.inaccessible_group = cls.access_group_model.create(
|
30
|
+
{
|
31
|
+
"name": "Inaccessible Group. No directory set",
|
32
|
+
"perm_create": True,
|
33
|
+
"explicit_user_ids": [(6, 0, [cls.user_a.id])],
|
34
|
+
}
|
35
|
+
)
|
36
|
+
cls.sub_directory_x = cls.create_directory(directory=cls.directory_group_a)
|
26
37
|
cls.group_a = cls.access_group_model.create(
|
27
38
|
{
|
28
39
|
"name": "Group A",
|
29
40
|
"perm_create": True,
|
30
41
|
"explicit_user_ids": [(6, 0, [cls.user_a.id])],
|
42
|
+
"directory_ids": [
|
43
|
+
(4, cls.directory_group_a.id),
|
44
|
+
(4, cls.sub_directory_x.id),
|
45
|
+
],
|
31
46
|
}
|
32
47
|
)
|
33
|
-
cls.directory_group_a = cls.create_directory(storage=cls.storage)
|
34
48
|
cls.directory_group_a.group_ids = [(4, cls.group_a.id)]
|
35
|
-
cls.sub_directory_x = cls.create_directory(directory=cls.directory_group_a)
|
36
49
|
cls.file2 = cls.create_file(directory=cls.sub_directory_x)
|
37
50
|
|
51
|
+
@users("user-a")
|
52
|
+
def test_unaccessible_file(self):
|
53
|
+
dms_files = self.file_model.with_user(self.env.user).search(
|
54
|
+
[("storage_id", "=", self.storage.id)]
|
55
|
+
)
|
56
|
+
self.assertNotIn(
|
57
|
+
self.inaccessible_file.id,
|
58
|
+
dms_files.ids,
|
59
|
+
msg="User A should not see the unaccessible file since it "
|
60
|
+
"was not granted access to the directory",
|
61
|
+
)
|
62
|
+
self.assertIn(
|
63
|
+
self.file2.id,
|
64
|
+
dms_files.ids,
|
65
|
+
msg="User A should see the file2 since it was granted access to "
|
66
|
+
"the directory",
|
67
|
+
)
|
68
|
+
|
69
|
+
@users("user-a")
|
70
|
+
def test_inaccessible_directory(self):
|
71
|
+
dms_directories = self.directory_model.with_user(self.env.user).search(
|
72
|
+
[("storage_id", "=", self.storage.id)]
|
73
|
+
)
|
74
|
+
self.assertNotIn(
|
75
|
+
self.inaccessible_directory.id,
|
76
|
+
dms_directories.ids,
|
77
|
+
msg="User A should not see the inaccessible directory since "
|
78
|
+
"it was not granted access to the directory",
|
79
|
+
)
|
80
|
+
self.assertIn(
|
81
|
+
self.sub_directory_x.id,
|
82
|
+
dms_directories.ids,
|
83
|
+
msg="User A should see the sub_directory_x since it was granted "
|
84
|
+
"access to the directory",
|
85
|
+
)
|
86
|
+
|
38
87
|
@users("user-a")
|
39
88
|
def test_file_access(self):
|
40
89
|
dms_files = self.file_model.with_user(self.env.user).search(
|
41
90
|
[("storage_id", "=", self.storage.id)]
|
42
91
|
)
|
43
|
-
self.assertNotIn(self.file.id, dms_files.ids)
|
44
|
-
self.assertIn(self.file2.id, dms_files.ids)
|
92
|
+
self.assertNotIn(self.file.id, dms_files.ids, msg="User A should not see file")
|
93
|
+
self.assertIn(self.file2.id, dms_files.ids, msg="User A should see file2")
|
45
94
|
dms_directories = self.directory_model.with_user(self.env.user).search(
|
46
95
|
[("storage_id", "=", self.storage.id)]
|
47
96
|
)
|
48
|
-
self.assertNotIn(
|
49
|
-
|
97
|
+
self.assertNotIn(
|
98
|
+
self.directory.id,
|
99
|
+
dms_directories.ids,
|
100
|
+
msg="User A should not see directory",
|
101
|
+
)
|
102
|
+
self.assertIn(
|
103
|
+
self.sub_directory_x.id,
|
104
|
+
dms_directories.ids,
|
105
|
+
msg="User A should see sub_directory_x",
|
106
|
+
)
|
50
107
|
|
51
108
|
@users("dms-manager", "dms-user")
|
52
109
|
@mute_logger("odoo.models.unlink")
|
53
110
|
def test_content_file(self):
|
54
|
-
|
55
|
-
self.assertTrue(
|
56
|
-
self.assertTrue(
|
57
|
-
self.assertTrue(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
self.assertTrue(
|
62
|
-
|
63
|
-
|
64
|
-
|
111
|
+
object_file = self.create_file(directory=self.directory)
|
112
|
+
self.assertTrue(object_file.content, msg="Content is not empty")
|
113
|
+
self.assertTrue(object_file.content_file, msg="Content file is not empty")
|
114
|
+
self.assertTrue(
|
115
|
+
object_file.with_context(bin_size=True).content,
|
116
|
+
msg="Content is not empty (with bin_size)",
|
117
|
+
)
|
118
|
+
self.assertTrue(
|
119
|
+
object_file.with_context(bin_size=True).content_file,
|
120
|
+
msg="Content file is not empty (with bin_size)",
|
121
|
+
)
|
122
|
+
self.assertTrue(
|
123
|
+
object_file.with_context(human_size=True).content_file,
|
124
|
+
msg="Content file is not empty (with human_size)",
|
125
|
+
)
|
126
|
+
self.assertTrue(
|
127
|
+
object_file.with_context(base64=True).content_file,
|
128
|
+
msg="Content file is not empty (with base64)",
|
129
|
+
)
|
130
|
+
self.assertTrue(
|
131
|
+
object_file.with_context(stream=True).content_file,
|
132
|
+
msg="Content file is not empty (with stream)",
|
133
|
+
)
|
134
|
+
oid = object_file.with_context(oid=True).content_file
|
135
|
+
self.assertTrue(oid, msg="Content file is not empty (with oid)")
|
136
|
+
object_file.with_context(**{"show_content": True}).write(
|
65
137
|
{"content": base64.b64encode(b"\xff new content")}
|
66
138
|
)
|
67
139
|
self.assertNotEqual(
|
68
|
-
oid,
|
140
|
+
oid,
|
141
|
+
object_file.with_context(**{"oid": True}).content_file,
|
142
|
+
msg="Content file has changed",
|
69
143
|
)
|
70
|
-
self.assertTrue(
|
71
|
-
|
144
|
+
self.assertTrue(object_file.export_data(["content"]))
|
145
|
+
object_file.unlink()
|
72
146
|
|
73
147
|
def test_content_file_mimetype(self):
|
74
148
|
file_svg = self.env.ref("dms.file_05_demo")
|
75
|
-
self.assertEqual(file_svg.mimetype, "image/svg+xml")
|
149
|
+
self.assertEqual(file_svg.mimetype, "image/svg+xml", msg="SVG mimetype")
|
76
150
|
file_logo = self.env.ref("dms.file_02_demo")
|
77
|
-
self.assertEqual(file_logo.mimetype, "image/jpeg")
|
151
|
+
self.assertEqual(file_logo.mimetype, "image/jpeg", msg="JPEG mimetype")
|
78
152
|
|
79
153
|
def test_content_file_mimetype_magic_library(self):
|
80
154
|
if not magic:
|
81
155
|
self.skipTest("Without python-magic library installed")
|
82
156
|
file_video = self.env.ref("dms.file_10_demo")
|
83
|
-
self.assertEqual(file_video.mimetype, "video/mp4")
|
157
|
+
self.assertEqual(file_video.mimetype, "video/mp4", msg="MP4 mimetype")
|
84
158
|
|
85
159
|
def test_content_file_extension(self):
|
86
160
|
file_pdf = self.env.ref("dms.file_27_demo")
|
87
|
-
self.assertEqual(file_pdf.extension, "pdf")
|
161
|
+
self.assertEqual(file_pdf.extension, "pdf", msg="PDF extension")
|
88
162
|
file_pdf.name = "Document_05"
|
89
|
-
self.assertEqual(
|
163
|
+
self.assertEqual(
|
164
|
+
file_pdf.extension, "pdf", msg="PDF extension without extension"
|
165
|
+
)
|
90
166
|
file_pdf.name = "Document_05.pdf"
|
91
|
-
self.assertEqual(file_pdf.extension, "pdf")
|
167
|
+
self.assertEqual(file_pdf.extension, "pdf", msg="PDF extension with extension")
|
92
168
|
|
93
169
|
def test_wizard_dms_file_move(self):
|
94
170
|
file3 = self.create_file(directory=self.sub_directory_x)
|
95
171
|
all_files = self.file + self.file2 + file3
|
96
172
|
# Error: All files must have the same root directory
|
97
|
-
with self.assertRaises(
|
173
|
+
with self.assertRaises(
|
174
|
+
UserError, msg="All files must have the same root directory"
|
175
|
+
):
|
98
176
|
self.file_model.with_context(
|
99
177
|
active_ids=all_files.ids
|
100
178
|
).action_wizard_dms_file_move()
|
@@ -105,7 +183,11 @@ class FileFilestoreTestCase(StorageFileBaseCase):
|
|
105
183
|
).action_wizard_dms_file_move()
|
106
184
|
wizard_model = self.env[res["res_model"]].with_context(**res["context"])
|
107
185
|
wizard = wizard_model.create({"directory_id": self.directory.id})
|
108
|
-
self.assertEqual(wizard.count_files, 2)
|
186
|
+
self.assertEqual(wizard.count_files, 2, msg="Wizard has 2 files")
|
109
187
|
wizard.process()
|
110
|
-
self.assertEqual(
|
111
|
-
|
188
|
+
self.assertEqual(
|
189
|
+
self.file2.directory_id, self.directory, msg="File2 has a new directory"
|
190
|
+
)
|
191
|
+
self.assertEqual(
|
192
|
+
file3.directory_id, self.directory, msg="File3 has a new directory"
|
193
|
+
)
|
@@ -25,29 +25,35 @@ class FileDatabaseTestCase(StorageDatabaseBaseCase):
|
|
25
25
|
self.create_file(directory=root_directory)
|
26
26
|
sub_directory = self.create_directory(directory=root_directory)
|
27
27
|
self.create_file(sub_directory)
|
28
|
-
self.assertEqual(root_directory.count_total_files, 2)
|
29
|
-
self.assertEqual(
|
28
|
+
self.assertEqual(root_directory.count_total_files, 2, "Total files should be 2")
|
29
|
+
self.assertEqual(
|
30
|
+
sub_directory.count_files, 1, "Subdirectory total files should be 1"
|
31
|
+
)
|
30
32
|
|
31
33
|
@users("dms-manager", "dms-user")
|
32
34
|
def test_lock_file(self):
|
33
35
|
file = self.create_file(directory=self.directory)
|
34
36
|
file.lock()
|
35
|
-
self.assertTrue(file.is_locked)
|
37
|
+
self.assertTrue(file.is_locked, "File should be locked")
|
36
38
|
file.unlock()
|
37
|
-
self.assertFalse(file.is_locked)
|
39
|
+
self.assertFalse(file.is_locked, "File should be unlocked")
|
38
40
|
|
39
41
|
@users("dms-manager", "dms-user")
|
40
42
|
def test_copy_file(self):
|
41
43
|
copy_file = self.file.copy()
|
42
|
-
self.assertEqual(
|
43
|
-
|
44
|
+
self.assertEqual(
|
45
|
+
self.file.storage_id, copy_file.storage_id, "Storage should be the same"
|
46
|
+
)
|
47
|
+
self.assertEqual(
|
48
|
+
self.file.content, copy_file.content, "Content should be the same"
|
49
|
+
)
|
44
50
|
|
45
51
|
@users("dms-manager", "dms-user")
|
46
52
|
def test_rename_file(self):
|
47
53
|
file = self.create_file(directory=self.directory)
|
48
54
|
extension = file.extension
|
49
55
|
file.write({"name": "test-%s.jpg" % self.env.user.login})
|
50
|
-
self.assertNotEqual(file.extension, extension)
|
56
|
+
self.assertNotEqual(file.extension, extension, "Extension should be different")
|
51
57
|
|
52
58
|
@users("dms-manager", "dms-user")
|
53
59
|
def test_move_file(self):
|
@@ -55,11 +61,15 @@ class FileDatabaseTestCase(StorageDatabaseBaseCase):
|
|
55
61
|
path_names = file.path_names
|
56
62
|
file.write({"directory_id": self.directory2.id})
|
57
63
|
file.flush_recordset()
|
58
|
-
self.assertNotEqual(
|
64
|
+
self.assertNotEqual(
|
65
|
+
path_names, file.path_names, "Path names should be different"
|
66
|
+
)
|
59
67
|
|
60
68
|
@users("dms-manager", "dms-user")
|
61
69
|
def test_move_directory(self):
|
62
|
-
with self.assertRaises(
|
70
|
+
with self.assertRaises(
|
71
|
+
UserError, msg="Directory can't have any parent, because it is " "root"
|
72
|
+
):
|
63
73
|
self.directory.write(
|
64
74
|
{
|
65
75
|
"is_root_directory": False,
|
@@ -72,57 +82,73 @@ class FileDatabaseTestCase(StorageDatabaseBaseCase):
|
|
72
82
|
def test_unlink_file(self):
|
73
83
|
file = self.create_file(directory=self.directory)
|
74
84
|
file.unlink()
|
75
|
-
self.assertFalse(file.exists())
|
85
|
+
self.assertFalse(file.exists(), "File should not exist")
|
76
86
|
|
77
87
|
@users("dms-manager", "dms-user")
|
78
88
|
def test_compute_thumbnail(self):
|
79
|
-
self.assertTrue(self.file_demo_01.image_128)
|
89
|
+
self.assertTrue(self.file_demo_01.image_128, "Thumbnail should be computed")
|
80
90
|
|
81
91
|
@users("dms-manager", "dms-user")
|
82
92
|
def test_compute_path_names(self):
|
83
|
-
self.assertTrue(self.file.path_names)
|
93
|
+
self.assertTrue(self.file.path_names, "Path names should be computed")
|
84
94
|
|
85
95
|
@users("dms-manager", "dms-user")
|
86
96
|
def test_compute_path_json(self):
|
87
|
-
self.assertTrue(self.file.path_json)
|
97
|
+
self.assertTrue(self.file.path_json, "Path json should be computed")
|
88
98
|
|
89
99
|
@users("dms-manager", "dms-user")
|
90
100
|
def test_compute_mimetype(self):
|
91
|
-
self.assertTrue(self.file.mimetype)
|
101
|
+
self.assertTrue(self.file.mimetype, "Mimetype should be computed")
|
92
102
|
|
93
103
|
@users("dms-manager", "dms-user")
|
94
104
|
def test_compute_extension(self):
|
95
|
-
self.assertTrue(self.file.extension)
|
105
|
+
self.assertTrue(self.file.extension, "Extension should be computed")
|
96
106
|
|
97
107
|
@users("dms-manager", "dms-user")
|
98
108
|
def test_size_calculation(self):
|
99
|
-
self.assertTrue(self.file.size)
|
109
|
+
self.assertTrue(self.file.size, "Size should be computed")
|
100
110
|
|
101
111
|
@users("dms-manager", "dms-user")
|
102
112
|
def test_checksum_calculation(self):
|
103
|
-
self.assertTrue(self.file.checksum)
|
113
|
+
self.assertTrue(self.file.checksum, "Checksum should be computed")
|
104
114
|
|
105
115
|
@users("dms-manager", "dms-user")
|
106
116
|
def test_compute_content(self):
|
107
|
-
self.assertTrue(
|
108
|
-
|
117
|
+
self.assertTrue(
|
118
|
+
self.file.with_context(bin_size=True).content,
|
119
|
+
"Content should be computed (with bin_size)",
|
120
|
+
)
|
121
|
+
self.assertTrue(
|
122
|
+
self.file.with_context(bin_size=False).content,
|
123
|
+
"Content should be computed (without bin_size)",
|
124
|
+
)
|
109
125
|
self.assertNotEqual(
|
110
126
|
self.file.with_context(bin_size=False).content,
|
111
127
|
self.file.with_context(bin_size=True).content,
|
128
|
+
"Content should be different",
|
112
129
|
)
|
113
130
|
|
114
131
|
@users("dms-manager", "dms-user")
|
115
132
|
def test_compute_save_type(self):
|
116
|
-
self.assertTrue(self.file.save_type)
|
133
|
+
self.assertTrue(self.file.save_type, "Save type should be computed")
|
117
134
|
|
118
135
|
@users("dms-manager", "dms-user")
|
119
136
|
def test_compute_migration(self):
|
120
|
-
self.assertTrue(self.file.migration)
|
137
|
+
self.assertTrue(self.file.migration, "Migration should be computed")
|
121
138
|
|
122
139
|
@users("dms-manager", "dms-user")
|
123
140
|
def test_search_panel(self):
|
124
|
-
self.assertTrue(
|
125
|
-
|
126
|
-
|
141
|
+
self.assertTrue(
|
142
|
+
self.file.search_panel_select_range("directory_id"),
|
143
|
+
"Directory should be selected",
|
144
|
+
)
|
145
|
+
self.assertTrue(
|
146
|
+
self.file.search_panel_select_multi_range("directory_id"),
|
147
|
+
"Directory should be selected",
|
148
|
+
)
|
149
|
+
self.assertTrue(
|
150
|
+
self.file.search_panel_select_multi_range("tag_ids"),
|
151
|
+
"Tag should be selected",
|
152
|
+
)
|
127
153
|
res = self.file.search_panel_select_range("directory_id", enable_counters=True)
|
128
154
|
self.assertTrue(self.directory2.id == x["id"] for x in res["values"])
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
|
3
3
|
|
4
4
|
import odoo.tests
|
5
|
+
from odoo.exceptions import AccessError
|
5
6
|
from odoo.tests.common import users
|
6
7
|
|
7
8
|
from .common import StorageAttachmentBaseCase
|
@@ -14,10 +15,15 @@ class TestDmsPortal(odoo.tests.HttpCase, StorageAttachmentBaseCase):
|
|
14
15
|
super().setUpClass()
|
15
16
|
cls.partner = cls.env.ref("base.partner_demo_portal")
|
16
17
|
cls.portal_user = cls.partner.user_ids
|
18
|
+
cls.other_portal_user = cls.other_partner.user_ids
|
17
19
|
cls.portal_user.login = "portal"
|
20
|
+
cls.other_portal_user.login = "other_portal"
|
18
21
|
cls._create_attachment("test.txt")
|
22
|
+
cls._create_attachment("test2.txt", cls.other_partner)
|
19
23
|
cls.directory_partner = cls._get_partner_directory()
|
24
|
+
cls.other_directory_partner = cls._get_partner_directory(cls.other_partner)
|
20
25
|
cls.file_partner = cls.directory_partner.file_ids[0]
|
26
|
+
cls.other_file_partner = cls.other_directory_partner.file_ids[0]
|
21
27
|
|
22
28
|
def test_access_portal(self):
|
23
29
|
self.authenticate("portal", "portal")
|
@@ -25,54 +31,61 @@ class TestDmsPortal(odoo.tests.HttpCase, StorageAttachmentBaseCase):
|
|
25
31
|
file_text = self.create_file(directory=self.directory_partner)
|
26
32
|
url = "%s&access_token=abc-def" % (file_text.access_url)
|
27
33
|
response = self.url_open(url, timeout=20)
|
28
|
-
self.assertEqual(
|
34
|
+
self.assertEqual(
|
35
|
+
response.status_code, 404, "Can't access file with incorrect access_token"
|
36
|
+
)
|
29
37
|
# 200
|
30
38
|
response = self.url_open(self.file_partner._get_share_url(), timeout=20)
|
31
|
-
self.assertEqual(
|
39
|
+
self.assertEqual(
|
40
|
+
response.status_code, 200, "Can access file with correct access_token"
|
41
|
+
)
|
32
42
|
# 200
|
33
43
|
response = self.url_open(self.directory_partner._get_share_url(), timeout=20)
|
34
|
-
self.assertEqual(
|
44
|
+
self.assertEqual(
|
45
|
+
response.status_code, 200, "Can access directory with correct access_token"
|
46
|
+
)
|
35
47
|
|
36
48
|
def test_tour(self):
|
37
49
|
for tour in ("dms_portal_mail_tour", "dms_portal_partners_tour"):
|
38
50
|
with self.subTest(tour=tour):
|
39
|
-
self.start_tour("/", tour, login="portal")
|
51
|
+
self.start_tour("/my", tour, login="portal")
|
40
52
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
# Public user can access only the empty res.partner folder
|
51
|
-
self.directory_partner.with_user(self.public_user).invalidate_recordset()
|
52
|
-
self.assertFalse(
|
53
|
-
self.directory_partner.with_user(self.public_user).permission_read
|
54
|
-
)
|
55
|
-
self.directory_partner.parent_id.with_user(
|
56
|
-
self.public_user
|
57
|
-
).invalidate_recordset()
|
58
|
-
self.assertTrue(
|
59
|
-
self.directory_partner.parent_id.with_user(self.public_user).permission_read
|
53
|
+
@users("portal")
|
54
|
+
def test_permission_portal_user_access_own_attachment(self):
|
55
|
+
"""
|
56
|
+
The user can access its own attachments, even if its access group are not set
|
57
|
+
"""
|
58
|
+
# Has to manually su=False because the portal user is not a superuser,
|
59
|
+
# but odoo uses somewhere sudo() internally
|
60
|
+
file = self.file_partner.with_user(self.portal_user).with_env(
|
61
|
+
self.env(su=False)
|
60
62
|
)
|
61
|
-
self.
|
62
|
-
|
63
|
-
self.assertFalse(
|
64
|
-
self.directory_partner.parent_id.with_user(
|
65
|
-
self.public_user
|
66
|
-
).child_directory_ids
|
63
|
+
directory = self.directory_partner.with_user(self.portal_user).with_env(
|
64
|
+
self.env(su=False)
|
67
65
|
)
|
66
|
+
# Portal user can only read
|
67
|
+
file.check_access_rule("read")
|
68
|
+
|
69
|
+
# Portal user can't do anything else
|
70
|
+
with self.assertRaises(AccessError, msg="Portal user should not have access"):
|
71
|
+
file.check_access_rule("write")
|
72
|
+
file.check_access_rule("unlink")
|
73
|
+
directory.check_access_rule("create")
|
68
74
|
|
69
75
|
@users("portal")
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
self.
|
76
|
+
def test_permission_portal_user_access_other_attachment(self):
|
77
|
+
"""
|
78
|
+
The user can't access other attachments if its access group are not set
|
79
|
+
"""
|
80
|
+
# Has to manually su=False because the portal user is not a superuser,
|
81
|
+
# but odoo uses somewhere sudo() internally
|
82
|
+
file = self.other_file_partner.with_user(self.portal_user).with_env(
|
83
|
+
self.env(su=False)
|
78
84
|
)
|
85
|
+
# Portal user can't do anything
|
86
|
+
with self.assertRaises(AccessError, msg="Portal user should not have access"):
|
87
|
+
file.check_access_rule("read")
|
88
|
+
with self.assertRaises(AccessError, msg="Portal user should not have access"):
|
89
|
+
file.check_access_rule("write")
|
90
|
+
with self.assertRaises(AccessError, msg="Portal user should not have access"):
|
91
|
+
file.check_access_rule("unlink")
|