mirror of
https://github.com/bringout/oca-storage.git
synced 2026-04-19 08:32:01 +02:00
Initial commit: OCA Storage packages (17 packages)
This commit is contained in:
commit
7a380f05d3
659 changed files with 41828 additions and 0 deletions
|
|
@ -0,0 +1,82 @@
|
|||
==============
|
||||
Storage Bakend
|
||||
==============
|
||||
|
||||
..
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:e06faaef8e877cb770756ffc80fe1426d83d0130f6f1c239e9f16995156676ed
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Production/Stable
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
|
||||
:alt: License: LGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/storage/tree/16.0/storage_backend
|
||||
:alt: OCA/storage
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-storage_backend
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
|
||||
:target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=16.0
|
||||
:alt: Try me on Runboat
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/storage/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/storage/issues/new?body=module:%20storage_backend%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Akretion
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
* Raphaël Reverdy <raphael.reverdy@akretion.com>
|
||||
* Florian da Costa <florian.dacosta@akretion.com>
|
||||
* Cédric Pigeon <cedric.pigeon@acsone.eu>
|
||||
* Renato Lima <renato.lima@akretion.com>
|
||||
* Benoît Guillot <benoit.guillot@akretion.com>
|
||||
* Laurent Mignon <laurent.mignon@acsone.eu>
|
||||
* Denis Roussel <denis.roussel@acsone.eu>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
This module is part of the `OCA/storage <https://github.com/OCA/storage/tree/16.0/storage_backend>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
from . import models
|
||||
from . import components
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
{
|
||||
"name": "Storage Bakend",
|
||||
"summary": "Implement the concept of Storage with amazon S3, sftp...",
|
||||
"version": "16.0.1.1.0",
|
||||
"category": "Storage",
|
||||
"website": "https://github.com/OCA/storage",
|
||||
"author": " Akretion, Odoo Community Association (OCA)",
|
||||
"license": "LGPL-3",
|
||||
"development_status": "Production/Stable",
|
||||
"installable": True,
|
||||
"depends": ["base", "component", "server_environment"],
|
||||
"data": [
|
||||
"views/backend_storage_view.xml",
|
||||
"data/data.xml",
|
||||
"security/ir.model.access.csv",
|
||||
],
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
from . import base_adapter
|
||||
from . import filesystem_adapter
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
# Copyright 2020 ACSONE SA/NV (<http://acsone.eu>)
|
||||
# @author Simone Orsi <simahawk@gmail.com>
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from odoo.addons.component.core import AbstractComponent
|
||||
|
||||
|
||||
class BaseStorageAdapter(AbstractComponent):
|
||||
_name = "base.storage.adapter"
|
||||
_collection = "storage.backend"
|
||||
|
||||
def _fullpath(self, relative_path):
|
||||
dp = self.collection.directory_path
|
||||
if not dp or relative_path.startswith(dp):
|
||||
return relative_path
|
||||
return os.path.join(dp, relative_path)
|
||||
|
||||
def add(self, relative_path, data, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
def get(self, relative_path, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
def list(self, relative_path=""):
|
||||
raise NotImplementedError
|
||||
|
||||
def find_files(self, pattern, relative_path="", **kwargs):
|
||||
"""Find files matching given pattern.
|
||||
|
||||
:param pattern: regex expression
|
||||
:param relative_path: optional relative path containing files
|
||||
:return: list of file paths as full paths from the root
|
||||
"""
|
||||
regex = re.compile(pattern)
|
||||
filelist = self.list(relative_path)
|
||||
files_matching = [
|
||||
regex.match(file_).group() for file_ in filelist if regex.match(file_)
|
||||
]
|
||||
filepaths = []
|
||||
if files_matching:
|
||||
filepaths = [
|
||||
os.path.join(self._fullpath(relative_path) or "", filename)
|
||||
for filename in files_matching
|
||||
]
|
||||
return filepaths
|
||||
|
||||
def move_files(self, files, destination_path, **kwargs):
|
||||
"""Move files to given destination.
|
||||
|
||||
:param files: list of file paths to be moved
|
||||
:param destination_path: directory path where to move files
|
||||
:return: None
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def delete(self, relative_path):
|
||||
raise NotImplementedError
|
||||
|
||||
# You can define `validate_config` on your own adapter
|
||||
# to make validation button available on UI.
|
||||
# This method should simply pass smoothly when validation is ok,
|
||||
# otherwise it should raise an exception.
|
||||
# def validate_config(self):
|
||||
# raise NotImplementedError
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from odoo import _
|
||||
from odoo.exceptions import AccessError
|
||||
|
||||
from odoo.addons.component.core import Component
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def is_safe_path(basedir, path):
|
||||
return os.path.realpath(path).startswith(basedir)
|
||||
|
||||
|
||||
class FileSystemStorageBackend(Component):
|
||||
_name = "filesystem.adapter"
|
||||
_inherit = "base.storage.adapter"
|
||||
_usage = "filesystem"
|
||||
|
||||
def _basedir(self):
|
||||
return os.path.join(self.env["ir.attachment"]._filestore(), "storage")
|
||||
|
||||
def _fullpath(self, relative_path):
|
||||
"""This will build the full path for the file, we force to
|
||||
store the data inside the filestore in the directory 'storage".
|
||||
Becarefull if you implement your own custom path, end user
|
||||
should never be able to write or read unwanted filesystem file"""
|
||||
full_path = super(FileSystemStorageBackend, self)._fullpath(relative_path)
|
||||
base_dir = self._basedir()
|
||||
full_path = os.path.join(base_dir, full_path)
|
||||
if not is_safe_path(base_dir, full_path):
|
||||
raise AccessError(_("Access to %s is forbidden") % full_path)
|
||||
return full_path
|
||||
|
||||
def add(self, relative_path, data, **kwargs):
|
||||
full_path = self._fullpath(relative_path)
|
||||
dirname = os.path.dirname(full_path)
|
||||
if not os.path.isdir(dirname):
|
||||
os.makedirs(dirname)
|
||||
with open(full_path, "wb") as my_file:
|
||||
my_file.write(data)
|
||||
|
||||
def get(self, relative_path, **kwargs):
|
||||
full_path = self._fullpath(relative_path)
|
||||
with open(full_path, "rb") as my_file:
|
||||
data = my_file.read()
|
||||
return data
|
||||
|
||||
def list(self, relative_path=""):
|
||||
full_path = self._fullpath(relative_path)
|
||||
if os.path.isdir(full_path):
|
||||
return os.listdir(full_path)
|
||||
return []
|
||||
|
||||
def delete(self, relative_path):
|
||||
full_path = self._fullpath(relative_path)
|
||||
try:
|
||||
os.remove(full_path)
|
||||
except FileNotFoundError:
|
||||
_logger.warning("File not found in %s", full_path)
|
||||
|
||||
def move_files(self, files, destination_path):
|
||||
result = []
|
||||
for file_path in files:
|
||||
if not os.path.exists(destination_path):
|
||||
os.makedirs(destination_path)
|
||||
filename = os.path.basename(file_path)
|
||||
destination_file = os.path.join(destination_path, filename)
|
||||
result.append(shutil.move(file_path, destination_file))
|
||||
return result
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo noupdate="1">
|
||||
<record id="default_storage_backend" model="storage.backend">
|
||||
<field name="name">Filesystem Backend</field>
|
||||
<field name="backend_type">filesystem</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * storage_backend
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/components/filesystem_adapter.py:0
|
||||
#, python-format
|
||||
msgid "Access to %s is forbidden"
|
||||
msgstr "Pristup %s je zabranjen"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type
|
||||
msgid "Backend Type"
|
||||
msgstr "Tip pozadine"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_default
|
||||
msgid "Backend Type Env Default"
|
||||
msgstr "Zadano okruženje tipa pozadine"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_is_editable
|
||||
msgid "Backend Type Env Is Editable"
|
||||
msgstr "Tip pozadine okruženja se može uređivati"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Failed!"
|
||||
msgstr "Provjera povezivanja nije uspjela!"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Succeeded!"
|
||||
msgstr "Provjera povezivanja uspješna!"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Kreirao"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Kreirano"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path
|
||||
msgid "Directory Path"
|
||||
msgstr "Putanja direktorija"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Directory Path Env Default"
|
||||
msgstr "Zadano okruženje putanje direktorija"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_is_editable
|
||||
msgid "Directory Path Env Is Editable"
|
||||
msgstr "Putanja direktorija okruženja se može uređivati"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Prikazani naziv"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Everything seems properly set up!"
|
||||
msgstr "Sve izgleda ispravno postavljeno!"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields.selection,name:storage_backend.selection__storage_backend__backend_type__filesystem
|
||||
msgid "Filesystem"
|
||||
msgstr "Datotečni sustav"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__has_validation
|
||||
msgid "Has Validation"
|
||||
msgstr "Ima validaciju"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Zadnje mijenjano"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Zadnji ažurirao"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Zadnje ažurirano"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__name
|
||||
msgid "Name"
|
||||
msgstr "Naziv:"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Relative path to the directory to store the file"
|
||||
msgstr "Relativna putanja do direktorija za skladištenje datoteke"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__server_env_defaults
|
||||
msgid "Server Env Defaults"
|
||||
msgstr "Zadane vrijednosti server okruženja"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.actions.act_window,name:storage_backend.act_open_storage_backend_view
|
||||
#: model:ir.model,name:storage_backend.model_storage_backend
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_search
|
||||
msgid "Storage Backend"
|
||||
msgstr "Pozadina skladištenja"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
msgid "Test connection"
|
||||
msgstr "Testiraj vezu"
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * storage_backend
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2023-10-29 00:15+0000\n"
|
||||
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.17\n"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/components/filesystem_adapter.py:0
|
||||
#, python-format
|
||||
msgid "Access to %s is forbidden"
|
||||
msgstr "El acceso a %s está prohibido"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type
|
||||
msgid "Backend Type"
|
||||
msgstr "Tipo de servidor"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_default
|
||||
msgid "Backend Type Env Default"
|
||||
msgstr "Tipo de servidor Ent Por defecto"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_is_editable
|
||||
msgid "Backend Type Env Is Editable"
|
||||
msgstr "El Tipo de Entorno del Servidor es Editable"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Failed!"
|
||||
msgstr "¡Error en la Prueba de Conexión!"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Succeeded!"
|
||||
msgstr "¡Conexión de Prueba Exitosa!"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creado por"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creado el"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path
|
||||
msgid "Directory Path"
|
||||
msgstr "Ruta del Directorio"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Directory Path Env Default"
|
||||
msgstr "Ruta del Directorio Ent Predet"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_is_editable
|
||||
msgid "Directory Path Env Is Editable"
|
||||
msgstr "El Entorno de Ruta del Directorio es Editable"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Mostrar Nombre"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Everything seems properly set up!"
|
||||
msgstr "¡Todo parece correctamente configurado!"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields.selection,name:storage_backend.selection__storage_backend__backend_type__filesystem
|
||||
msgid "Filesystem"
|
||||
msgstr "Sistema de archivos"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__has_validation
|
||||
msgid "Has Validation"
|
||||
msgstr "Tiene Validación"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__id
|
||||
msgid "ID"
|
||||
msgstr "ID(identificación)"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Última Modifiación el"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Última Actualización por"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Última Actualización el"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__name
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Relative path to the directory to store the file"
|
||||
msgstr "Ruta relativa al directorio para almacenar el archivo"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__server_env_defaults
|
||||
msgid "Server Env Defaults"
|
||||
msgstr "Valores por defecto del Entorno de Servidor"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.actions.act_window,name:storage_backend.act_open_storage_backend_view
|
||||
#: model:ir.model,name:storage_backend.model_storage_backend
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_search
|
||||
msgid "Storage Backend"
|
||||
msgstr "Servidor de Almacenamiento"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
msgid "Test connection"
|
||||
msgstr "Probar conexión"
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * storage_backend
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-06-03 09:25+0000\n"
|
||||
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.10.4\n"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/components/filesystem_adapter.py:0
|
||||
#, python-format
|
||||
msgid "Access to %s is forbidden"
|
||||
msgstr "L'accesso a %s è vietato"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type
|
||||
msgid "Backend Type"
|
||||
msgstr "Tipo backend"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_default
|
||||
msgid "Backend Type Env Default"
|
||||
msgstr "Tipo backend ambiente predefinito"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_is_editable
|
||||
msgid "Backend Type Env Is Editable"
|
||||
msgstr "Il tipo backend ambiente è modificabile"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Failed!"
|
||||
msgstr "Test connessione fallito!"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Succeeded!"
|
||||
msgstr "Test connessione avvenuto con successo!"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creato da"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creato il"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path
|
||||
msgid "Directory Path"
|
||||
msgstr "Percorso cartella"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Directory Path Env Default"
|
||||
msgstr "Percorso cartella ambiente predefinito"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_is_editable
|
||||
msgid "Directory Path Env Is Editable"
|
||||
msgstr "Percorso cartella ambiente è modificabile"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nome visualizzato"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Everything seems properly set up!"
|
||||
msgstr "Tutto sembra impostato correttamente!"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields.selection,name:storage_backend.selection__storage_backend__backend_type__filesystem
|
||||
msgid "Filesystem"
|
||||
msgstr "Filesystem"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__has_validation
|
||||
msgid "Has Validation"
|
||||
msgstr "Ha validazione"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Ultima modifica il"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Ultimo aggiornamento di"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Ultimo aggiornamento il"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__name
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Relative path to the directory to store the file"
|
||||
msgstr "Percorso relativo alla cartella per archiviare il file"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__server_env_defaults
|
||||
msgid "Server Env Defaults"
|
||||
msgstr "Predefiniti ambiente server"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.actions.act_window,name:storage_backend.act_open_storage_backend_view
|
||||
#: model:ir.model,name:storage_backend.model_storage_backend
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_search
|
||||
msgid "Storage Backend"
|
||||
msgstr "Backend deposito"
|
||||
|
||||
#. module: storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
msgid "Test connection"
|
||||
msgstr "Prova connessione"
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * storage_backend
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/components/filesystem_adapter.py:0
|
||||
#, python-format
|
||||
msgid "Access to %s is forbidden"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type
|
||||
msgid "Backend Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_default
|
||||
msgid "Backend Type Env Default"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__backend_type_env_is_editable
|
||||
msgid "Backend Type Env Is Editable"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Failed!"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Connection Test Succeeded!"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path
|
||||
msgid "Directory Path"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Directory Path Env Default"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__directory_path_env_is_editable
|
||||
msgid "Directory Path Env Is Editable"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#. odoo-python
|
||||
#: code:addons/storage_backend/models/storage_backend.py:0
|
||||
#, python-format
|
||||
msgid "Everything seems properly set up!"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields.selection,name:storage_backend.selection__storage_backend__backend_type__filesystem
|
||||
msgid "Filesystem"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__has_validation
|
||||
msgid "Has Validation"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__name
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path
|
||||
#: model:ir.model.fields,help:storage_backend.field_storage_backend__directory_path_env_default
|
||||
msgid "Relative path to the directory to store the file"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.model.fields,field_description:storage_backend.field_storage_backend__server_env_defaults
|
||||
msgid "Server Env Defaults"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model:ir.actions.act_window,name:storage_backend.act_open_storage_backend_view
|
||||
#: model:ir.model,name:storage_backend.model_storage_backend
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage
|
||||
#: model:ir.ui.menu,name:storage_backend.menu_storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_search
|
||||
msgid "Storage Backend"
|
||||
msgstr ""
|
||||
|
||||
#. module: storage_backend
|
||||
#: model_terms:ir.ui.view,arch_db:storage_backend.storage_backend_view_form
|
||||
msgid "Test connection"
|
||||
msgstr ""
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import storage_backend
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# Copyright 2019 Camptocamp SA (http://www.camptocamp.com).
|
||||
# @author Simone Orsi <simone.orsi@camptocamp.com>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
import base64
|
||||
import fnmatch
|
||||
import functools
|
||||
import inspect
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
from odoo import _, fields, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO: useful for the whole OCA?
|
||||
def deprecated(reason):
|
||||
"""Mark functions or classes as deprecated.
|
||||
|
||||
Emit warning at execution.
|
||||
|
||||
The @deprecated is used with a 'reason'.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@deprecated("please, use another function")
|
||||
def old_function(x, y):
|
||||
pass
|
||||
"""
|
||||
|
||||
def decorator(func1):
|
||||
|
||||
if inspect.isclass(func1):
|
||||
fmt1 = "Call to deprecated class {name} ({reason})."
|
||||
else:
|
||||
fmt1 = "Call to deprecated function {name} ({reason})."
|
||||
|
||||
@functools.wraps(func1)
|
||||
def new_func1(*args, **kwargs):
|
||||
warnings.simplefilter("always", DeprecationWarning)
|
||||
warnings.warn(
|
||||
fmt1.format(name=func1.__name__, reason=reason),
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
warnings.simplefilter("default", DeprecationWarning)
|
||||
return func1(*args, **kwargs)
|
||||
|
||||
return new_func1
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class StorageBackend(models.Model):
|
||||
_name = "storage.backend"
|
||||
_inherit = ["collection.base", "server.env.mixin"]
|
||||
_backend_name = "storage_backend"
|
||||
_description = "Storage Backend"
|
||||
|
||||
name = fields.Char(required=True)
|
||||
backend_type = fields.Selection(
|
||||
selection=[("filesystem", "Filesystem")], required=True, default="filesystem"
|
||||
)
|
||||
directory_path = fields.Char(
|
||||
help="Relative path to the directory to store the file"
|
||||
)
|
||||
has_validation = fields.Boolean(compute="_compute_has_validation")
|
||||
|
||||
def _compute_has_validation(self):
|
||||
for rec in self:
|
||||
if not rec.backend_type:
|
||||
# with server_env
|
||||
# this code can be triggered
|
||||
# before a backend_type has been set
|
||||
# get_adapter() can't work without backend_type
|
||||
rec.has_validation = False
|
||||
continue
|
||||
adapter = rec._get_adapter()
|
||||
rec.has_validation = hasattr(adapter, "validate_config")
|
||||
|
||||
@property
|
||||
def _server_env_fields(self):
|
||||
return {"backend_type": {}, "directory_path": {}}
|
||||
|
||||
def add(self, relative_path, data, binary=True, **kwargs):
|
||||
if not binary:
|
||||
data = base64.b64decode(data)
|
||||
return self._forward("add", relative_path, data, **kwargs)
|
||||
|
||||
@deprecated("Use `add`")
|
||||
def _add_bin_data(self, relative_path, data, **kwargs):
|
||||
return self.add(relative_path, data, **kwargs)
|
||||
|
||||
@deprecated("Use `add` with `binary=False`")
|
||||
def _add_b64_data(self, relative_path, data, **kwargs):
|
||||
return self.add(relative_path, data, binary=False, **kwargs)
|
||||
|
||||
def get(self, relative_path, binary=True, **kwargs):
|
||||
data = self._forward("get", relative_path, **kwargs)
|
||||
if not binary and data:
|
||||
data = base64.b64encode(data)
|
||||
return data
|
||||
|
||||
@deprecated("Use `get` with `binary=False`")
|
||||
def _get_b64_data(self, relative_path, **kwargs):
|
||||
return self.get(relative_path, binary=False, **kwargs)
|
||||
|
||||
@deprecated("Use `get`")
|
||||
def _get_bin_data(self, relative_path, **kwargs):
|
||||
return self.get(relative_path, **kwargs)
|
||||
|
||||
def list_files(self, relative_path="", pattern=False):
|
||||
names = self._forward("list", relative_path)
|
||||
if pattern:
|
||||
names = fnmatch.filter(names, pattern)
|
||||
return names
|
||||
|
||||
@deprecated("Use `list_files`")
|
||||
def _list(self, relative_path="", pattern=False):
|
||||
return self.list_files(relative_path, pattern=pattern)
|
||||
|
||||
def find_files(self, pattern, relative_path="", **kw):
|
||||
return self._forward("find_files", pattern, relative_path=relative_path)
|
||||
|
||||
@deprecated("Use `find_files`")
|
||||
def _find_files(self, pattern, relative_path="", **kw):
|
||||
return self.find_files(pattern, relative_path=relative_path, **kw)
|
||||
|
||||
def move_files(self, files, destination_path, **kw):
|
||||
return self._forward("move_files", files, destination_path, **kw)
|
||||
|
||||
@deprecated("Use `move_files`")
|
||||
def _move_files(self, files, destination_path, **kw):
|
||||
return self.move_files(files, destination_path, **kw)
|
||||
|
||||
def delete(self, relative_path):
|
||||
return self._forward("delete", relative_path)
|
||||
|
||||
@deprecated("Use `delete`")
|
||||
def _delete(self, relative_path):
|
||||
return self.delete(relative_path)
|
||||
|
||||
def _forward(self, method, *args, **kwargs):
|
||||
_logger.debug(
|
||||
"Backend Storage ID: %s type %s: %s file %s %s",
|
||||
self.backend_type,
|
||||
self.id,
|
||||
method,
|
||||
args,
|
||||
kwargs,
|
||||
)
|
||||
self.ensure_one()
|
||||
adapter = self._get_adapter()
|
||||
return getattr(adapter, method)(*args, **kwargs)
|
||||
|
||||
def _get_adapter(self):
|
||||
with self.work_on(self._name) as work:
|
||||
return work.component(usage=self.backend_type)
|
||||
|
||||
def action_test_config(self):
|
||||
if not self.has_validation:
|
||||
raise AttributeError("Validation not supported!")
|
||||
adapter = self._get_adapter()
|
||||
try:
|
||||
adapter.validate_config()
|
||||
title = _("Connection Test Succeeded!")
|
||||
message = _("Everything seems properly set up!")
|
||||
msg_type = "success"
|
||||
except Exception as err:
|
||||
title = _("Connection Test Failed!")
|
||||
message = str(err)
|
||||
msg_type = "danger"
|
||||
return {
|
||||
"type": "ir.actions.client",
|
||||
"tag": "display_notification",
|
||||
"params": {
|
||||
"title": title,
|
||||
"message": message,
|
||||
"type": msg_type,
|
||||
"sticky": False,
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
* Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
* Raphaël Reverdy <raphael.reverdy@akretion.com>
|
||||
* Florian da Costa <florian.dacosta@akretion.com>
|
||||
* Cédric Pigeon <cedric.pigeon@acsone.eu>
|
||||
* Renato Lima <renato.lima@akretion.com>
|
||||
* Benoît Guillot <benoit.guillot@akretion.com>
|
||||
* Laurent Mignon <laurent.mignon@acsone.eu>
|
||||
* Denis Roussel <denis.roussel@acsone.eu>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_storage_backend_edit,storage_backend edit,model_storage_backend,base.group_system,1,1,1,1
|
||||
|
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
|
|
@ -0,0 +1,429 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
|
||||
<title>Storage Bakend</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
Despite the name, some widely supported CSS2 features are used.
|
||||
|
||||
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: gray; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic, pre.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="storage-bakend">
|
||||
<h1 class="title">Storage Bakend</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:e06faaef8e877cb770756ffc80fe1426d83d0130f6f1c239e9f16995156676ed
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/storage/tree/16.0/storage_backend"><img alt="OCA/storage" src="https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-storage_backend"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/storage/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/storage/issues/new?body=module:%20storage_backend%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Akretion</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Sébastien BEAU <<a class="reference external" href="mailto:sebastien.beau@akretion.com">sebastien.beau@akretion.com</a>></li>
|
||||
<li>Raphaël Reverdy <<a class="reference external" href="mailto:raphael.reverdy@akretion.com">raphael.reverdy@akretion.com</a>></li>
|
||||
<li>Florian da Costa <<a class="reference external" href="mailto:florian.dacosta@akretion.com">florian.dacosta@akretion.com</a>></li>
|
||||
<li>Cédric Pigeon <<a class="reference external" href="mailto:cedric.pigeon@acsone.eu">cedric.pigeon@acsone.eu</a>></li>
|
||||
<li>Renato Lima <<a class="reference external" href="mailto:renato.lima@akretion.com">renato.lima@akretion.com</a>></li>
|
||||
<li>Benoît Guillot <<a class="reference external" href="mailto:benoit.guillot@akretion.com">benoit.guillot@akretion.com</a>></li>
|
||||
<li>Laurent Mignon <<a class="reference external" href="mailto:laurent.mignon@acsone.eu">laurent.mignon@acsone.eu</a>></li>
|
||||
<li>Denis Roussel <<a class="reference external" href="mailto:denis.roussel@acsone.eu">denis.roussel@acsone.eu</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org">
|
||||
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
|
||||
</a>
|
||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/storage/tree/16.0/storage_backend">OCA/storage</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
from . import common
|
||||
from . import test_filesystem
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
import base64
|
||||
from unittest import mock
|
||||
|
||||
from odoo.addons.component.tests.common import TransactionComponentCase
|
||||
|
||||
|
||||
class BackendStorageTestMixin(object):
|
||||
def _test_setting_and_getting_data(self):
|
||||
# Check that the directory is empty
|
||||
files = self.backend.list_files()
|
||||
self.assertNotIn(self.filename, files)
|
||||
|
||||
# Add a new file
|
||||
self.backend.add(
|
||||
self.filename, self.filedata, mimetype="text/plain", binary=False
|
||||
)
|
||||
|
||||
# Check that the file exist
|
||||
files = self.backend.list_files()
|
||||
self.assertIn(self.filename, files)
|
||||
|
||||
# Retrieve the file added
|
||||
data = self.backend.get(self.filename, binary=False)
|
||||
self.assertEqual(data, self.filedata)
|
||||
|
||||
# Delete the file
|
||||
self.backend.delete(self.filename)
|
||||
files = self.backend.list_files()
|
||||
self.assertNotIn(self.filename, files)
|
||||
|
||||
def _test_setting_and_getting_data_from_root(self):
|
||||
self._test_setting_and_getting_data()
|
||||
|
||||
def _test_setting_and_getting_data_from_dir(self):
|
||||
self.backend.directory_path = self.case_with_subdirectory
|
||||
self._test_setting_and_getting_data()
|
||||
|
||||
def _test_find_files(
|
||||
self,
|
||||
backend,
|
||||
adapter_dotted_path,
|
||||
mocked_filepaths,
|
||||
pattern,
|
||||
expected_filepaths,
|
||||
):
|
||||
with mock.patch(adapter_dotted_path + ".list") as mocked:
|
||||
mocked.return_value = mocked_filepaths
|
||||
res = backend.find_files(pattern)
|
||||
self.assertEqual(sorted(res), sorted(expected_filepaths))
|
||||
|
||||
def _test_move_files(
|
||||
self,
|
||||
backend,
|
||||
adapter_dotted_path,
|
||||
filename,
|
||||
destination_path,
|
||||
expected_filepaths,
|
||||
):
|
||||
with mock.patch(adapter_dotted_path + ".move_files") as mocked:
|
||||
mocked.return_value = expected_filepaths
|
||||
res = backend.move_files(filename, destination_path)
|
||||
self.assertEqual(sorted(res), sorted(expected_filepaths))
|
||||
|
||||
|
||||
class CommonCase(TransactionComponentCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
cls.backend = cls.env.ref("storage_backend.default_storage_backend")
|
||||
cls.filedata = base64.b64encode(b"This is a simple file")
|
||||
cls.filename = "test_file.txt"
|
||||
cls.case_with_subdirectory = "subdirectory/here"
|
||||
cls.demo_user = cls.env.ref("base.user_demo")
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
import os
|
||||
|
||||
from odoo.exceptions import AccessError
|
||||
|
||||
from .common import BackendStorageTestMixin, CommonCase
|
||||
|
||||
ADAPTER_PATH = (
|
||||
"odoo.addons.storage_backend.components.filesystem_adapter.FileSystemStorageBackend"
|
||||
)
|
||||
|
||||
|
||||
class FileSystemCase(CommonCase, BackendStorageTestMixin):
|
||||
def test_setting_and_getting_data_from_root(self):
|
||||
self._test_setting_and_getting_data_from_root()
|
||||
|
||||
def test_setting_and_getting_data_from_dir(self):
|
||||
self._test_setting_and_getting_data_from_dir()
|
||||
|
||||
def test_find_files(self):
|
||||
good_filepaths = ["somepath/file%d.good" % x for x in range(1, 10)]
|
||||
bad_filepaths = ["somepath/file%d.bad" % x for x in range(1, 10)]
|
||||
mocked_filepaths = bad_filepaths + good_filepaths
|
||||
backend = self.backend.sudo()
|
||||
base_dir = backend._get_adapter()._basedir()
|
||||
expected = [base_dir + "/" + path for path in good_filepaths]
|
||||
self._test_find_files(
|
||||
backend, ADAPTER_PATH, mocked_filepaths, r".*\.good$", expected
|
||||
)
|
||||
|
||||
def test_move_files(self):
|
||||
backend = self.backend.sudo()
|
||||
base_dir = backend._get_adapter()._basedir()
|
||||
expected = [base_dir + "/" + self.filename]
|
||||
destination_path = os.path.join(base_dir, "destination")
|
||||
self._test_move_files(
|
||||
backend, ADAPTER_PATH, self.filename, destination_path, expected
|
||||
)
|
||||
|
||||
|
||||
class FileSystemDemoUserAccessCase(CommonCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.backend = cls.backend.with_user(cls.demo_user)
|
||||
|
||||
def test_cannot_add_file(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.backend.add(
|
||||
self.filename, self.filedata, mimetype="text/plain", binary=False
|
||||
)
|
||||
|
||||
def test_cannot_list_file(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.backend.list_files()
|
||||
|
||||
def test_cannot_read_file(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.backend.get(self.filename, binary=False)
|
||||
|
||||
def test_cannot_delete_file(self):
|
||||
with self.assertRaises(AccessError):
|
||||
self.backend.delete(self.filename)
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="storage_backend_view_tree" model="ir.ui.view">
|
||||
<field name="model">storage.backend</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
<field name="backend_type" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="storage_backend_view_form" model="ir.ui.view">
|
||||
<field name="model">storage.backend</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Storage Backend">
|
||||
<header>
|
||||
<field name="has_validation" invisible="1" />
|
||||
<button
|
||||
type="object"
|
||||
name="action_test_config"
|
||||
string="Test connection"
|
||||
attrs="{'invisible': [('has_validation', '=', False)]}"
|
||||
/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only" />
|
||||
<h1>
|
||||
<field name="name" />
|
||||
</h1>
|
||||
</div>
|
||||
<group name="config">
|
||||
<field name="backend_type" />
|
||||
<field name="directory_path" />
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="storage_backend_view_search" model="ir.ui.view">
|
||||
<field name="model">storage.backend</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Storage Backend">
|
||||
<field name="name" />
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window" id="act_open_storage_backend_view">
|
||||
<field name="name">Storage Backend</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">storage.backend</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="storage_backend_view_search" />
|
||||
<field name="domain">[]</field>
|
||||
<field name="context">{}</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="act_open_storage_backend_view_form">
|
||||
<field name="act_window_id" ref="act_open_storage_backend_view" />
|
||||
<field name="sequence" eval="20" />
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="storage_backend_view_form" />
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="act_open_storage_backend_view_tree">
|
||||
<field name="act_window_id" ref="act_open_storage_backend_view" />
|
||||
<field name="sequence" eval="10" />
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="storage_backend_view_tree" />
|
||||
</record>
|
||||
<menuitem
|
||||
id="menu_storage"
|
||||
parent="base.menu_custom"
|
||||
sequence="100"
|
||||
action="act_open_storage_backend_view"
|
||||
/>
|
||||
<menuitem
|
||||
id="menu_storage_backend"
|
||||
parent="menu_storage"
|
||||
sequence="10"
|
||||
action="act_open_storage_backend_view"
|
||||
/>
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue