diff --git a/README.md b/README.md index df694981e5..92de52a2b5 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ addon | version | maintainers | summary [users_ldap_groups](users_ldap_groups/) | 16.0.1.0.0 | | Adds user accounts to groups based on rules defined by the administrator. [users_ldap_mail](users_ldap_mail/) | 16.0.1.0.0 | [![joao-p-marques](https://github.com/joao-p-marques.png?size=30px)](https://github.com/joao-p-marques) | LDAP mapping for user name and e-mail [users_ldap_populate](users_ldap_populate/) | 16.0.1.0.0 | [![joao-p-marques](https://github.com/joao-p-marques.png?size=30px)](https://github.com/joao-p-marques) | LDAP Populate +[vault](vault/) | 16.0.1.0.0 | | Password vault integration in Odoo [//]: # (end addons) diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt index 9a0109d4fb..ef64b9af1c 100644 --- a/setup/_metapackage/VERSION.txt +++ b/setup/_metapackage/VERSION.txt @@ -1 +1 @@ -16.0.20231219.0 \ No newline at end of file +16.0.20240222.0 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py index 45298261ac..e0acedec55 100644 --- a/setup/_metapackage/setup.py +++ b/setup/_metapackage/setup.py @@ -28,6 +28,7 @@ 'odoo-addon-users_ldap_groups>=16.0dev,<16.1dev', 'odoo-addon-users_ldap_mail>=16.0dev,<16.1dev', 'odoo-addon-users_ldap_populate>=16.0dev,<16.1dev', + 'odoo-addon-vault>=16.0dev,<16.1dev', ], classifiers=[ 'Programming Language :: Python', diff --git a/setup/vault/odoo/addons/vault b/setup/vault/odoo/addons/vault new file mode 120000 index 0000000000..4ead31e201 --- /dev/null +++ b/setup/vault/odoo/addons/vault @@ -0,0 +1 @@ +../../../../vault \ No newline at end of file diff --git a/setup/vault/setup.py b/setup/vault/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/vault/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/vault/README.rst b/vault/README.rst new file mode 100644 index 0000000000..e58d1e5c71 --- /dev/null +++ b/vault/README.rst @@ -0,0 +1,100 @@ +===== +Vault +===== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:12d8822aab453f4a6f00d8151ec6cdef4c66ec07c08d88e6528c85f3526d0818 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github + :target: https://github.com/OCA/server-auth/tree/16.0/vault + :alt: OCA/server-auth +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-auth-16-0/server-auth-16-0-vault + :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/server-auth&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module implements a vault for secrets and files using end-to-end-encryption. The encryption and decryption happens in the browser using a vault specific shared master key. The master keys are encrypted using asymmetrically. For this the user has to enter a second password on the first login or if he needs to access data in a vault. The asymmetric keys are stored for a certain time in the browser storage. + +The server can never access the secrets with the information available. Only people registered in the vault can decrypt or encrypt values in a vault. The meta data isn't encrypted to be able to search/filter for entries more easily. + +This modules requires a secure context for the browser to work properly and therefore HTTPS support is required. + +The `vault-recovery `_ project focuses on disaster recovery in case of an incident to recover secrets from old database backups or old exports. + +**Table of contents** + +.. contents:: + :local: + +Known issues / Roadmap +====================== + +* Field and file history for restoration + +* Import improvement + + * Support challenge-response/FIDO2 + * Support for argon2 and kdbx v4 + +* When changing an entry from one vault to another existing vault, the values added on + this entry cannot be accessed, so the field vault is going to be readonly when it + is defined. + + If you want to move entries between vaults you can use the export -> import option. + +* HTTPS or localhost (secure browser context) is required for the client side encryption + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* initOS GmbH + +Contributors +~~~~~~~~~~~~ + +* Florian Kantelberg + +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/server-auth `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/vault/TECHNICAL.rst b/vault/TECHNICAL.rst new file mode 100644 index 0000000000..4a5456445d --- /dev/null +++ b/vault/TECHNICAL.rst @@ -0,0 +1,143 @@ +:: + + ┌───────┐ ┏━━━━━━━━━━━━━┓ ╔═══════════╗ + │ input │ ┃ unencrypted ┃ ║ encrypted ║ + └───────┘ ┗━━━━━━━━━━━━━┛ ╚═══════════╝ + +Vault +===== + +Each vault stores entries with enrypted fields and files in a tree like structure. The access is controlled per vault. Every added user can read the secrets of a vault. Otherwise the users can receive permission to share the vault with other users, to write secrets in the vault, or to delete entries of the vault. The databases stores the public and password protected private key of each user. The password used for the private key is derived from a password entered by the user and should be different than the password used for the login. Keep in mind that the meta information like field name or file names aren't encrypted. + +Shared-key encryption +===================== + +To be able to securely share sensitive data between all users a shared-key encryption is used. All users share a common secret for each vault. This secret is encrypted by the public key of each user to grant access to the user by using the private key to restore the secret. + +Encryption of master key +------------------------ + +:: + + . ┏━━━━━━━━━━━━┓ + ┃ Master key ┃ + ┗━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━━━━━┓ ┃ + ┃ User ┃ ▼ + ┃ ┃ ┏━━━━━━━━━┓ + ┃ ┏━━━━━━━━━━━━━┓ ┃ ┃ encrypt ┃ ╔════════════╗ + ┃ ┃ Public key ┃━━━━▶┃ (RSA) ┃━━━━━▶║ Master key ║ + ┃ ┗━━━━━━━━━━━━━┛ ┃ ┗━━━━━━━━━┛ ╚════════════╝ + ┃ ╔═════════════╗ ┃ + ┃ ║ Private key ║ ┃ + ┃ ╚═════════════╝ ┃ + ┗━━━━━━━━━━━━━━━━━┛ + +Decryption of master key +------------------------ + +:: + + . ┌──────────┐ ┏━━━━━━━━━━┓ + │ Password │━━━━▶┃ derive ┃ + └──────────┘ ┃ (PBKDF2) ┃ + ┗━━━━━━━━━━┛ + ┃ + ┏━━━━━━━━━━━━━━━━━┓ ▼ ╔════════════╗ + ┃ User ┃ ┏━━━━━━━━━━┓ ║ Master key ║ + ┃ ┃ ┃ Password ┃ ╚════════════╝ + ┃ ┏━━━━━━━━━━━━━┓ ┃ ┗━━━━━━━━━━┛ ┃ + ┃ ┃ Public key ┃ ┃ ┃ ▼ + ┃ ┗━━━━━━━━━━━━━┛ ┃ ▼ ┏━━━━━━━━━┓ + ┃ ╔═════════════╗ ┃ ┏━━━━━━━━┓ ┏━━━━━━━━━━━━━┓ ┃ decrypt ┃ ┏━━━━━━━━━━━━┓ + ┃ ║ Private key ║━━━━━┃ unlock ┃━━▶┃ Private key ┃━━━▶┃ (RSA) ┃━━━━━▶┃ Master key ┃ + ┃ ╚═════════════╝ ┃ ┗━━━━━━━━┛ ┗━━━━━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━┛ + ┗━━━━━━━━━━━━━━━━━┛ + +Symmetric encryption of the data +================================ + +The symmetric cipher AES is used with the common master key to encrypt/decrypt the secrets of the vaults. The encryption parameter and encrypted data is stored in the database while everything else happens in the browser. + +Encryption of data +------------------ + +:: + + . ┏━━━━━━━━━━━━┓ + ┃ Master key ┃ + ┗━━━━━━━━━━━━┛ + ┃ ┏━━━━━━━━━━━━━━━━━━┓ + ▼ ┃ Database ┃ + ┏━━━━━━━━━┓ ┃ ┃ + ┏━━━━━━━━━━━━┓ ┃ encrypt ┃ ┃╔════════════════╗┃ + ┃ Plain text ┃━━▶┃ (AES) ┃━━━▶║ Encrypted data ║┃ + ┗━━━━━━━━━━━━┛ ┗━━━━━━━━━┛ ┃╚════════════════╝┃ + ┃ ┃┏━━━━━━━━━━━━━━━━┓┃ + ┗━━━━━━━━▶┃ Parameters ┃┃ + ┃┗━━━━━━━━━━━━━━━━┛┃ + ┗━━━━━━━━━━━━━━━━━━┛ + +Decryption of data +------------------ + +:: + + . ┏━━━━━━━━━━━━┓ + ┃ Master key ┃ + ┗━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━━━━━━┓ ┃ + ┃ Database ┃ ▼ + ┃ ┃ ┏━━━━━━━━━┓ + ┃╔════════════════╗┃ ┃ decrypt ┃ ┏━━━━━━━━━━━━┓ + ┃║ Encrypted data ║━━━▶┃ (AES) ┃━━▶┃ Plain text ┃ + ┃╚════════════════╝┃ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━┛ + ┃┏━━━━━━━━━━━━━━━━┓┃ ▲ + ┃┃ Parameters ┃━━━━━━━━┛ + ┃┗━━━━━━━━━━━━━━━━┛┃ + ┗━━━━━━━━━━━━━━━━━━┛ + +Inbox +===== + +This allows an user to receive encrypted secrets by external or internal Odoo users. External users have to use either the owner specific inbox link from his preferences or the link of an already created inbox. The value is symmetrically encrypted. The key for the encryption is wrapped with the public key of the user of the inbox to grant the user the access to the key. Internal users can directly send a secret from a vault entry to another user who has enabled this feature. If a direct link is used the access counter and expiration time can block an overwrite. + +Encryption of inbox +------------------- + +:: + + . ┏━━━━━━━━━━━━┓ + ┃ Plain data ┃ + ┗━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━━━━━┓ ┃ + ┃ User ┃ ▼ + ┃ ┃ ┏━━━━━━━━━┓ + ┃ ┏━━━━━━━━━━━━━┓ ┃ ┃ encrypt ┃ ╔════════════════╗ + ┃ ┃ Public key ┃━━━━▶┃ (RSA) ┃━━━━━▶║ Encrypted data ║ + ┃ ┗━━━━━━━━━━━━━┛ ┃ ┗━━━━━━━━━┛ ╚════════════════╝ + ┃ ╔═════════════╗ ┃ + ┃ ║ Private key ║ ┃ + ┃ ╚═════════════╝ ┃ + ┗━━━━━━━━━━━━━━━━━┛ + +Decryption of inbox +------------------- + +:: + + . ┌──────────┐ ┏━━━━━━━━━━┓ + │ Password │━━━━▶┃ derive ┃ + └──────────┘ ┃ (PBKDF2) ┃ + ┗━━━━━━━━━━┛ + ┃ + ┏━━━━━━━━━━━━━━━━━┓ ▼ ╔════════════════╗ + ┃ User ┃ ┏━━━━━━━━━━┓ ║ Encrypted data ║ + ┃ ┃ ┃ Password ┃ ╚════════════════╝ + ┃ ┏━━━━━━━━━━━━━┓ ┃ ┗━━━━━━━━━━┛ ┃ + ┃ ┃ Public key ┃ ┃ ┃ ▼ + ┃ ┗━━━━━━━━━━━━━┛ ┃ ▼ ┏━━━━━━━━━┓ + ┃ ╔═════════════╗ ┃ ┏━━━━━━━━┓ ┏━━━━━━━━━━━━━┓ ┃ decrypt ┃ ┏━━━━━━━━━━━━┓ + ┃ ║ Private key ║━━━━━┃ unlock ┃━━▶┃ Private key ┃━━━▶┃ (RSA) ┃━━━━━▶┃ Plain data ┃ + ┃ ╚═════════════╝ ┃ ┗━━━━━━━━┛ ┗━━━━━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━┛ + ┗━━━━━━━━━━━━━━━━━┛ diff --git a/vault/__init__.py b/vault/__init__.py new file mode 100644 index 0000000000..843ac90a95 --- /dev/null +++ b/vault/__init__.py @@ -0,0 +1,4 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import controllers, models, wizards diff --git a/vault/__manifest__.py b/vault/__manifest__.py new file mode 100644 index 0000000000..e3cfda3f64 --- /dev/null +++ b/vault/__manifest__.py @@ -0,0 +1,50 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Vault", + "summary": "Password vault integration in Odoo", + "license": "AGPL-3", + "version": "16.0.1.0.0", + "website": "https://github.com/OCA/server-auth", + "application": True, + "author": "initOS GmbH, Odoo Community Association (OCA)", + "category": "Vault", + "depends": ["base_setup", "web"], + "data": [ + "security/ir.model.access.csv", + "security/ir_rule.xml", + "security/vault_security.xml", + "views/res_config_settings_views.xml", + "views/res_users_views.xml", + "views/vault_entry_views.xml", + "views/vault_field_views.xml", + "views/vault_file_views.xml", + "views/vault_log_views.xml", + "views/vault_inbox_views.xml", + "views/vault_right_views.xml", + "views/vault_views.xml", + "views/menuitems.xml", + "views/templates.xml", + "wizards/vault_export_wizard.xml", + "wizards/vault_import_wizard.xml", + "wizards/vault_send_wizard.xml", + "wizards/vault_store_wizard.xml", + ], + "assets": { + "vault.assets_frontend": [ + "vault/static/src/common/*.js", + "vault/static/src/frontend/*.js", + ], + "web.assets_backend": [ + "vault/static/lib/**/*.min.js", + "vault/static/src/**/*.xml", + "vault/static/src/common/*.js", + "vault/static/src/backend/*.scss", + "vault/static/src/backend/**/*.js", + ], + "web.tests_assets": [ + "vault/static/tests/**/*.js", + ], + }, +} diff --git a/vault/controllers/__init__.py b/vault/controllers/__init__.py new file mode 100644 index 0000000000..aabfa83edd --- /dev/null +++ b/vault/controllers/__init__.py @@ -0,0 +1,4 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import main diff --git a/vault/controllers/main.py b/vault/controllers/main.py new file mode 100644 index 0000000000..1ca361dda3 --- /dev/null +++ b/vault/controllers/main.py @@ -0,0 +1,152 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, http +from odoo.exceptions import AccessDenied +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class Controller(http.Controller): + @http.route("/vault/inbox/", type="http", auth="public") + def vault_inbox(self, token): + ctx = {"disable_footer": True, "token": token} + # Find the right token + inbox = request.env["vault.inbox"].sudo().find_inbox(token) + user = request.env["res.users"].sudo().find_user_of_inbox(token) + if len(inbox) == 1 and inbox.accesses > 0: + ctx.update({"name": inbox.name, "public": inbox.user_id.active_key.public}) + elif len(inbox) == 0 and len(user) == 1: + ctx["public"] = user.active_key.public + + # A valid token would mean we found a public key + if not ctx.get("public"): + ctx["error"] = _("Invalid token") + return request.render("vault.inbox", ctx) + + # Just render if GET method + if request.httprequest.method != "POST": + return request.render("vault.inbox", ctx) + + # Check the param + name = request.params.get("name") + secret = request.params.get("encrypted") + secret_file = request.params.get("encrypted_file") + filename = request.params.get("filename") + iv = request.params.get("iv") + key = request.params.get("key") + if not name: + ctx["error"] = _("Please specify a name") + return request.render("vault.inbox", ctx) + + if not secret and not secret_file: + ctx["error"] = _("No secret found") + return request.render("vault.inbox", ctx) + + if secret_file and not filename: + ctx["error"] = _("Missing filename") + return request.render("vault.inbox", ctx) + + if not iv or not key: + ctx["error"] = _("Something went wrong with the encryption") + return request.render("vault.inbox", ctx) + + try: + inbox.store_in_inbox( + name, + secret, + secret_file, + iv, + key, + user, + filename, + ip=request.httprequest.remote_addr, + ) + except Exception as e: + _logger.exception(e) + ctx["error"] = _( + "An error occured. Please contact the user or administrator" + ) + return request.render("vault.inbox", ctx) + + ctx["message"] = _("Successfully stored") + return request.render("vault.inbox", ctx) + + @http.route("/vault/public", type="json") + def vault_public(self, user_id): + """Get the public key of a specific user""" + user = request.env["res.users"].sudo().browse(user_id).exists() + if not user or not user.keys: + return {} + + return {"public_key": user.active_key.public} + + @http.route("/vault/inbox/get", auth="user", type="json") + def vault_get_inbox(self): + inboxes = request.env.user.inbox_ids + return {inbox.token: inbox.key for inbox in inboxes} + + @http.route("/vault/inbox/store", auth="user", type="json") + def vault_store_inbox(self, keys): + if not isinstance(keys, dict): + return + + for inbox in request.env.user.inbox_ids: + key = keys.get(inbox.token) + + if isinstance(key, str): + inbox.key = key + + @http.route("/vault/keys/store", auth="user", type="json") + def vault_store_keys(self, **kwargs): + """Store the key pair for the current user""" + return request.env["res.users.key"].store(**kwargs) + + @http.route("/vault/keys/get", auth="user", type="json") + def vault_get_keys(self): + """Get the currently active key pair""" + return request.env.user.get_vault_keys() + + @http.route("/vault/rights/get", auth="user", type="json") + def vault_get_right_keys(self): + """Get the master keys from the vault.right records""" + rights = request.env.user.vault_right_ids + return {right.vault_id.uuid: right.key for right in rights} + + @http.route("/vault/rights/store", auth="user", type="json") + def vault_store_right_keys(self, keys): + """Store the master keys to the specific vault.right records""" + if not isinstance(keys, dict): + return + + for right in request.env.user.vault_right_ids: + master_key = keys.get(right.vault_id.uuid) + + if isinstance(master_key, str): + right.sudo().key = master_key + + @http.route("/vault/replace", auth="user", type="json") + def vault_replace(self, data): + """Replace the master keys and values within a single transaction""" + if not isinstance(data, list): + return + + vault = request.env["vault"].with_context(vault_skip_log=True) + for changes in data: + record = vault.env[changes["model"]].browse(changes["id"]) + if not record.vault_id.allowed_write: + raise AccessDenied() + + vault |= record.vault_id + if record._name in ("vault.field", "vault.file"): + record.write({k: v for k, v in changes.items() if k in ["iv", "value"]}) + elif record._name == "vault.right": + record.write({k: v for k, v in changes.items() if k in ["key"]}) + + for v in vault: + v._log_entry("Replaced the keys", "info") + + vault.sudo().write({"reencrypt_required": False}) diff --git a/vault/i18n/es.po b/vault/i18n/es.po new file mode 100644 index 0000000000..3358c5bda5 --- /dev/null +++ b/vault/i18n/es.po @@ -0,0 +1,1505 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * vault +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-06-06 06:57+0000\n" +"PO-Revision-Date: 2023-10-31 20:36+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "%(action)s entry %(name)s by %(user)s" +msgstr "%(action)s entrada %(name)s por %(user)s" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "%s '%s' of entry '%s'" +msgstr "%s '%s' del registro '%s'" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "%s (copy)" +msgstr "%s (copia)" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "" +"A secure browser context is required. Please switch to https or contact your " +"administrator" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "A-Z" +msgstr "A-Z" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault_field.py:0 +#: model:ir.model,name:vault.model_vault_abstract_field +#, python-format +msgid "Abstract model to implement basic fields for encryption" +msgstr "Modelo abstracto para implementar los campos básicos de encriptación" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault.py:0 +#: model:ir.model,name:vault.model_vault_abstract +#, python-format +msgid "Abstract model to implement general access rights" +msgstr "Modelo abstracto para aplicar los derechos de acceso generales" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__accesses +msgid "Access counter" +msgstr "Contador de acceso" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__active_key +msgid "Active Key" +msgstr "Clave activa" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_entry +#: model:ir.ui.menu,name:vault.menu_vault_entry +msgid "All Entries" +msgstr "Todos los registros" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow all users to export vaults accessible to them" +msgstr "Permitir que todos los usuarios exporten bóvedas accesibles para ellos" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow all users to import vaults accessible to them" +msgstr "Permitir que todos los usuarios importen bóvedas accesibles para ellos" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow the usage to share secrets with external users" +msgstr "Permitir el uso para compartir secretos con usuarios externos" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_create +msgid "Allow to create in the vault" +msgstr "Permitir crear en el vault" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_delete +msgid "Allow to delete a vault" +msgstr "Permitir borrar un vault" + +#. module: vault +#: model:res.groups,name:vault.group_vault_export +msgid "Allow to export vaults" +msgstr "Permitir exportar bóvedas" + +#. module: vault +#: model:res.groups,name:vault.group_vault_import +msgid "Allow to import vaults" +msgstr "Permitir importar bóvedas" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_share +msgid "Allow to share a vault with new users" +msgstr "Permitir compartir un vault con nuevos usuarios" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_write +msgid "Allow to write to the vault" +msgstr "Permitir escribir en un vault" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_create +msgid "Allowed Create" +msgstr "Permitido crear" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_delete +msgid "Allowed Delete" +msgstr "Permitido borrar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_read +msgid "Allowed Read" +msgstr "Permitido leer" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_share +msgid "Allowed Share" +msgstr "Permitido añadir usuarios" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_write +msgid "Allowed Write" +msgstr "Permitido escribir" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "An error occured. Please contact the user or administrator" +msgstr "" +"Se ha producido un error. Por favor, póngase en contacto con el usuario o el " +"administrador" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "By user" +msgstr "Por usuario" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "By vault" +msgstr "Por vault" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +#, python-format +msgid "Cancel" +msgstr "Cancelar" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Cancelled" +msgstr "Cancelado" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Characters:" +msgstr "Caracteres:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__child_ids +msgid "Child" +msgstr "Hijo" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Childs" +msgstr "Hijos" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_export_wizard +msgid "Close" +msgstr "Cerrar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__entry_name +#: model:ir.model.fields,field_description:vault.field_vault_entry__complete_name +#: model:ir.model.fields,field_description:vault.field_vault_field__entry_name +#: model:ir.model.fields,field_description:vault.field_vault_file__entry_name +msgid "Complete Name" +msgstr "Nombre completo" + +#. module: vault +#: model:ir.model,name:vault.model_res_config_settings +msgid "Config Settings" +msgstr "Opciones de Configuración" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Confirm your password:" +msgstr "Confirma tu contraseña:" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Content" +msgstr "Contenido" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Copy to clipboard" +msgstr "Copiar al portapapeles" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_create +msgid "Create" +msgstr "Crear" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__create_uid +#: model:ir.model.fields,field_description:vault.field_vault__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_entry__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_field__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_file__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_log__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_right__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_tag__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#, python-format +msgid "Created by %(name)s via %(ip)s" +msgstr "Creado por %(name)s a través de %(ip)s" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#, python-format +msgid "Created by %s" +msgstr "Creado por %s" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__create_date +#: model:ir.model.fields,field_description:vault.field_vault__create_date +#: model:ir.model.fields,field_description:vault.field_vault_entry__create_date +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_field__create_date +#: model:ir.model.fields,field_description:vault.field_vault_file__create_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__create_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox__create_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__create_date +#: model:ir.model.fields,field_description:vault.field_vault_log__create_date +#: model:ir.model.fields,field_description:vault.field_vault_right__create_date +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_tag__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__crypted_content +msgid "Crypted Content" +msgstr "Contenido encriptado" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__current +msgid "Current" +msgstr "Actual" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Custom JSON format .json" +msgstr "Formato JSON personalizado .json" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__content +msgid "Database" +msgstr "Base de datos" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_delete +msgid "Delete" +msgstr "Borrar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__display_name +#: model:ir.model.fields,field_description:vault.field_vault__display_name +#: model:ir.model.fields,field_description:vault.field_vault_entry__display_name +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_field__display_name +#: model:ir.model.fields,field_description:vault.field_vault_file__display_name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__display_name +#: model:ir.model.fields,field_description:vault.field_vault_inbox__display_name +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__display_name +#: model:ir.model.fields,field_description:vault.field_vault_log__display_name +#: model:ir.model.fields,field_description:vault.field_vault_right__display_name +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_tag__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "Do you really want to create a new key pair and set it active?" +msgstr "¿Realmente quiere crear un nuevo par de claves y activarlo?" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__content +msgid "Download" +msgstr "Descargar" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Enter" +msgstr "Ingrese a" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Enter your password:" +msgstr "Ingrese su contraseña:" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_open_entries +#: model:ir.model.fields,field_description:vault.field_vault__entry_ids +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__entry_id +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Entries" +msgstr "Registros" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_field__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_file__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_log__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__entry_id +msgid "Entry" +msgstr "Registro" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#: model:ir.model,name:vault.model_vault_entry +#, python-format +msgid "Entry inside a vault" +msgstr "Entrar al interior de un vault" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Error" +msgstr "Error" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__expiration +msgid "Expiration" +msgstr "Expiración" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__expired +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Expired" +msgstr "Expirado" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__expire_date +msgid "Expires on" +msgstr "Expira en" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__group_vault_export +msgid "Export Vaults" +msgstr "Exportar bóvedas" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +#, python-format +msgid "Export to file" +msgstr "Exportar a fichero" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_export_wizard.py:0 +#: model:ir.model,name:vault.model_vault_export_wizard +#, python-format +msgid "Export wizard for vaults" +msgstr "Asistente de exportación para vaults" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to export keys to object store" +msgstr "Fallo en la exportación de claves al almacén de objetos" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to export the keys to the database" +msgstr "Fallo en la exportación de claves a la base de datos" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to import keys from database" +msgstr "Fallo en la importación de claves desde la base de datos" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_field.py:0 +#: model:ir.model,name:vault.model_vault_field +#, python-format +msgid "Field of a vault" +msgstr "Campo de un vault" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__field_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__field_ids +msgid "Fields" +msgstr "Campos" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_file.py:0 +#: model:ir.model,name:vault.model_vault_file +#, python-format +msgid "File of a vault" +msgstr "Fichero de un vault" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "File to share:" +msgstr "Fichero a compartir:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__filename +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__filename +msgid "Filename" +msgstr "Nombre del fichero" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__file_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__file_ids +msgid "Files" +msgstr "Ficheros" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__fingerprint +msgid "Fingerprint" +msgstr "Huella digital" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Generate" +msgstr "Generar" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Generate a new secret:" +msgstr "Generar nuevo secreto:" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "Grouped" +msgstr "Agrupado" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Hide" +msgstr "Ocultar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__id +#: model:ir.model.fields,field_description:vault.field_vault__id +#: model:ir.model.fields,field_description:vault.field_vault_entry__id +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_field__id +#: model:ir.model.fields,field_description:vault.field_vault_file__id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__id +#: model:ir.model.fields,field_description:vault.field_vault_inbox__id +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__id +#: model:ir.model.fields,field_description:vault.field_vault_log__id +#: model:ir.model.fields,field_description:vault.field_vault_right__id +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_tag__id +msgid "ID" +msgstr "ID" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__expiration +msgid "If expired the inbox can't be written using the link" +msgstr "" +"Si ha caducado, la bandeja de entrada no puede escribirse utilizando el " +"enlace" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__accesses +msgid "If this is 0 the inbox can't be written using the link" +msgstr "" +"Si esto es 0 la bandeja de entrada no puede ser escrita usando el enlace" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Import" +msgstr "Importar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__group_vault_import +msgid "Import Vaults" +msgstr "Importar bóvedas" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +#, python-format +msgid "Import from file" +msgstr "Importar desde archivo" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#: model:ir.model,name:vault.model_vault_import_wizard +#, python-format +msgid "Import wizard for vaults" +msgstr "Asistente de importación para vaults" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#: model:ir.model,name:vault.model_vault_import_wizard_path +#, python-format +msgid "Import wizard path for vaults" +msgstr "Ruta del asistente de importación para vaults" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_inbox +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_ids +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__inbox_id +#: model:ir.ui.menu,name:vault.menu_vault_inbox +msgid "Inbox" +msgstr "Bandeja de entrada" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_enabled +msgid "Inbox Enabled" +msgstr "Bandeja de entrada habilitada" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_link +#: model:ir.model.fields,field_description:vault.field_vault_inbox__inbox_link +msgid "Inbox Link" +msgstr "Enlace de la bandeja de entrada" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_token +msgid "Inbox Token" +msgstr "Token bandeja de entrada" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__include_childs +msgid "Include Childs" +msgstr "Incluir hijos" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Information" +msgstr "Información" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#, python-format +msgid "Invalid file to import from" +msgstr "Archivo inválido para importar" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/res_users_key.py:0 +#, python-format +msgid "Invalid parameter" +msgstr "Parámetro no válido" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Invalid token" +msgstr "Token inválido" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "Invalidate private key" +msgstr "Invalidar clave privada" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__iterations +msgid "Iterations" +msgstr "Iteraciones" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__iv +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__iv +#: model:ir.model.fields,field_description:vault.field_vault_field__iv +#: model:ir.model.fields,field_description:vault.field_vault_file__iv +#: model:ir.model.fields,field_description:vault.field_vault_inbox__iv +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__iv +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__iv +msgid "Iv" +msgstr "Iv" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Keepass Database .kdbx" +msgstr "Base de datos keepass .kdbx" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__key +#: model:ir.model.fields,field_description:vault.field_vault_right__key +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__key +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__key +msgid "Key" +msgstr "Clave" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/user_menu.esm.js:0 +#, python-format +msgid "Key Management" +msgstr "Gestión de claves" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__key_user +msgid "Key User" +msgstr "Clave de usuario" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Keyfile:" +msgstr "Archivo de llaves:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__keys +msgid "Keys" +msgstr "Claves" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key____last_update +#: model:ir.model.fields,field_description:vault.field_vault____last_update +#: model:ir.model.fields,field_description:vault.field_vault_entry____last_update +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_field____last_update +#: model:ir.model.fields,field_description:vault.field_vault_file____last_update +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path____last_update +#: model:ir.model.fields,field_description:vault.field_vault_inbox____last_update +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log____last_update +#: model:ir.model.fields,field_description:vault.field_vault_log____last_update +#: model:ir.model.fields,field_description:vault.field_vault_right____last_update +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_tag____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__write_uid +#: model:ir.model.fields,field_description:vault.field_vault__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_entry__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_field__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_file__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_log__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_right__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_tag__write_uid +msgid "Last Updated by" +msgstr "Última modificación por" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__write_date +#: model:ir.model.fields,field_description:vault.field_vault__write_date +#: model:ir.model.fields,field_description:vault.field_vault_entry__write_date +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_field__write_date +#: model:ir.model.fields,field_description:vault.field_vault_file__write_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__write_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox__write_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__write_date +#: model:ir.model.fields,field_description:vault.field_vault_log__write_date +#: model:ir.model.fields,field_description:vault.field_vault_right__write_date +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_tag__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Length:" +msgstr "Longitud:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__log_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__log_ids +#: model:ir.model.fields,field_description:vault.field_vault_inbox__log_ids +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Log" +msgstr "Registro" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#: model:ir.model,name:vault.model_vault_log +#, python-format +msgid "Log entry of a vault" +msgstr "Registro de entrada de un vault" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_res_users_keys +msgid "Manage my keys" +msgstr "Gestionar mis claves" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__master_key +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__master_key +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__master_key +#: model:ir.model.fields,field_description:vault.field_vault_field__master_key +#: model:ir.model.fields,field_description:vault.field_vault_file__master_key +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__master_key +#: model:ir.model.fields,field_description:vault.field_vault_right__master_key +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__master_key +msgid "Master Key" +msgstr "Clave maestra" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_log__message +msgid "Message" +msgstr "Mensaje" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Missing filename" +msgstr "Falta el nombre del fichero" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Missing password" +msgstr "Falta la contraseña" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__model +msgid "Model" +msgstr "Modelo" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__module_vault_share +msgid "Module Vault Share" +msgstr "Módulo Vault Share" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__name +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__name +#: model:ir.model.fields,field_description:vault.field_vault_entry__name +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_field__name +#: model:ir.model.fields,field_description:vault.field_vault_file__name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__name +#: model:ir.model.fields,field_description:vault.field_vault_inbox__name +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__name +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_tag__name +msgid "Name" +msgstr "Nombre" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Name of your secret:" +msgstr "Nombre de tu secreto:" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#, python-format +msgid "Neither a secret nor file was given" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "New inbox link" +msgstr "Nuevo enlace de la bandeja de entrada" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "New private key" +msgstr "Nueva clave privada" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "No secret found" +msgstr "No se ha encontrado ningún secreto" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_inbox_value_check +#: model:ir.model.constraint,message:vault.constraint_vault_send_wizard_value_check +#, python-format +msgid "No value found" +msgstr "No se ha encontrado ningún valor" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Not Expired" +msgstr "No ha caducado" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__note +#: model:ir.model.fields,field_description:vault.field_vault_entry__note +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Note" +msgstr "Nota" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__user_id +#: model:ir.model.fields,field_description:vault.field_vault_entry__user_id +msgid "Owner" +msgstr "Propietario" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__parent_id +msgid "Parent" +msgstr "Padre" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__parent_id +msgid "Parent Entry" +msgstr "Registro padre" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Password:" +msgstr "Contraseña:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__path +msgid "Path to import" +msgstr "Ruta de importación" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_entry__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_field__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_file__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_user +msgid "Perm User" +msgstr "Usuario permanente" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/export.esm.js:0 +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Please enter the password for the database" +msgstr "Por favor, introduzca la contraseña de la base de datos" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Please enter the password for the keepass database" +msgstr "Por favor, introduzca la contraseña de la base de datos keepass" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Please enter the password for your private key" +msgstr "Por favor, introduzca la contraseña de su clave privada" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Please enter your password or upload a keyfile:" +msgstr "Por favor, introduzca su contraseña o cargue un archivo de claves:" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Please specify a name" +msgstr "Por favor, especifique un nombre" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__private +msgid "Private" +msgstr "Privado" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__public +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__public +msgid "Public" +msgstr "Público" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__public_key +msgid "Public Key" +msgstr "Clave pública" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Re-encrypt" +msgstr "Reencriptar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__reencrypt_required +msgid "Reencrypt Required" +msgstr "Necesita reencriptarse" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_right +#: model:ir.model.fields,field_description:vault.field_vault__right_ids +#: model:ir.ui.menu,name:vault.menu_vault_right +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Rights" +msgstr "Derechos" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__salt +msgid "Salt" +msgstr "Sal" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_export_file.esm.js:0 +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "Save As..." +msgstr "Guardar como..." + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Save in a vault" +msgstr "Guardar en un vault" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__secret +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__secret +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__secret +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Secret" +msgstr "Secreto" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__secret_file +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__secret_file +msgid "Secret File" +msgstr "Archivo de secretos" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__secret_temporary +msgid "Secret Temporary" +msgstr "Secreto temporal" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Secret to share:" +msgstr "Secreto a compartir:" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +msgid "Send" +msgstr "Enviar" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Send the secret to an user" +msgstr "Enviar secreto a un usuario" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_mixin.esm.js:0 +#, python-format +msgid "Send the secret to another user" +msgstr "Enviar secreto a otro usuario" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_share +msgid "Share" +msgstr "Compartir" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Show" +msgstr "Mostrar" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Something went wrong with the encryption" +msgstr "Algo ha ido mal en el encriptado" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Special" +msgstr "Especial" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_log__state +msgid "State" +msgstr "Estado" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +msgid "Store" +msgstr "Tienda" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_mixin.esm.js:0 +#, python-format +msgid "Store the secret in a vault" +msgstr "Guarda el secreto en un vault" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Submit secret" +msgstr "Enviar secreto" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Successfully stored" +msgstr "Guardado correctamente" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__tags +msgid "Tags" +msgstr "Etiquetas" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_entry_vault_uuid_uniq +#: model:ir.model.constraint,message:vault.constraint_vault_uuid_uniq +#, python-format +msgid "The UUID must be unique." +msgstr "El UUID debe ser único." + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_export_file.esm.js:0 +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "The field is empty, there's nothing to save!" +msgstr "El campo está vacío, ¡no hay nada que guardar!" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "The files must end on one of the supported file type:" +msgstr "Los archivos deben terminar en uno de los tipos de archivo admitidos:" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "The following entries are broken:" +msgstr "Los siguientes registros están rotos:" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "The passwords aren't matching" +msgstr "Las contraseñas no coinciden" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault.py:0 +#, python-format +msgid "" +"The requested operation can not be completed due to security restrictions." +msgstr "" +"La operación solicitada no puede completarse debido a restricciones de " +"seguridad." + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_tag.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_tag_name_uniq +#, python-format +msgid "The tag must be unique!" +msgstr "¡La etiqueta debe ser única!" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_right.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_right_user_uniq +#, python-format +msgid "The user must be unique" +msgstr "El usuario debe ser único" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__token +msgid "Token" +msgstr "Token" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Unsupported file to import" +msgstr "Archivo no compatible para importar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__url +msgid "Url" +msgstr "Url" + +#. module: vault +#: model:ir.model,name:vault.model_res_users +#: model:ir.model.fields,field_description:vault.field_res_users_key__user_id +#: model:ir.model.fields,field_description:vault.field_vault_log__user_id +#: model:ir.model.fields,field_description:vault.field_vault_right__user_id +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__user_id +msgid "User" +msgstr "Usuario" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/res_users_key.py:0 +#: model:ir.model,name:vault.model_res_users_key +#, python-format +msgid "User data of a vault" +msgstr "Datos de usuario de un vault" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__inbox_link +msgid "" +"Using this link you can write to the current inbox. If you want people to " +"create new inboxes you should give them your inbox link from your key " +"management." +msgstr "" +"Con este enlace puedes escribir en la bandeja de entrada actual. Si quieres " +"que la gente cree nuevas bandejas de entrada, deberás darles el enlace de tu " +"bandeja de entrada desde tu gestor de claves." + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__uuid +#: model:ir.model.fields,field_description:vault.field_vault__uuid +#: model:ir.model.fields,field_description:vault.field_vault_entry__uuid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__uuid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__uuid +msgid "Uuid" +msgstr "Uuid" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_field__value +#: model:ir.model.fields,field_description:vault.field_vault_file__value +msgid "Value" +msgstr "Valor" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: model:ir.actions.act_window,name:vault.action_vault +#: model:ir.model,name:vault.model_vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_entry__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_field__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_file__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_inbox__user_id +#: model:ir.model.fields,field_description:vault.field_vault_log__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_right__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__vault_id +#: model:ir.ui.menu,name:vault.menu_vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +#, python-format +msgid "Vault" +msgstr "Bóveda" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_field.esm.js:0 +#, python-format +msgid "Vault Field" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "Vault File" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_field.esm.js:0 +#, python-format +msgid "Vault Inbox Field" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_file.esm.js:0 +#, python-format +msgid "Vault Inbox File" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__vault_right_ids +msgid "Vault Right" +msgstr "Permiso de vault" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Vault Share" +msgstr "Compartir vault" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox_log.py:0 +#: model:ir.model,name:vault.model_vault_inbox_log +#, python-format +msgid "Vault inbox log" +msgstr "Registro de bandeja de entrada de vault" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "Vault is not supported" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_right.py:0 +#: model:ir.model,name:vault.model_vault_right +#, python-format +msgid "Vault rights" +msgstr "Permisos de vault" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#: model:ir.model,name:vault.model_vault_inbox +#, python-format +msgid "Vault share incoming secrets" +msgstr "Compartir los secretos de entrada de vault" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_tag.py:0 +#: model:ir.model,name:vault.model_vault_tag +#, python-format +msgid "Vault tag" +msgstr "Etiqueta de vault" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Vaults" +msgstr "Bóvedas" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Verify" +msgstr "Verificar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__version +msgid "Version" +msgstr "Versión" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Warning" +msgstr "Advertencia" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_store_wizard.py:0 +#: model:ir.model,name:vault.model_vault_store_wizard +#, python-format +msgid "Wizard store a shared secret in a vault" +msgstr "Asistente de almacenado de secreto compartido en un vault" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#: model:ir.model,name:vault.model_vault_send_wizard +#, python-format +msgid "Wizard to send another user a secret" +msgstr "Asistente para enviar un secreto a otro usuario" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_write +msgid "Write" +msgstr "Escribir" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#, python-format +msgid "Written by %(name)s via %(ip)s" +msgstr "Escrito por %(name)s vía %(ip)s" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "You can not create recursive entries." +msgstr "No puedes crear registros recrsivos." + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +msgid "" +"You can only send the secret to the user who has generated a key-pair.\n" +" If an user is not showing please ask him to generate " +"these." +msgstr "" +"Sólo se puede enviar el secreto al usuario que ha generado un par de " +"claves.\n" +" Si un usuario no aparece, por favor, pídale que los " +"genere." + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "" +"You will loose access to all vaults and your inbox. Do you want to continue?" +msgstr "" +"Perderá el acceso a todos sus vaults y a su bandeja de entrada. ¿Desea " +"continuar?" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "a-z" +msgstr "a-z" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +msgid "or" +msgstr "o" + +#~ msgid "Users" +#~ msgstr "Usuarios" + +#, python-format +#~ msgid "" +#~ "This will re-encrypt everything in the vault. Do you want to proceed?" +#~ msgstr "Esto volverá a encriptar todo en el vault. ¿Quieres proceder?" + +#, python-format +#~ msgid "%s entry %s by %s" +#~ msgstr "%s registrado %s por %s" + +#, python-format +#~ msgid "Created by %s via %s" +#~ msgstr "Creado por %s via %s" + +#, python-format +#~ msgid "Written by %s via %s" +#~ msgstr "Escrito por %s via %s" diff --git a/vault/i18n/nl.po b/vault/i18n/nl.po new file mode 100644 index 0000000000..eeb7fc93f9 --- /dev/null +++ b/vault/i18n/nl.po @@ -0,0 +1,1477 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * vault +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-05-05 10:45+0000\n" +"Last-Translator: Bosd \n" +"Language-Team: none\n" +"Language: nl\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.14.1\n" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "%(action)s entry %(name)s by %(user)s" +msgstr "%(action)s toegang %(name)s door %(user)s" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "%s '%s' of entry '%s'" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "" +"A secure browser context is required. Please switch to https or contact your " +"administrator" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "A-Z" +msgstr "A-Z" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault_field.py:0 +#: model:ir.model,name:vault.model_vault_abstract_field +#, python-format +msgid "Abstract model to implement basic fields for encryption" +msgstr "Abstract model om basisvelden voor encryptie te implementeren" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault.py:0 +#: model:ir.model,name:vault.model_vault_abstract +#, python-format +msgid "Abstract model to implement general access rights" +msgstr "Abstract model om algemene toegangsrechten te implementeren" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__accesses +msgid "Access counter" +msgstr "Toegangsteller" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__active_key +msgid "Active Key" +msgstr "Actieve sleutel" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_entry +#: model:ir.ui.menu,name:vault.menu_vault_entry +msgid "All Entries" +msgstr "Alle invoeren" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow all users to export vaults accessible to them" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow all users to import vaults accessible to them" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow the usage to share secrets with external users" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_create +msgid "Allow to create in the vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_delete +msgid "Allow to delete a vault" +msgstr "" + +#. module: vault +#: model:res.groups,name:vault.group_vault_export +msgid "Allow to export vaults" +msgstr "" + +#. module: vault +#: model:res.groups,name:vault.group_vault_import +msgid "Allow to import vaults" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_share +msgid "Allow to share a vault with new users" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_write +msgid "Allow to write to the vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_create +msgid "Allowed Create" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_delete +msgid "Allowed Delete" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_read +msgid "Allowed Read" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_share +msgid "Allowed Share" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_write +msgid "Allowed Write" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "An error occured. Please contact the user or administrator" +msgstr "" +"Er is een fout opgetreden. Neem contact op met de gebruiker of beheerder" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "By user" +msgstr "Door gebruiker" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "By vault" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +#, python-format +msgid "Cancel" +msgstr "Annuleer" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Cancelled" +msgstr "Geannuleerd" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Characters:" +msgstr "Karakters:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__child_ids +msgid "Child" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Childs" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_export_wizard +msgid "Close" +msgstr "Sluiten" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__entry_name +#: model:ir.model.fields,field_description:vault.field_vault_entry__complete_name +#: model:ir.model.fields,field_description:vault.field_vault_field__entry_name +#: model:ir.model.fields,field_description:vault.field_vault_file__entry_name +msgid "Complete Name" +msgstr "Volledige naam" + +#. module: vault +#: model:ir.model,name:vault.model_res_config_settings +msgid "Config Settings" +msgstr "Configuratie-instellingen" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Confirm your password:" +msgstr "Bevestig uw wachtwoord:" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Content" +msgstr "Inhoud" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Copy to clipboard" +msgstr "Kopiëren naar klembord" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_create +msgid "Create" +msgstr "Aanmaken" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__create_uid +#: model:ir.model.fields,field_description:vault.field_vault__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_entry__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_field__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_file__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_log__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_right__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_tag__create_uid +msgid "Created by" +msgstr "Aangemaakt door" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#, python-format +msgid "Created by %(name)s via %(ip)s" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#, python-format +msgid "Created by %s" +msgstr "Aangemaakt door %s" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__create_date +#: model:ir.model.fields,field_description:vault.field_vault__create_date +#: model:ir.model.fields,field_description:vault.field_vault_entry__create_date +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_field__create_date +#: model:ir.model.fields,field_description:vault.field_vault_file__create_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__create_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox__create_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__create_date +#: model:ir.model.fields,field_description:vault.field_vault_log__create_date +#: model:ir.model.fields,field_description:vault.field_vault_right__create_date +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_tag__create_date +msgid "Created on" +msgstr "Aangemaakt op" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__crypted_content +msgid "Crypted Content" +msgstr "Versleutelde inhoud" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__current +msgid "Current" +msgstr "Huidig" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Custom JSON format .json" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__content +msgid "Database" +msgstr "Database" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_delete +msgid "Delete" +msgstr "Verwijder" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__display_name +#: model:ir.model.fields,field_description:vault.field_vault__display_name +#: model:ir.model.fields,field_description:vault.field_vault_entry__display_name +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_field__display_name +#: model:ir.model.fields,field_description:vault.field_vault_file__display_name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__display_name +#: model:ir.model.fields,field_description:vault.field_vault_inbox__display_name +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__display_name +#: model:ir.model.fields,field_description:vault.field_vault_log__display_name +#: model:ir.model.fields,field_description:vault.field_vault_right__display_name +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_tag__display_name +msgid "Display Name" +msgstr "Schermnaam" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "Do you really want to create a new key pair and set it active?" +msgstr "Wilt u echt een nieuw sleutelpaar aanmaken en activeren?" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__content +msgid "Download" +msgstr "Download" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Enter" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Enter your password:" +msgstr "Voer uw wachtwoord in:" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_open_entries +#: model:ir.model.fields,field_description:vault.field_vault__entry_ids +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__entry_id +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Entries" +msgstr "Boekingen" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_field__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_file__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_log__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__entry_id +msgid "Entry" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#: model:ir.model,name:vault.model_vault_entry +#, python-format +msgid "Entry inside a vault" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Error" +msgstr "Fout" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__expiration +msgid "Expiration" +msgstr "Vervaldatum" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__expired +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Expired" +msgstr "Verlopen" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__expire_date +msgid "Expires on" +msgstr "Verloopt op" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__group_vault_export +msgid "Export Vaults" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +#, python-format +msgid "Export to file" +msgstr "Export naar bestand" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_export_wizard.py:0 +#: model:ir.model,name:vault.model_vault_export_wizard +#, python-format +msgid "Export wizard for vaults" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to export keys to object store" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to export the keys to the database" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to import keys from database" +msgstr "Kan geen sleutels uit database importeren" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_field.py:0 +#: model:ir.model,name:vault.model_vault_field +#, python-format +msgid "Field of a vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__field_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__field_ids +msgid "Fields" +msgstr "Velden" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_file.py:0 +#: model:ir.model,name:vault.model_vault_file +#, python-format +msgid "File of a vault" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "File to share:" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__filename +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__filename +msgid "Filename" +msgstr "Bestandsnaam" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__file_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__file_ids +msgid "Files" +msgstr "Bestanden" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__fingerprint +msgid "Fingerprint" +msgstr "Fingerprint" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Generate" +msgstr "Genereer" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Generate a new secret:" +msgstr "Genereer een nieuw geheim:" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "Grouped" +msgstr "Gegroepeerd" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Hide" +msgstr "Verbergen" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__id +#: model:ir.model.fields,field_description:vault.field_vault__id +#: model:ir.model.fields,field_description:vault.field_vault_entry__id +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_field__id +#: model:ir.model.fields,field_description:vault.field_vault_file__id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__id +#: model:ir.model.fields,field_description:vault.field_vault_inbox__id +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__id +#: model:ir.model.fields,field_description:vault.field_vault_log__id +#: model:ir.model.fields,field_description:vault.field_vault_right__id +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_tag__id +msgid "ID" +msgstr "ID" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__expiration +msgid "If expired the inbox can't be written using the link" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__accesses +msgid "If this is 0 the inbox can't be written using the link" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Import" +msgstr "Import" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__group_vault_import +msgid "Import Vaults" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +#, python-format +msgid "Import from file" +msgstr "Importeren uit bestand" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#: model:ir.model,name:vault.model_vault_import_wizard +#, python-format +msgid "Import wizard for vaults" +msgstr "Wizard voor het importeren van kluizen" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#: model:ir.model,name:vault.model_vault_import_wizard_path +#, python-format +msgid "Import wizard path for vaults" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_inbox +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_ids +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__inbox_id +#: model:ir.ui.menu,name:vault.menu_vault_inbox +msgid "Inbox" +msgstr "Inbox" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_enabled +msgid "Inbox Enabled" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_link +#: model:ir.model.fields,field_description:vault.field_vault_inbox__inbox_link +msgid "Inbox Link" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_token +msgid "Inbox Token" +msgstr "Inbox Token" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__include_childs +msgid "Include Childs" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Information" +msgstr "Informatie" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#, python-format +msgid "Invalid file to import from" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/res_users_key.py:0 +#, python-format +msgid "Invalid parameter" +msgstr "Ongeldige parameter" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Invalid token" +msgstr "Ongeldige token" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "Invalidate private key" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__iterations +msgid "Iterations" +msgstr "Iteraties" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__iv +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__iv +#: model:ir.model.fields,field_description:vault.field_vault_field__iv +#: model:ir.model.fields,field_description:vault.field_vault_file__iv +#: model:ir.model.fields,field_description:vault.field_vault_inbox__iv +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__iv +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__iv +msgid "Iv" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Keepass Database .kdbx" +msgstr "Keepass Database .kdbx" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__key +#: model:ir.model.fields,field_description:vault.field_vault_right__key +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__key +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__key +msgid "Key" +msgstr "Sleutel" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/user_menu.esm.js:0 +#, python-format +msgid "Key Management" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__key_user +msgid "Key User" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Keyfile:" +msgstr "Keyfile:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__keys +msgid "Keys" +msgstr "Keys" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key____last_update +#: model:ir.model.fields,field_description:vault.field_vault____last_update +#: model:ir.model.fields,field_description:vault.field_vault_entry____last_update +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_field____last_update +#: model:ir.model.fields,field_description:vault.field_vault_file____last_update +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path____last_update +#: model:ir.model.fields,field_description:vault.field_vault_inbox____last_update +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log____last_update +#: model:ir.model.fields,field_description:vault.field_vault_log____last_update +#: model:ir.model.fields,field_description:vault.field_vault_right____last_update +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_tag____last_update +msgid "Last Modified on" +msgstr "Laatst gewijzigd op" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__write_uid +#: model:ir.model.fields,field_description:vault.field_vault__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_entry__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_field__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_file__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_log__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_right__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_tag__write_uid +msgid "Last Updated by" +msgstr "Laatst bijgewerkt door" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__write_date +#: model:ir.model.fields,field_description:vault.field_vault__write_date +#: model:ir.model.fields,field_description:vault.field_vault_entry__write_date +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_field__write_date +#: model:ir.model.fields,field_description:vault.field_vault_file__write_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__write_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox__write_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__write_date +#: model:ir.model.fields,field_description:vault.field_vault_log__write_date +#: model:ir.model.fields,field_description:vault.field_vault_right__write_date +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_tag__write_date +msgid "Last Updated on" +msgstr "Laatst bijgewerkt op" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Length:" +msgstr "Lengte:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__log_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__log_ids +#: model:ir.model.fields,field_description:vault.field_vault_inbox__log_ids +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Log" +msgstr "Log" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#: model:ir.model,name:vault.model_vault_log +#, python-format +msgid "Log entry of a vault" +msgstr "Logboekvermelding van een kluis" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_res_users_keys +msgid "Manage my keys" +msgstr "Beheer mijn sleutels" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__master_key +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__master_key +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__master_key +#: model:ir.model.fields,field_description:vault.field_vault_field__master_key +#: model:ir.model.fields,field_description:vault.field_vault_file__master_key +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__master_key +#: model:ir.model.fields,field_description:vault.field_vault_right__master_key +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__master_key +msgid "Master Key" +msgstr "Hoofdsleutel" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_log__message +msgid "Message" +msgstr "Bericht" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Missing filename" +msgstr "Ontbrekende bestandsnaam" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Missing password" +msgstr "Ontbrekend wachtwoord" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__model +msgid "Model" +msgstr "Type" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__module_vault_share +msgid "Module Vault Share" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__name +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__name +#: model:ir.model.fields,field_description:vault.field_vault_entry__name +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_field__name +#: model:ir.model.fields,field_description:vault.field_vault_file__name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__name +#: model:ir.model.fields,field_description:vault.field_vault_inbox__name +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__name +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_tag__name +msgid "Name" +msgstr "Naam" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Name of your secret:" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#, python-format +msgid "Neither a secret nor file was given" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "New inbox link" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "New private key" +msgstr "Nieuwe privésleutel" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "No secret found" +msgstr "Geen geheim gevonden" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_inbox_value_check +#: model:ir.model.constraint,message:vault.constraint_vault_send_wizard_value_check +#, python-format +msgid "No value found" +msgstr "Geen waarde gevonden" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Not Expired" +msgstr "Niet verlopen" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__note +#: model:ir.model.fields,field_description:vault.field_vault_entry__note +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Note" +msgstr "Notitie" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__user_id +#: model:ir.model.fields,field_description:vault.field_vault_entry__user_id +msgid "Owner" +msgstr "Eigenaar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__parent_id +msgid "Parent" +msgstr "Bovenliggend" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__parent_id +msgid "Parent Entry" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Password:" +msgstr "Wachtwoord:" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__path +msgid "Path to import" +msgstr "Pad om te importeren" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_entry__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_field__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_file__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_user +msgid "Perm User" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/export.esm.js:0 +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Please enter the password for the database" +msgstr "Voer het wachtwoord van de database in" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Please enter the password for the keepass database" +msgstr "Voer het wachtwoord van de keepass database in" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Please enter the password for your private key" +msgstr "Voer het wachtwoord voor uw privésleutel in" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Please enter your password or upload a keyfile:" +msgstr "Voer uw wachtwoord in of upload een keyfile:" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Please specify a name" +msgstr "Geef een naam op" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__private +msgid "Private" +msgstr "Privé" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__public +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__public +msgid "Public" +msgstr "Openbaar" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__public_key +msgid "Public Key" +msgstr "Openbare sleutel" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Re-encrypt" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__reencrypt_required +msgid "Reencrypt Required" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_right +#: model:ir.model.fields,field_description:vault.field_vault__right_ids +#: model:ir.ui.menu,name:vault.menu_vault_right +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Rights" +msgstr "Rechten" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__salt +msgid "Salt" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_export_file.esm.js:0 +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "Save As..." +msgstr "Opslaan als..." + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Save in a vault" +msgstr "Opslaan in een kluis" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__secret +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__secret +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__secret +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Secret" +msgstr "Geheim" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__secret_file +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__secret_file +msgid "Secret File" +msgstr "Secret File" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__secret_temporary +msgid "Secret Temporary" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Secret to share:" +msgstr "Geheim om te delen:" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +msgid "Send" +msgstr "Verzenden" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Send the secret to an user" +msgstr "Verzend het geheim naar een gebruiker" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_mixin.esm.js:0 +#, python-format +msgid "Send the secret to another user" +msgstr "Verzend het geheim naar een andere gebruiker" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_share +msgid "Share" +msgstr "Delen" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Show" +msgstr "Toon" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Something went wrong with the encryption" +msgstr "Er ging iets mis met de encryptie" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Special" +msgstr "Speciaal" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_log__state +msgid "State" +msgstr "Status" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +msgid "Store" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_mixin.esm.js:0 +#, python-format +msgid "Store the secret in a vault" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Submit secret" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Successfully stored" +msgstr "Succesvol opgeslagen" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__tags +msgid "Tags" +msgstr "Labels" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_entry_vault_uuid_uniq +#: model:ir.model.constraint,message:vault.constraint_vault_uuid_uniq +#, python-format +msgid "The UUID must be unique." +msgstr "De UUID moet uniek zijn." + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_export_file.esm.js:0 +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "The field is empty, there's nothing to save!" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "The files must end on one of the supported file type:" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "The following entries are broken:" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "The passwords aren't matching" +msgstr "De wachtwoorden komen niet overeen" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault.py:0 +#, python-format +msgid "" +"The requested operation can not be completed due to security restrictions." +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_tag.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_tag_name_uniq +#, python-format +msgid "The tag must be unique!" +msgstr "Het label moet uniek zijn!" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_right.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_right_user_uniq +#, python-format +msgid "The user must be unique" +msgstr "De gebruiker moet uniek zijn" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__token +msgid "Token" +msgstr "Token" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Unsupported file to import" +msgstr "Niet ondersteund bestand voor import" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__url +msgid "Url" +msgstr "Url" + +#. module: vault +#: model:ir.model,name:vault.model_res_users +#: model:ir.model.fields,field_description:vault.field_res_users_key__user_id +#: model:ir.model.fields,field_description:vault.field_vault_log__user_id +#: model:ir.model.fields,field_description:vault.field_vault_right__user_id +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__user_id +msgid "User" +msgstr "Gebruiker" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/res_users_key.py:0 +#: model:ir.model,name:vault.model_res_users_key +#, python-format +msgid "User data of a vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__inbox_link +msgid "" +"Using this link you can write to the current inbox. If you want people to " +"create new inboxes you should give them your inbox link from your key " +"management." +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__uuid +#: model:ir.model.fields,field_description:vault.field_vault__uuid +#: model:ir.model.fields,field_description:vault.field_vault_entry__uuid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__uuid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__uuid +msgid "Uuid" +msgstr "Uuid" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_field__value +#: model:ir.model.fields,field_description:vault.field_vault_file__value +msgid "Value" +msgstr "Waarde" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: model:ir.actions.act_window,name:vault.action_vault +#: model:ir.model,name:vault.model_vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_entry__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_field__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_file__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_inbox__user_id +#: model:ir.model.fields,field_description:vault.field_vault_log__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_right__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__vault_id +#: model:ir.ui.menu,name:vault.menu_vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +#, python-format +msgid "Vault" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_field.esm.js:0 +#, python-format +msgid "Vault Field" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "Vault File" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_field.esm.js:0 +#, python-format +msgid "Vault Inbox Field" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_file.esm.js:0 +#, python-format +msgid "Vault Inbox File" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__vault_right_ids +msgid "Vault Right" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Vault Share" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox_log.py:0 +#: model:ir.model,name:vault.model_vault_inbox_log +#, python-format +msgid "Vault inbox log" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "Vault is not supported" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_right.py:0 +#: model:ir.model,name:vault.model_vault_right +#, python-format +msgid "Vault rights" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#: model:ir.model,name:vault.model_vault_inbox +#, python-format +msgid "Vault share incoming secrets" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_tag.py:0 +#: model:ir.model,name:vault.model_vault_tag +#, python-format +msgid "Vault tag" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Vaults" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Verify" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__version +msgid "Version" +msgstr "Versie" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Warning" +msgstr "Waarschuwing" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_store_wizard.py:0 +#: model:ir.model,name:vault.model_vault_store_wizard +#, python-format +msgid "Wizard store a shared secret in a vault" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#: model:ir.model,name:vault.model_vault_send_wizard +#, python-format +msgid "Wizard to send another user a secret" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_write +msgid "Write" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#, python-format +msgid "Written by %(name)s via %(ip)s" +msgstr "Geschreven door %(name)s via %(ip)s" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "You can not create recursive entries." +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +msgid "" +"You can only send the secret to the user who has generated a key-pair.\n" +" If an user is not showing please ask him to generate " +"these." +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "" +"You will loose access to all vaults and your inbox. Do you want to continue?" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "a-z" +msgstr "a-z" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +msgid "or" +msgstr "of" + +#~ msgid "Users" +#~ msgstr "Gebruikers" + +#, python-format +#~ msgid "" +#~ "This will re-encrypt everything in the vault. Do you want to proceed?" +#~ msgstr "Dit zal alles in de kluis opnieuw versleutelen. Wil je doorgaan?" diff --git a/vault/i18n/vault.pot b/vault/i18n/vault.pot new file mode 100644 index 0000000000..1ff8dfa7d6 --- /dev/null +++ b/vault/i18n/vault.pot @@ -0,0 +1,1478 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * vault +# +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: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "%(action)s entry %(name)s by %(user)s" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "%s '%s' of entry '%s'" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "" +"A secure browser context is required. Please switch to https or contact your" +" administrator" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "A-Z" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault_field.py:0 +#: model:ir.model,name:vault.model_vault_abstract_field +#, python-format +msgid "Abstract model to implement basic fields for encryption" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault.py:0 +#: model:ir.model,name:vault.model_vault_abstract +#, python-format +msgid "Abstract model to implement general access rights" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__accesses +msgid "Access counter" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__active_key +msgid "Active Key" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_entry +#: model:ir.ui.menu,name:vault.menu_vault_entry +msgid "All Entries" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow all users to export vaults accessible to them" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow all users to import vaults accessible to them" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Allow the usage to share secrets with external users" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_create +msgid "Allow to create in the vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_delete +msgid "Allow to delete a vault" +msgstr "" + +#. module: vault +#: model:res.groups,name:vault.group_vault_export +msgid "Allow to export vaults" +msgstr "" + +#. module: vault +#: model:res.groups,name:vault.group_vault_import +msgid "Allow to import vaults" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_share +msgid "Allow to share a vault with new users" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_right__perm_write +msgid "Allow to write to the vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_create +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_create +msgid "Allowed Create" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_delete +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_delete +msgid "Allowed Delete" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_read +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_read +msgid "Allowed Read" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_share +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_share +msgid "Allowed Share" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_entry__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_field__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_file__allowed_write +#: model:ir.model.fields,field_description:vault.field_vault_right__allowed_write +msgid "Allowed Write" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "An error occured. Please contact the user or administrator" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "By user" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "By vault" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +#, python-format +msgid "Cancel" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Cancelled" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Characters:" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__child_ids +msgid "Child" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Childs" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_export_wizard +msgid "Close" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__entry_name +#: model:ir.model.fields,field_description:vault.field_vault_entry__complete_name +#: model:ir.model.fields,field_description:vault.field_vault_field__entry_name +#: model:ir.model.fields,field_description:vault.field_vault_file__entry_name +msgid "Complete Name" +msgstr "" + +#. module: vault +#: model:ir.model,name:vault.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Confirm your password:" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Content" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Copy to clipboard" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_create +msgid "Create" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__create_uid +#: model:ir.model.fields,field_description:vault.field_vault__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_entry__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_field__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_file__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_log__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_right__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__create_uid +#: model:ir.model.fields,field_description:vault.field_vault_tag__create_uid +msgid "Created by" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#, python-format +msgid "Created by %(name)s via %(ip)s" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#, python-format +msgid "Created by %s" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__create_date +#: model:ir.model.fields,field_description:vault.field_vault__create_date +#: model:ir.model.fields,field_description:vault.field_vault_entry__create_date +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_field__create_date +#: model:ir.model.fields,field_description:vault.field_vault_file__create_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__create_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox__create_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__create_date +#: model:ir.model.fields,field_description:vault.field_vault_log__create_date +#: model:ir.model.fields,field_description:vault.field_vault_right__create_date +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__create_date +#: model:ir.model.fields,field_description:vault.field_vault_tag__create_date +msgid "Created on" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__crypted_content +msgid "Crypted Content" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__current +msgid "Current" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Custom JSON format .json" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__content +msgid "Database" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_delete +msgid "Delete" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__display_name +#: model:ir.model.fields,field_description:vault.field_vault__display_name +#: model:ir.model.fields,field_description:vault.field_vault_entry__display_name +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_field__display_name +#: model:ir.model.fields,field_description:vault.field_vault_file__display_name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__display_name +#: model:ir.model.fields,field_description:vault.field_vault_inbox__display_name +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__display_name +#: model:ir.model.fields,field_description:vault.field_vault_log__display_name +#: model:ir.model.fields,field_description:vault.field_vault_right__display_name +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__display_name +#: model:ir.model.fields,field_description:vault.field_vault_tag__display_name +msgid "Display Name" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "Do you really want to create a new key pair and set it active?" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__content +msgid "Download" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Enter" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Enter your password:" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_open_entries +#: model:ir.model.fields,field_description:vault.field_vault__entry_ids +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__entry_id +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Entries" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_field__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_file__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_log__entry_id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__entry_id +msgid "Entry" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#: model:ir.model,name:vault.model_vault_entry +#, python-format +msgid "Entry inside a vault" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Error" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__expiration +msgid "Expiration" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__expired +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Expired" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__expire_date +msgid "Expires on" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__group_vault_export +msgid "Export Vaults" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +#, python-format +msgid "Export to file" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_export_wizard.py:0 +#: model:ir.model,name:vault.model_vault_export_wizard +#, python-format +msgid "Export wizard for vaults" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to export keys to object store" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to export the keys to the database" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Failed to import keys from database" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_field.py:0 +#: model:ir.model,name:vault.model_vault_field +#, python-format +msgid "Field of a vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__field_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__field_ids +msgid "Fields" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_file.py:0 +#: model:ir.model,name:vault.model_vault_file +#, python-format +msgid "File of a vault" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "File to share:" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__filename +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__filename +msgid "Filename" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__file_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__file_ids +msgid "Files" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__fingerprint +msgid "Fingerprint" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Generate" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Generate a new secret:" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_right_overview_search +msgid "Grouped" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Hide" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__id +#: model:ir.model.fields,field_description:vault.field_vault__id +#: model:ir.model.fields,field_description:vault.field_vault_entry__id +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_field__id +#: model:ir.model.fields,field_description:vault.field_vault_file__id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__id +#: model:ir.model.fields,field_description:vault.field_vault_inbox__id +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__id +#: model:ir.model.fields,field_description:vault.field_vault_log__id +#: model:ir.model.fields,field_description:vault.field_vault_right__id +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__id +#: model:ir.model.fields,field_description:vault.field_vault_tag__id +msgid "ID" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__expiration +msgid "If expired the inbox can't be written using the link" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__accesses +msgid "If this is 0 the inbox can't be written using the link" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Import" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__group_vault_import +msgid "Import Vaults" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +#, python-format +msgid "Import from file" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#: model:ir.model,name:vault.model_vault_import_wizard +#, python-format +msgid "Import wizard for vaults" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#: model:ir.model,name:vault.model_vault_import_wizard_path +#, python-format +msgid "Import wizard path for vaults" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_inbox +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_ids +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__inbox_id +#: model:ir.ui.menu,name:vault.menu_vault_inbox +msgid "Inbox" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_enabled +msgid "Inbox Enabled" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_link +#: model:ir.model.fields,field_description:vault.field_vault_inbox__inbox_link +msgid "Inbox Link" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__inbox_token +msgid "Inbox Token" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__include_childs +msgid "Include Childs" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Information" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_import_wizard.py:0 +#, python-format +msgid "Invalid file to import from" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/res_users_key.py:0 +#: code:addons/vault/models/res_users_key.py:0 +#: code:addons/vault/models/res_users_key.py:0 +#, python-format +msgid "Invalid parameter" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Invalid token" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "Invalidate private key" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__iterations +msgid "Iterations" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__iv +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__iv +#: model:ir.model.fields,field_description:vault.field_vault_field__iv +#: model:ir.model.fields,field_description:vault.field_vault_file__iv +#: model:ir.model.fields,field_description:vault.field_vault_inbox__iv +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__iv +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__iv +msgid "Iv" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "Keepass Database .kdbx" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__key +#: model:ir.model.fields,field_description:vault.field_vault_right__key +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__key +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__key +msgid "Key" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/user_menu.esm.js:0 +#, python-format +msgid "Key Management" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__key_user +msgid "Key User" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Keyfile:" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__keys +msgid "Keys" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key____last_update +#: model:ir.model.fields,field_description:vault.field_vault____last_update +#: model:ir.model.fields,field_description:vault.field_vault_entry____last_update +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_field____last_update +#: model:ir.model.fields,field_description:vault.field_vault_file____last_update +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path____last_update +#: model:ir.model.fields,field_description:vault.field_vault_inbox____last_update +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log____last_update +#: model:ir.model.fields,field_description:vault.field_vault_log____last_update +#: model:ir.model.fields,field_description:vault.field_vault_right____last_update +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard____last_update +#: model:ir.model.fields,field_description:vault.field_vault_tag____last_update +msgid "Last Modified on" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__write_uid +#: model:ir.model.fields,field_description:vault.field_vault__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_entry__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_field__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_file__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_log__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_right__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__write_uid +#: model:ir.model.fields,field_description:vault.field_vault_tag__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__write_date +#: model:ir.model.fields,field_description:vault.field_vault__write_date +#: model:ir.model.fields,field_description:vault.field_vault_entry__write_date +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_field__write_date +#: model:ir.model.fields,field_description:vault.field_vault_file__write_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__write_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox__write_date +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__write_date +#: model:ir.model.fields,field_description:vault.field_vault_log__write_date +#: model:ir.model.fields,field_description:vault.field_vault_right__write_date +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__write_date +#: model:ir.model.fields,field_description:vault.field_vault_tag__write_date +msgid "Last Updated on" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Length:" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__log_ids +#: model:ir.model.fields,field_description:vault.field_vault_entry__log_ids +#: model:ir.model.fields,field_description:vault.field_vault_inbox__log_ids +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Log" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#: model:ir.model,name:vault.model_vault_log +#, python-format +msgid "Log entry of a vault" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_res_users_keys +msgid "Manage my keys" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__master_key +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__master_key +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__master_key +#: model:ir.model.fields,field_description:vault.field_vault_field__master_key +#: model:ir.model.fields,field_description:vault.field_vault_file__master_key +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__master_key +#: model:ir.model.fields,field_description:vault.field_vault_right__master_key +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__master_key +msgid "Master Key" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_log__message +msgid "Message" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Missing filename" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "Missing password" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__model +msgid "Model" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_config_settings__module_vault_share +msgid "Module Vault Share" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__name +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__name +#: model:ir.model.fields,field_description:vault.field_vault_entry__name +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_field__name +#: model:ir.model.fields,field_description:vault.field_vault_file__name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__name +#: model:ir.model.fields,field_description:vault.field_vault_inbox__name +#: model:ir.model.fields,field_description:vault.field_vault_inbox_log__name +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__name +#: model:ir.model.fields,field_description:vault.field_vault_tag__name +msgid "Name" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Name of your secret:" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#, python-format +msgid "Neither a secret nor file was given" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "New inbox link" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "New private key" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "No secret found" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_inbox_value_check +#: model:ir.model.constraint,message:vault.constraint_vault_send_wizard_value_check +#, python-format +msgid "No value found" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Not Expired" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__note +#: model:ir.model.fields,field_description:vault.field_vault_entry__note +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_form +msgid "Note" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__user_id +#: model:ir.model.fields,field_description:vault.field_vault_entry__user_id +msgid "Owner" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__parent_id +msgid "Parent" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__parent_id +msgid "Parent Entry" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Password:" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__path +msgid "Path to import" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_entry__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_field__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_file__perm_user +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_user +msgid "Perm User" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/export.esm.js:0 +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Please enter the password for the database" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Please enter the password for the keepass database" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/vault.esm.js:0 +#, python-format +msgid "Please enter the password for your private key" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Please enter your password or upload a keyfile:" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Please specify a name" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__private +msgid "Private" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__public +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__public +msgid "Public" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__public_key +msgid "Public Key" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Re-encrypt" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault__reencrypt_required +msgid "Reencrypt Required" +msgstr "" + +#. module: vault +#: model:ir.actions.act_window,name:vault.action_vault_right +#: model:ir.model.fields,field_description:vault.field_vault__right_ids +#: model:ir.ui.menu,name:vault.menu_vault_right +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Rights" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__salt +msgid "Salt" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_export_file.esm.js:0 +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "Save As..." +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Save in a vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__secret +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__secret +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__secret +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Secret" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__secret_file +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__secret_file +msgid "Secret File" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__secret_temporary +msgid "Secret Temporary" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Secret to share:" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +msgid "Send" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Send the secret to an user" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_mixin.esm.js:0 +#, python-format +msgid "Send the secret to another user" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_share +msgid "Share" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#: code:addons/vault/static/src/backend/fields/templates.xml:0 +#, python-format +msgid "Show" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Something went wrong with the encryption" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "Special" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_log__state +msgid "State" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +msgid "Store" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_mixin.esm.js:0 +#, python-format +msgid "Store the secret in a vault" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.inbox +msgid "Submit secret" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/controllers/main.py:0 +#, python-format +msgid "Successfully stored" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__tags +msgid "Tags" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: code:addons/vault/models/vault_entry.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_entry_vault_uuid_uniq +#: model:ir.model.constraint,message:vault.constraint_vault_uuid_uniq +#, python-format +msgid "The UUID must be unique." +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_export_file.esm.js:0 +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "The field is empty, there's nothing to save!" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +msgid "The files must end on one of the supported file type:" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "The following entries are broken:" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/common/utils.esm.js:0 +#, python-format +msgid "The passwords aren't matching" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/abstract_vault.py:0 +#, python-format +msgid "" +"The requested operation can not be completed due to security restrictions." +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_tag.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_tag_name_uniq +#, python-format +msgid "The tag must be unique!" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_right.py:0 +#: model:ir.model.constraint,message:vault.constraint_vault_right_user_uniq +#, python-format +msgid "The user must be unique" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_inbox__token +msgid "Token" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/import.esm.js:0 +#, python-format +msgid "Unsupported file to import" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_entry__url +msgid "Url" +msgstr "" + +#. module: vault +#: model:ir.model,name:vault.model_res_users +#: model:ir.model.fields,field_description:vault.field_res_users_key__user_id +#: model:ir.model.fields,field_description:vault.field_vault_log__user_id +#: model:ir.model.fields,field_description:vault.field_vault_right__user_id +#: model:ir.model.fields,field_description:vault.field_vault_send_wizard__user_id +msgid "User" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/res_users_key.py:0 +#: model:ir.model,name:vault.model_res_users_key +#, python-format +msgid "User data of a vault" +msgstr "" + +#. module: vault +#: model:ir.model.fields,help:vault.field_vault_inbox__inbox_link +msgid "" +"Using this link you can write to the current inbox. If you want people to " +"create new inboxes you should give them your inbox link from your key " +"management." +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__uuid +#: model:ir.model.fields,field_description:vault.field_vault__uuid +#: model:ir.model.fields,field_description:vault.field_vault_entry__uuid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__uuid +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard_path__uuid +msgid "Uuid" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_field__value +#: model:ir.model.fields,field_description:vault.field_vault_file__value +msgid "Value" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault.py:0 +#: model:ir.actions.act_window,name:vault.action_vault +#: model:ir.model,name:vault.model_vault +#: model:ir.model.fields,field_description:vault.field_vault_abstract_field__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_entry__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_export_wizard__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_field__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_file__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_import_wizard__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_inbox__user_id +#: model:ir.model.fields,field_description:vault.field_vault_log__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_right__vault_id +#: model:ir.model.fields,field_description:vault.field_vault_store_wizard__vault_id +#: model:ir.ui.menu,name:vault.menu_vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +#, python-format +msgid "Vault" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_field.esm.js:0 +#, python-format +msgid "Vault Field" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_file.esm.js:0 +#, python-format +msgid "Vault File" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_field.esm.js:0 +#, python-format +msgid "Vault Inbox Field" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/fields/vault_inbox_file.esm.js:0 +#, python-format +msgid "Vault Inbox File" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users__vault_right_ids +msgid "Vault Right" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.res_config_settings_view_form +msgid "Vault Share" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox_log.py:0 +#: model:ir.model,name:vault.model_vault_inbox_log +#, python-format +msgid "Vault inbox log" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/controller.esm.js:0 +#, python-format +msgid "Vault is not supported" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_right.py:0 +#: model:ir.model,name:vault.model_vault_right +#, python-format +msgid "Vault rights" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#: model:ir.model,name:vault.model_vault_inbox +#, python-format +msgid "Vault share incoming secrets" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_tag.py:0 +#: model:ir.model,name:vault.model_vault_tag +#, python-format +msgid "Vault tag" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_entry_search +msgid "Vaults" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_form +msgid "Verify" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_res_users_key__version +msgid "Version" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_log.py:0 +#, python-format +msgid "Warning" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_store_wizard.py:0 +#: model:ir.model,name:vault.model_vault_store_wizard +#, python-format +msgid "Wizard store a shared secret in a vault" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/wizards/vault_send_wizard.py:0 +#: model:ir.model,name:vault.model_vault_send_wizard +#, python-format +msgid "Wizard to send another user a secret" +msgstr "" + +#. module: vault +#: model:ir.model.fields,field_description:vault.field_vault_right__perm_write +msgid "Write" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_inbox.py:0 +#, python-format +msgid "Written by %(name)s via %(ip)s" +msgstr "" + +#. module: vault +#. odoo-python +#: code:addons/vault/models/vault_entry.py:0 +#, python-format +msgid "You can not create recursive entries." +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +msgid "" +"You can only send the secret to the user who has generated a key-pair.\n" +" If an user is not showing please ask him to generate these." +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_users_form_keys_modif +msgid "" +"You will loose access to all vaults and your inbox. Do you want to continue?" +msgstr "" + +#. module: vault +#. odoo-javascript +#: code:addons/vault/static/src/backend/templates.xml:0 +#, python-format +msgid "a-z" +msgstr "" + +#. module: vault +#: model_terms:ir.ui.view,arch_db:vault.view_vault_import_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_send_wizard +#: model_terms:ir.ui.view,arch_db:vault.view_vault_store_wizard +msgid "or" +msgstr "" diff --git a/vault/models/__init__.py b/vault/models/__init__.py new file mode 100644 index 0000000000..d9d3e40ebe --- /dev/null +++ b/vault/models/__init__.py @@ -0,0 +1,19 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import ( + abstract_vault, + abstract_vault_field, + res_config_settings, + res_users, + res_users_key, + vault, + vault_entry, + vault_field, + vault_file, + vault_inbox, + vault_inbox_log, + vault_log, + vault_right, + vault_tag, +) diff --git a/vault/models/abstract_vault.py b/vault/models/abstract_vault.py new file mode 100644 index 0000000000..614173056d --- /dev/null +++ b/vault/models/abstract_vault.py @@ -0,0 +1,77 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, api, models +from odoo.exceptions import AccessError + +_logger = logging.getLogger(__name__) + + +class AbstractVault(models.AbstractModel): + """Models must have the following fields: + `perm_user`: The permissions are computed for this user + `allowed_read`: The current user can read from the vault + `allowed_create`: The current user can read from the vault + `allowed_write`: The current user has write access to the vault + `allowed_share`: The current user can share the vault with other users + `allowed_delete`: The current user can delete the vault or entries of it + """ + + _name = "vault.abstract" + _description = _("Abstract model to implement general access rights") + + @api.model + def raise_access_error(self): + raise AccessError( + _( + "The requested operation can not be completed due to security " + "restrictions." + ) + ) + + def check_access_rule(self, operation): + super().check_access_rule(operation) + + if self.env.su: + return + + # We have to recompute if the user of the environment changed + if self.env.user != self.mapped("perm_user"): + vault = self if self._name == "vault" else self.mapped("vault_id") + vault._compute_access() + + # Shortcut for vault.right because only the share right is required + if self._name == "vault.right": + if not self.filtered("allowed_share"): + self.raise_access_error() + return + + # Check the operation and matching permissions + if operation == "read" and not self.filtered("allowed_read"): + self.raise_access_error() + + if operation == "create" and not self.filtered("allowed_create"): + self.raise_access_error() + + if operation == "write" and not self.filtered("allowed_write"): + self.raise_access_error() + + if operation == "unlink" and not self.filtered("allowed_delete"): + self.raise_access_error() + + def _log_entry(self, msg, state): + raise NotImplementedError() + + def log_entry(self, msg): + return self._log_entry(msg, None) + + def log_info(self, msg): + return self._log_entry(msg, "info") + + def log_warn(self, msg): + return self._log_entry(msg, "warn") + + def log_error(self, msg): + return self._log_entry(msg, "error") diff --git a/vault/models/abstract_vault_field.py b/vault/models/abstract_vault_field.py new file mode 100644 index 0000000000..691d7b7d03 --- /dev/null +++ b/vault/models/abstract_vault_field.py @@ -0,0 +1,57 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, api, fields, models + +_logger = logging.getLogger(__name__) + + +class AbstractVaultField(models.AbstractModel): + _name = "vault.abstract.field" + _description = _("Abstract model to implement basic fields for encryption") + + entry_id = fields.Many2one("vault.entry", ondelete="cascade", required=True) + entry_name = fields.Char(related="entry_id.complete_name") + vault_id = fields.Many2one(related="entry_id.vault_id") + master_key = fields.Char(compute="_compute_master_key", store=False) + + perm_user = fields.Many2one(related="vault_id.perm_user", store=False) + allowed_read = fields.Boolean(related="vault_id.allowed_read", store=False) + allowed_create = fields.Boolean(related="vault_id.allowed_create", store=False) + allowed_write = fields.Boolean(related="vault_id.allowed_write", store=False) + allowed_share = fields.Boolean(related="vault_id.allowed_share", store=False) + allowed_delete = fields.Boolean(related="vault_id.allowed_delete", store=False) + + name = fields.Char(required=True) + iv = fields.Char() + + @api.depends("entry_id.vault_id.master_key") + def _compute_master_key(self): + for rec in self: + rec.master_key = rec.vault_id.master_key + + def log_change(self, action): + if self.env.context.get("vault_skip_log"): + return + + for rec in self: + rec.entry_id.log_info( + f"{action} value {rec.name} of {rec.entry_id.complete_name} " + f"by {self.env.user.display_name}" + ) + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + res.log_change("Created") + return res + + def unlink(self): + self.log_change("Deleted") + return super().unlink() + + def write(self, values): + self.log_change("Changed") + return super().write(values) diff --git a/vault/models/res_config_settings.py b/vault/models/res_config_settings.py new file mode 100644 index 0000000000..105571263f --- /dev/null +++ b/vault/models/res_config_settings.py @@ -0,0 +1,16 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + module_vault_share = fields.Boolean() + group_vault_export = fields.Boolean( + "Export Vaults", implied_group="vault.group_vault_export" + ) + group_vault_import = fields.Boolean( + "Import Vaults", implied_group="vault.group_vault_import" + ) diff --git a/vault/models/res_users.py b/vault/models/res_users.py new file mode 100644 index 0000000000..ecf5d3c91e --- /dev/null +++ b/vault/models/res_users.py @@ -0,0 +1,78 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from uuid import uuid4 + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class ResUsers(models.Model): + _inherit = "res.users" + + active_key = fields.Many2one( + "res.users.key", + compute="_compute_active_key", + store=False, + ) + keys = fields.One2many("res.users.key", "user_id", readonly=True) + vault_right_ids = fields.One2many("vault.right", "user_id", readonly=True) + inbox_ids = fields.One2many("vault.inbox", "user_id") + inbox_enabled = fields.Boolean(default=True) + inbox_link = fields.Char(compute="_compute_inbox_link", readonly=True, store=False) + inbox_token = fields.Char(default=lambda self: uuid4(), readonly=True) + + @api.depends("keys", "keys.current") + def _compute_active_key(self): + for rec in self: + keys = rec.sudo().keys.filtered("current") + rec.active_key = keys[0] if keys else None + + @api.depends("inbox_token") + def _compute_inbox_link(self): + base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url") + for rec in self: + rec.inbox_link = f"{base_url}/vault/inbox/{rec.inbox_token}" + + @api.model + def action_get_vault(self): + action = self.sudo().env.ref("vault.action_res_users_keys") + result = action.read()[0] + result["res_id"] = self.env.uid + return result + + def action_new_inbox_token(self): + self.ensure_one() + self.sudo().inbox_token = uuid4() + return self.action_get_vault() + + def action_invalidate_key(self): + """Disable the current key and remove all accesses to the vaults""" + self.ensure_one() + self.keys.write({"current": False}) + self.vault_right_ids.sudo().unlink() + self.inbox_ids.unlink() + self.env["vault"].search([])._compute_access() + return self.action_get_vault() + + @api.model + def find_user_of_inbox(self, token): + return self.search([("inbox_token", "=", token), ("inbox_enabled", "=", True)]) + + def get_vault_keys(self): + self.ensure_one() + + if not self.active_key: + return {} + + return { + "iterations": self.active_key.iterations, + "iv": self.active_key.iv, + "private": self.active_key.private, + "public": self.active_key.public, + "salt": self.active_key.salt, + "uuid": self.active_key.uuid, + "version": self.active_key.version, + } diff --git a/vault/models/res_users_key.py b/vault/models/res_users_key.py new file mode 100644 index 0000000000..6c3ae5bc1b --- /dev/null +++ b/vault/models/res_users_key.py @@ -0,0 +1,82 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +import re +from hashlib import sha256 +from uuid import uuid4 + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class ResUsersKey(models.Model): + _name = "res.users.key" + _description = _("User data of a vault") + _rec_name = "fingerprint" + _order = "create_date DESC" + + user_id = fields.Many2one("res.users", required=True) + uuid = fields.Char(default=lambda self: uuid4(), required=True, readonly=True) + current = fields.Boolean(default=True, readonly=True) + fingerprint = fields.Char(compute="_compute_fingerprint", store=True) + public = fields.Char(required=True, readonly=True) + salt = fields.Char(required=True, readonly=True) + iv = fields.Char(required=True, readonly=True) + iterations = fields.Integer(required=True, readonly=True) + version = fields.Integer(readonly=True) + # Encrypted with master password of user + private = fields.Char(required=True, readonly=True) + + @api.depends("public") + def _compute_fingerprint(self): + for rec in self: + if rec.public: + hashed = sha256(rec.public.encode()).hexdigest() + rec.fingerprint = ":".join(re.findall(r".{2}", hashed)) + else: + rec.fingerprint = False + + def _prepare_values(self, iterations, iv, private, public, salt, version): + return { + "iterations": iterations, + "iv": iv, + "private": private, + "public": public, + "salt": salt, + "user_id": self.env.uid, + "current": True, + "version": version, + } + + def store(self, iterations, iv, private, public, salt, version): + if not all(isinstance(x, str) and x for x in [public, private, iv, salt]): + raise ValidationError(_("Invalid parameter")) + + if not isinstance(iterations, int) or iterations < 4000: + raise ValidationError(_("Invalid parameter")) + + if not isinstance(version, int): + raise ValidationError(_("Invalid parameter")) + + domain = [ + ("user_id", "=", self.env.uid), + ("private", "=", private), + ] + key = self.search(domain) + if not key: + # Disable all current keys + self.env.user.keys.write({"current": False}) + + rec = self.create( + self._prepare_values(iterations, iv, private, public, salt, version) + ) + return rec.uuid + + return False + + def extract_public_key(self, user): + user = self.sudo().search([("user_id", "=", user), ("current", "=", True)]) + return user.public or None diff --git a/vault/models/vault.py b/vault/models/vault.py new file mode 100644 index 0000000000..5aef99f230 --- /dev/null +++ b/vault/models/vault.py @@ -0,0 +1,165 @@ +# © 2021-2024 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from uuid import uuid4 + +from odoo import _, api, fields, models + +_logger = logging.getLogger(__name__) + + +class Vault(models.Model): + _name = "vault" + _description = _("Vault") + _inherit = ["vault.abstract"] + _order = "name" + + user_id = fields.Many2one( + "res.users", + "Owner", + readonly=True, + default=lambda self: self.env.user, + required=True, + ) + right_ids = fields.One2many( + "vault.right", + "vault_id", + "Rights", + default=lambda self: self._get_default_rights(), + ) + entry_ids = fields.One2many("vault.entry", "vault_id", "Entries") + field_ids = fields.One2many("vault.field", "vault_id", "Fields") + file_ids = fields.One2many("vault.file", "vault_id", "Files") + log_ids = fields.One2many("vault.log", "vault_id", "Log", readonly=True) + reencrypt_required = fields.Boolean(default=False) + + # Access control + perm_user = fields.Many2one("res.users", compute="_compute_access", store=False) + allowed_read = fields.Boolean(compute="_compute_access", store=False) + allowed_create = fields.Boolean(compute="_compute_access", store=False) + allowed_share = fields.Boolean(compute="_compute_access", store=False) + allowed_write = fields.Boolean(compute="_compute_access", store=False) + allowed_delete = fields.Boolean(compute="_compute_access", store=False) + + master_key = fields.Char( + compute="_compute_master_key", + inverse="_inverse_master_key", + store=False, + ) + + uuid = fields.Char(default=lambda self: uuid4(), required=True, readonly=True) + name = fields.Char(required=True) + note = fields.Text() + + _sql_constraints = [ + ("uuid_uniq", "UNIQUE(uuid)", _("The UUID must be unique.")), + ] + + @api.depends("right_ids.user_id") + def _compute_access(self): + user = self.env.user + for rec in self.sudo(): + rec.perm_user = user.id + + if user == rec.user_id: + rec.write( + { + "allowed_create": True, + "allowed_share": True, + "allowed_write": True, + "allowed_delete": True, + "allowed_read": True, + } + ) + continue + + rights = rec.right_ids + rec.allowed_read = user in rights.mapped("user_id") + rec.allowed_create = user in rights.filtered("perm_create").mapped( + "user_id" + ) + rec.allowed_share = user in rights.filtered("perm_share").mapped("user_id") + rec.allowed_write = user in rights.filtered("perm_write").mapped("user_id") + rec.allowed_delete = user in rights.filtered("perm_delete").mapped( + "user_id" + ) + + @api.depends("right_ids.key") + def _compute_master_key(self): + domain = [("user_id", "=", self.env.uid)] + for rec in self: + rights = rec.right_ids.filtered_domain(domain) + rec.master_key = rights[0].key if rights else False + + def _inverse_master_key(self): + domain = [("user_id", "=", self.env.uid)] + for rec in self: + rights = rec.right_ids.filtered_domain(domain) + if rights and not rights.key: + rights.key = rec.master_key + + def _get_default_rights(self): + return [ + ( + 0, + 0, + { + "user_id": self.env.uid, + "perm_create": True, + "perm_write": True, + "perm_delete": True, + "perm_share": True, + }, + ) + ] + + def _log_entry(self, msg, state): + self.ensure_one() + return ( + self.env["vault.log"] + .sudo() + .create( + { + "vault_id": self.id, + "user_id": self.env.uid, + "message": msg, + "state": state, + } + ) + ) + + def share_public_keys(self): + self.ensure_one() + result = [] + for right in self.right_ids: + result.append({"user": right.user_id.id, "public": right.public_key}) + return result + + def action_open_import_wizard(self): + self.ensure_one() + wizard = self.env.ref("vault.view_vault_import_wizard") + return { + "name": _("Import from file"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "vault.import.wizard", + "views": [(wizard.id, "form")], + "view_id": wizard.id, + "target": "new", + "context": {"default_vault_id": self.id}, + } + + def action_open_export_wizard(self): + self.ensure_one() + wizard = self.env.ref("vault.view_vault_export_wizard") + return { + "name": _("Export to file"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "vault.export.wizard", + "views": [(wizard.id, "form")], + "view_id": wizard.id, + "target": "new", + "context": {"default_vault_id": self.id}, + } diff --git a/vault/models/vault_entry.py b/vault/models/vault_entry.py new file mode 100644 index 0000000000..1f553c3561 --- /dev/null +++ b/vault/models/vault_entry.py @@ -0,0 +1,215 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from datetime import datetime +from uuid import uuid4 + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class VaultEntry(models.Model): + _name = "vault.entry" + _description = _("Entry inside a vault") + _inherit = ["vault.abstract"] + _order = "complete_name" + _rec_name = "complete_name" + + parent_id = fields.Many2one( + "vault.entry", + "Parent", + ondelete="cascade", + domain="[('vault_id', '=', vault_id)]", + ) + child_ids = fields.One2many("vault.entry", "parent_id", "Child") + + vault_id = fields.Many2one("vault", "Vault", ondelete="cascade", required=True) + user_id = fields.Many2one(related="vault_id.user_id") + field_ids = fields.One2many("vault.field", "entry_id", "Fields") + file_ids = fields.One2many("vault.file", "entry_id", "Files") + log_ids = fields.One2many("vault.log", "entry_id", "Log", readonly=True) + + perm_user = fields.Many2one(related="vault_id.perm_user", store=False) + allowed_read = fields.Boolean(related="vault_id.allowed_read", store=False) + allowed_create = fields.Boolean(related="vault_id.allowed_create", store=False) + allowed_share = fields.Boolean(related="vault_id.allowed_share", store=False) + allowed_write = fields.Boolean(related="vault_id.allowed_write", store=False) + allowed_delete = fields.Boolean(related="vault_id.allowed_delete", store=False) + + complete_name = fields.Char( + compute="_compute_complete_name", + store=True, + readonly=True, + recursive=True, + ) + uuid = fields.Char(default=lambda self: uuid4(), required=True, copy=False) + name = fields.Char(required=True) + url = fields.Char() + note = fields.Text() + tags = fields.Many2many("vault.tag") + expire_date = fields.Datetime("Expires on", default=False) + expired = fields.Boolean( + compute="_compute_expired", + search="_search_expired", + store=False, + ) + + _sql_constraints = [ + ("vault_uuid_uniq", "UNIQUE(vault_id, uuid)", _("The UUID must be unique.")), + ] + + @api.constrains("parent_id") + def _check_parent_id(self): + if not self._check_recursion(): + raise ValidationError(_("You can not create recursive entries.")) + + @api.depends("name", "parent_id.complete_name") + def _compute_complete_name(self): + for rec in self: + if rec.parent_id: + rec.complete_name = f"{rec.parent_id.complete_name} / {rec.name}" + else: + rec.complete_name = rec.name + + @api.model + def search_panel_select_range(self, field_name, **kwargs): + """We add the following contexts related to searchpanel: + - entry_short_name: Show just the name instead of full path. + - from_search_panel: It will be used to overwrite domain. + Remove the limit of records (default is 200). + """ + return super( + VaultEntry, + self.with_context(from_search_panel=True, entry_short_name=True), + ).search_panel_select_range(field_name, **kwargs) + + def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None): + """Changes related to searchpanel: + - Add a domain to only show records with children. + """ + domain = domain if domain else [] + if self.env.context.get("from_search_panel"): + domain += [("child_ids", "!=", False)] + return super().search_read( + domain=domain, fields=fields, offset=offset, limit=limit, order=order + ) + + def copy_data(self, default=None): + self.ensure_one() + + if default is None: + default = {} + + if "name" not in default: + default["name"] = _("%s (copy)", self.name) + + if "field_ids" not in default: + default["field_ids"] = [ + (0, 0, field.copy_data()[0]) for field in self.field_ids + ] + if "file_ids" not in default: + default["file_ids"] = [ + (0, 0, field.copy_data()[0]) for field in self.file_ids + ] + return super().copy_data(default) + + @api.depends("name", "complete_name") + def _compute_display_name(self): + if not self.env.context.get("entry_short_name", False): + return super()._compute_display_name() + for record in self: + record.display_name = record.name + + @api.depends("expire_date") + def _compute_expired(self): + now = datetime.now() + for rec in self: + rec.expired = rec.expire_date and now > rec.expire_date + + def _search_expired(self, operator, value): + if (operator not in ["=", "!="]) or (value not in [True, False]): + return [] + + if (operator, value) in [("=", True), ("!=", False)]: + return [("expire_date", "<", datetime.now())] + + return ["|", ("expire_date", ">=", datetime.now()), ("expire_date", "=", False)] + + def log_change(self, action): + if self.env.context.get("vault_skip_log"): + return + + for rec in self: + rec.log_info( + _("%(action)s entry %(name)s by %(user)s") + % { + "action": action, + "name": rec.complete_name, + "user": rec.env.user.display_name, + } + ) + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + res.log_change("Created") + return res + + def unlink(self): + self.log_change("Deleted") + + return super().unlink() + + def _log_entry(self, msg, state): + self.ensure_one() + return ( + self.env["vault.log"] + .sudo() + .create( + { + "vault_id": self.vault_id.id, + "entry_id": self.id, + "user_id": self.env.uid, + "message": msg, + "state": state, + } + ) + ) + + def action_open_import_wizard(self): + self.ensure_one() + wizard = self.env.ref("vault.view_vault_import_wizard") + return { + "name": _("Import from file"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "vault.import.wizard", + "views": [(wizard.id, "form")], + "view_id": wizard.id, + "target": "new", + "context": { + "default_vault_id": self.vault_id.id, + "default_parent_id": self.id, + }, + } + + def action_open_export_wizard(self): + self.ensure_one() + wizard = self.env.ref("vault.view_vault_export_wizard") + return { + "name": _("Export to file"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "vault.export.wizard", + "views": [(wizard.id, "form")], + "view_id": wizard.id, + "target": "new", + "context": { + "default_vault_id": self.vault_id.id, + "default_entry_id": self.id, + }, + } diff --git a/vault/models/vault_field.py b/vault/models/vault_field.py new file mode 100644 index 0000000000..26490b26e0 --- /dev/null +++ b/vault/models/vault_field.py @@ -0,0 +1,17 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, fields, models + +_logger = logging.getLogger(__name__) + + +class VaultField(models.Model): + _name = "vault.field" + _description = _("Field of a vault") + _order = "name" + _inherit = ["vault.abstract.field", "vault.abstract"] + + value = fields.Char(required=True) diff --git a/vault/models/vault_file.py b/vault/models/vault_file.py new file mode 100644 index 0000000000..011412d38e --- /dev/null +++ b/vault/models/vault_file.py @@ -0,0 +1,25 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, api, fields, models + +_logger = logging.getLogger(__name__) + + +class VaultFile(models.Model): + _name = "vault.file" + _description = _("File of a vault") + _order = "name" + _inherit = ["vault.abstract.field", "vault.abstract"] + + value = fields.Binary(attachment=False) + + @api.model + def search_read(self, *args, **kwargs): + if self.env.context.get("vault_reencrypt"): + return super(VaultFile, self.with_context(bin_size=False)).search_read( + *args, **kwargs + ) + return super().search_read(*args, **kwargs) diff --git a/vault/models/vault_inbox.py b/vault/models/vault_inbox.py new file mode 100644 index 0000000000..d8c8028e22 --- /dev/null +++ b/vault/models/vault_inbox.py @@ -0,0 +1,114 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from datetime import datetime, timedelta +from uuid import uuid4 + +from odoo import _, api, fields, models + +_logger = logging.getLogger(__name__) + + +class VaultInbox(models.Model): + _name = "vault.inbox" + _description = _("Vault share incoming secrets") + + token = fields.Char(default=lambda self: uuid4(), readonly=True, copy=False) + inbox_link = fields.Char( + compute="_compute_inbox_link", + readonly=True, + help="Using this link you can write to the current inbox. If you want people " + "to create new inboxes you should give them your inbox link from your key " + "management.", + ) + user_id = fields.Many2one( + "res.users", + "Vault", + required=True, + ) + name = fields.Char(required=True) + secret = fields.Char(readonly=True) + filename = fields.Char() + secret_file = fields.Binary(attachment=False, readonly=True) + key = fields.Char(required=True) + iv = fields.Char(required=True) + accesses = fields.Integer( + "Access counter", + default=1, + help="If this is 0 the inbox can't be written using the link", + ) + expiration = fields.Datetime( + default=lambda self: datetime.now() + timedelta(days=7), + help="If expired the inbox can't be written using the link", + ) + log_ids = fields.One2many("vault.inbox.log", "inbox_id", "Log", readonly=True) + + _sql_constraints = [ + ( + "value_check", + "CHECK(secret IS NOT NULL OR secret_file IS NOT NULL)", + _("No value found"), + ), + ] + + @api.depends("token") + def _compute_inbox_link(self): + base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url") + for rec in self: + rec.inbox_link = f"{base_url}/vault/inbox/{rec.token}" + + def read(self, *args, **kwargs): + # Always load the binary instead of the size + return super(VaultInbox, self.with_context(bin_size=False)).read( + *args, **kwargs + ) + + @api.model + def find_inbox(self, token): + return self.search([("token", "=", token)]) + + def store_in_inbox( + self, + name, + secret, + secret_file, + iv, + key, + user, + filename, + ip=None, + ): + log_info = {"name": user.name, "ip": ip or "n/a"} + if len(self) == 0: + log = _("Created by %(name)s via %(ip)s") % log_info + return self.create( + { + "name": name, + "accesses": 0, + "iv": iv, + "key": key, + "secret": secret or None, + "secret_file": secret_file or None, + "filename": filename, + "user_id": user.id, + "log_ids": [(0, 0, {"name": log})], + } + ) + + self.ensure_one() + if self.accesses > 0 and datetime.now() < self.expiration: + log = _("Written by %(name)s via %(ip)s") % log_info + + self.write( + { + "accesses": self.accesses - 1, + "iv": iv, + "key": key, + "secret": secret or None, + "secret_file": secret_file or None, + "filename": filename, + "log_ids": [(0, 0, {"name": log})], + } + ) + return self diff --git a/vault/models/vault_inbox_log.py b/vault/models/vault_inbox_log.py new file mode 100644 index 0000000000..e072283624 --- /dev/null +++ b/vault/models/vault_inbox_log.py @@ -0,0 +1,22 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, fields, models + +_logger = logging.getLogger(__name__) + + +class VaultInboxLog(models.Model): + _name = "vault.inbox.log" + _description = _("Vault inbox log") + _order = "create_date DESC" + + inbox_id = fields.Many2one( + "vault.inbox", + ondelete="cascade", + readonly=True, + required=True, + ) + name = fields.Char(readonly=True) diff --git a/vault/models/vault_log.py b/vault/models/vault_log.py new file mode 100644 index 0000000000..3f44569c53 --- /dev/null +++ b/vault/models/vault_log.py @@ -0,0 +1,46 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo import _, api, fields, models + +_logger = logging.getLogger(__name__) + + +class VaultLog(models.Model): + _name = "vault.log" + _description = _("Log entry of a vault") + _order = "create_date DESC" + _rec_name = "message" + + vault_id = fields.Many2one( + "vault", + "Vault", + ondelete="cascade", + required=True, + readonly=True, + ) + entry_id = fields.Many2one( + "vault.entry", + "Entry", + ondelete="cascade", + readonly=True, + ) + user_id = fields.Many2one("res.users", "User", required=True, readonly=True) + state = fields.Selection(lambda self: self._get_log_state(), readonly=True) + message = fields.Char(readonly=True, required=True) + + def _get_log_state(self): + return [ + ("info", _("Information")), + ("warn", _("Warning")), + ("error", _("Error")), + ] + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + if not self.env.context.get("skip_log", False): + _logger.info("Vault log: %s", res.message) + return res diff --git a/vault/models/vault_right.py b/vault/models/vault_right.py new file mode 100644 index 0000000000..1f9fc3bc77 --- /dev/null +++ b/vault/models/vault_right.py @@ -0,0 +1,110 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models + + +class VaultRight(models.Model): + _name = "vault.right" + _description = _("Vault rights") + _inherit = ["vault.abstract"] + _order = "user_id" + + vault_id = fields.Many2one( + "vault", + "Vault", + readonly=True, + required=True, + ondelete="cascade", + ) + master_key = fields.Char(related="vault_id.master_key", readonly=True, store=False) + user_id = fields.Many2one( + "res.users", + "User", + domain=[("keys", "!=", False)], + required=True, + ) + public_key = fields.Char(compute="_compute_public_key", readonly=True, store=False) + perm_create = fields.Boolean( + "Create", + default=lambda self: self._get_is_owner(), + help="Allow to create in the vault", + ) + perm_write = fields.Boolean( + "Write", + default=lambda self: self._get_is_owner(), + help="Allow to write to the vault", + ) + perm_share = fields.Boolean( + "Share", + default=lambda self: self._get_is_owner(), + help="Allow to share a vault with new users", + ) + perm_delete = fields.Boolean( + "Delete", + default=lambda self: self._get_is_owner(), + help="Allow to delete a vault", + ) + + perm_user = fields.Many2one(related="vault_id.perm_user", store=False) + allowed_read = fields.Boolean(related="vault_id.allowed_read", store=False) + allowed_create = fields.Boolean(related="vault_id.allowed_create", store=False) + allowed_write = fields.Boolean(related="vault_id.allowed_write", store=False) + allowed_share = fields.Boolean(related="vault_id.allowed_share", store=False) + allowed_delete = fields.Boolean(related="vault_id.allowed_delete", store=False) + + # Encrypted with the public key of the user + key = fields.Char() + + _sql_constraints = ( + ("user_uniq", "UNIQUE(user_id, vault_id)", _("The user must be unique")), + ) + + def _get_is_owner(self): + return self.env.user == self.vault_id.user_id + + @api.depends("user_id") + def _compute_public_key(self): + for rec in self: + rec.public_key = rec.user_id.active_key.public + + def log_access(self): + for rec in self: + rights = ", ".join( + sorted( + ["read"] + + [ + right + for right in ["create", "write", "share", "delete"] + if getattr(rec, f"perm_{right}", False) + ] + ) + ) + + rec.vault_id.log_info( + f"Grant access to user {rec.user_id.display_name}: {rights}" + ) + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + if not res.allowed_share and not res.env.su: + self.raise_access_error() + + res.log_access() + return res + + def write(self, values): + res = super().write(values) + perms = ["perm_write", "perm_delete", "perm_share", "perm_create"] + if any(x in values for x in perms): + self.log_access() + + return res + + def unlink(self): + for rec in self: + rec.vault_id.log_info(f"Removed user {self.user_id.display_name}") + rec.vault_id.reencrypt_required = True + + return super().unlink() diff --git a/vault/models/vault_tag.py b/vault/models/vault_tag.py new file mode 100644 index 0000000000..f50ae6de88 --- /dev/null +++ b/vault/models/vault_tag.py @@ -0,0 +1,16 @@ +# © 2021 Florian Kantelberg - initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, fields, models + + +class VaultTag(models.Model): + _name = "vault.tag" + _description = _("Vault tag") + _order = "name" + + name = fields.Char(required=True) + + _sql_constraints = [ + ("name_uniq", "unique(name)", _("The tag must be unique!")), + ] diff --git a/vault/readme/CONTRIBUTORS.rst b/vault/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..e202826121 --- /dev/null +++ b/vault/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Florian Kantelberg diff --git a/vault/readme/DESCRIPTION.rst b/vault/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..50cf3c7679 --- /dev/null +++ b/vault/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +This module implements a vault for secrets and files using end-to-end-encryption. The encryption and decryption happens in the browser using a vault specific shared master key. The master keys are encrypted using asymmetrically. For this the user has to enter a second password on the first login or if he needs to access data in a vault. The asymmetric keys are stored for a certain time in the browser storage. + +The server can never access the secrets with the information available. Only people registered in the vault can decrypt or encrypt values in a vault. The meta data isn't encrypted to be able to search/filter for entries more easily. + +This modules requires a secure context for the browser to work properly and therefore HTTPS support is required. + +The `vault-recovery `_ project focuses on disaster recovery in case of an incident to recover secrets from old database backups or old exports. diff --git a/vault/readme/ROADMAP.rst b/vault/readme/ROADMAP.rst new file mode 100644 index 0000000000..ccaf5abc1d --- /dev/null +++ b/vault/readme/ROADMAP.rst @@ -0,0 +1,14 @@ +* Field and file history for restoration + +* Import improvement + + * Support challenge-response/FIDO2 + * Support for argon2 and kdbx v4 + +* When changing an entry from one vault to another existing vault, the values added on + this entry cannot be accessed, so the field vault is going to be readonly when it + is defined. + + If you want to move entries between vaults you can use the export -> import option. + +* HTTPS or localhost (secure browser context) is required for the client side encryption diff --git a/vault/security/ir.model.access.csv b/vault/security/ir.model.access.csv new file mode 100644 index 0000000000..0863b98aa8 --- /dev/null +++ b/vault/security/ir.model.access.csv @@ -0,0 +1,16 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_vault,access_vault,model_vault,base.group_user,1,1,1,1 +access_vault_entry,access_vault_entry,model_vault_entry,base.group_user,1,1,1,1 +access_vault_export_wizard,access_vault_export_wizard,model_vault_export_wizard,base.group_user,1,1,1,1 +access_vault_field,access_vault_field,model_vault_field,base.group_user,1,1,1,1 +access_vault_file,access_vault_file,model_vault_file,base.group_user,1,1,1,1 +access_vault_import_wizard,access_vault_import_wizard,model_vault_import_wizard,base.group_user,1,1,1,1 +access_vault_import_wizard_path,access_vault_import_wizard_path,model_vault_import_wizard_path,base.group_user,1,1,1,1 +access_vault_inbox,access_vault_inbox,model_vault_inbox,base.group_user,1,1,1,1 +access_vault_inbox_log,access_vault_inbox_log,model_vault_inbox_log,base.group_user,1,1,1,1 +access_vault_log,access_vault_log,model_vault_log,base.group_user,1,0,0,0 +access_vault_right,access_vault_right,model_vault_right,base.group_user,1,1,1,1 +access_vault_send_wizard,access_vault_send_wizard,model_vault_send_wizard,base.group_user,1,1,1,1 +access_vault_store_wizard,access_vault_store_wizard,model_vault_store_wizard,base.group_user,1,1,1,1 +access_vault_tag,access_vault_tag,model_vault_tag,base.group_user,1,1,1,1 +access_vault_users_key,access_res_users_key,model_res_users_key,base.group_user,1,1,1,1 diff --git a/vault/security/ir_rule.xml b/vault/security/ir_rule.xml new file mode 100644 index 0000000000..13f7cdb45f --- /dev/null +++ b/vault/security/ir_rule.xml @@ -0,0 +1,111 @@ + + + + vault.access.default + + ['|', ('user_id', '=', user.id), ('right_ids.user_id', '=', user.id)] + + + + + + + + + vault.log.access.read + + ['|', ('vault_id.user_id', '=', user.id), ('vault_id.right_ids.user_id', '=', user.id)] + + + + + + + + + vault.entry.access.default + + ['|', ('vault_id.user_id', '=', user.id), ('vault_id.right_ids.user_id', '=', user.id)] + + + + + + + + + vault.field.access.default + + ['|', ('vault_id.user_id', '=', user.id), ('vault_id.right_ids.user_id', '=', user.id)] + + + + + + + + + vault.file.access.default + + ['|', ('vault_id.user_id', '=', user.id), ('vault_id.right_ids.user_id', '=', user.id)] + + + + + + + + + res.users.key.access.default + + [('user_id', '=', user.id)] + + + + + + + + + vault.inbox.access.owner + + [('user_id', '=', user.id)] + + + + + + + + vault.right.access.default + + [('vault_id.right_ids.user_id', '=', user.id)] + + + + + + + + + vault.inbox.log.access.owner + + [('inbox_id.user_id', '=', user.id)] + + + + + + diff --git a/vault/security/vault_security.xml b/vault/security/vault_security.xml new file mode 100644 index 0000000000..a810f29538 --- /dev/null +++ b/vault/security/vault_security.xml @@ -0,0 +1,13 @@ + + + + Allow to export vaults + + + + + Allow to import vaults + + + + diff --git a/vault/static/description/icon.png b/vault/static/description/icon.png new file mode 100644 index 0000000000..a0c9035d9b Binary files /dev/null and b/vault/static/description/icon.png differ diff --git a/vault/static/description/index.html b/vault/static/description/index.html new file mode 100644 index 0000000000..99cd2f80d1 --- /dev/null +++ b/vault/static/description/index.html @@ -0,0 +1,447 @@ + + + + + + +Vault + + + +
+

Vault

+ + +

Beta License: AGPL-3 OCA/server-auth Translate me on Weblate Try me on Runboat

+

This module implements a vault for secrets and files using end-to-end-encryption. The encryption and decryption happens in the browser using a vault specific shared master key. The master keys are encrypted using asymmetrically. For this the user has to enter a second password on the first login or if he needs to access data in a vault. The asymmetric keys are stored for a certain time in the browser storage.

+

The server can never access the secrets with the information available. Only people registered in the vault can decrypt or encrypt values in a vault. The meta data isn’t encrypted to be able to search/filter for entries more easily.

+

This modules requires a secure context for the browser to work properly and therefore HTTPS support is required.

+

The vault-recovery project focuses on disaster recovery in case of an incident to recover secrets from old database backups or old exports.

+

Table of contents

+ +
+

Known issues / Roadmap

+
    +
  • Field and file history for restoration
  • +
  • Import improvement
  • +
+
+
    +
  • Support challenge-response/FIDO2
  • +
  • Support for argon2 and kdbx v4
  • +
+
+
    +
  • When changing an entry from one vault to another existing vault, the values added on +this entry cannot be accessed, so the field vault is going to be readonly when it +is defined.

    +

    If you want to move entries between vaults you can use the export -> import option.

    +
  • +
  • HTTPS or localhost (secure browser context) is required for the client side encryption

    +
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • initOS GmbH
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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/server-auth project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/vault/static/lib/kdbxweb/kdbxweb.min.js b/vault/static/lib/kdbxweb/kdbxweb.min.js new file mode 100644 index 0000000000..eee616aa20 --- /dev/null +++ b/vault/static/lib/kdbxweb/kdbxweb.min.js @@ -0,0 +1,2 @@ +/*! kdbxweb v1.10.0, (c) 2020 Antelle, opensource.org/licenses/MIT */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("crypto"),require("xmldom")):"function"==typeof define&&define.amd?define(["crypto","xmldom"],t):"object"==typeof exports?exports.kdbxweb=t(require("crypto"),require("xmldom")):e.kdbxweb=t(e.crypto,e.xmldom)}(this,(function(e,t){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(i,n,function(t){return e[t]}.bind(null,n));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=29)}([function(e,t,r){"use strict";(function(t){var i=t.TextEncoder,n=t.TextDecoder;if(!i||!n){var o=r(40);i=o.TextEncoder,n=o.TextDecoder}var a=new i,s=new n;e.exports.arrayBufferEquals=function(e,t){if(e.byteLength!==t.byteLength)return!1;for(var r=new Uint8Array(e),i=new Uint8Array(t),n=0,o=r.length;n0;){var r=e%65536;r=r>0?r:65536;var i=new Uint8Array(r);s.getRandomValues(i),e-=r,t.set(i,e)}return t}(e);if(h)return new Uint8Array(h.randomBytes(e));throw new n(o.ErrorCodes.NotImplemented,"Random not implemented")},e.exports.createAesCbc=function(){if(d)return new u;if(h)return new l;throw new n(o.ErrorCodes.NotImplemented,"AES-CBC not implemented")},e.exports.chacha20=function(e,t,r){return Promise.resolve().then((function(){var n=new a(new Uint8Array(t),new Uint8Array(r));return i.arrayToBuffer(n.encrypt(new Uint8Array(e)))}))},e.exports.argon2=function(e,t,r,i,a,s,d,h){return Promise.reject(new n(o.ErrorCodes.NotImplemented,"Argon2 not implemented"))},e.exports.configure=function(e,t,r){d=e,s=t,h=r}}).call(this,r(13))},function(e,t,r){"use strict";(function(t){var i=r(2),n=r(1),o=r(6),a=r(7),s=r(9),d=r(0),h=r(8),u=r(16),l=/\.\d\d\d/,c=t.DOMParser?t:r(44),f=t.DOMParser?void 0:{errorHandler:{error:function(e){throw e},fatalError:function(e){throw e}}},p=62135596800;function m(e){var t,r=f?new c.DOMParser(f):new c.DOMParser;try{t=r.parseFromString(e,"application/xml")}catch(e){throw new i(n.ErrorCodes.FileCorrupt,"bad xml: "+e.message)}if(!t.documentElement)throw new i(n.ErrorCodes.FileCorrupt,"bad xml");var o=t.getElementsByTagName("parsererror")[0];if(o)throw new i(n.ErrorCodes.FileCorrupt,"bad xml: "+o.textContent);return t}function y(e,t){var r=e.childNodes.length;if(0!==r){for(var i,n="\n"+" ".repeat(t),o=t>0?"\n"+" ".repeat(t-1):"",a=e.ownerDocument||e,s=[],d=0;d0){var l=a.createTextNode(o);e.appendChild(l)}y(i,t+1)}}}function g(e){if(e&&e.childNodes)return e.protectedValue?e.protectedValue.text:e.textContent}function _(e,t){e.textContent=t||""}function b(e){var t=g(e);return t?d.arrayToBuffer(d.base64ToBytes(t)):void 0}function v(e,t){"string"==typeof t&&(t=d.base64ToBytes(t)),_(e,t?d.bytesToBase64(d.arrayToBuffer(t)):void 0)}function w(e){switch(e&&e.toLowerCase&&e.toLowerCase()){case"true":return!0;case"false":return!1;case"null":return null}}function k(e,t){t(e);for(var r=0,i=e.childNodes,n=i.length;r)<'+e+"/>")},e.exports.getChildNode=function(e,t,r){if(e&&e.childNodes)for(var o=0,a=e.childNodes,s=a.length;o0)return new Date(t);var r=new DataView(d.arrayToBuffer(d.base64ToBytes(t))),i=new h(r.getUint32(0,!0),r.getUint32(4,!0)).value;return new Date(1e3*(i-p))}},e.exports.setDate=function(e,t,r){if(t)if(r){var i=Math.floor(t.getTime()/1e3)+p,n=new DataView(new ArrayBuffer(8)),o=h.from(i);n.setUint32(0,o.lo,!0),n.setUint32(4,o.hi,!0),_(e,d.bytesToBase64(n.buffer))}else _(e,t.toISOString().replace(l,""));else _(e,"")},e.exports.getNumber=function(e){var t=g(e);return t?+t:void 0},e.exports.setNumber=function(e,t){_(e,"number"!=typeof t||isNaN(t)?void 0:t.toString())},e.exports.getBoolean=function(e){var t=g(e);return t?w(t):void 0},e.exports.setBoolean=function(e,t){_(e,void 0===t?"":null===t?"null":t?"True":"False")},e.exports.strToBoolean=w,e.exports.getUuid=function(e){var t=b(e);return t?new a(t):void 0},e.exports.setUuid=function(e,t){v(e,t instanceof a?t.toBytes():t)},e.exports.getProtectedText=function(e){return e.protectedValue||e.textContent},e.exports.setProtectedText=function(e,t){t instanceof s?(e.protectedValue=t,e.setAttribute(o.Attr.Protected,"True")):_(e,t)},e.exports.getProtectedBinary=function(e){if(e.protectedValue)return e.protectedValue;var t=e.textContent,r=e.getAttribute(o.Attr.Ref);if(r)return{ref:r};if(t){var i=w(e.getAttribute(o.Attr.Compressed)),n=d.base64ToBytes(t);return i&&(n=u.ungzip(n)),d.arrayToBuffer(n)}},e.exports.setProtectedBinary=function(e,t){t instanceof s?(e.protectedValue=t,e.setAttribute(o.Attr.Protected,"True")):t&&t.ref?e.setAttribute(o.Attr.Ref,t.ref):v(e,t)},e.exports.setProtectedValues=function(e,t){k(e,(function(e){if(w(e.getAttribute(o.Attr.Protected)))try{var r=d.arrayToBuffer(d.base64ToBytes(e.textContent));if(r.byteLength){var a=t.getSalt(r.byteLength);e.protectedValue=new s(r,a)}}catch(t){throw new i(n.ErrorCodes.FileCorrupt,"bad protected value at line "+e.lineNumber+": "+t)}}))},e.exports.updateProtectedValuesSalt=function(e,t){k(e,(function(e){if(w(e.getAttribute(o.Attr.Protected))&&e.protectedValue){var r=t.getSalt(e.protectedValue.byteLength);e.protectedValue.setSalt(r),e.textContent=e.protectedValue.toString()}}))},e.exports.unprotectValues=function(e){k(e,(function(e){w(e.getAttribute(o.Attr.Protected))&&e.protectedValue&&(e.removeAttribute(o.Attr.Protected),e.setAttribute(o.Attr.ProtectedInMemPlainXml,"True"),e.textContent=e.protectedValue.getText())}))},e.exports.protectUnprotectedValues=function(e){k(e,(function(e){w(e.getAttribute(o.Attr.ProtectedInMemPlainXml))&&e.protectedValue&&(e.removeAttribute(o.Attr.ProtectedInMemPlainXml),e.setAttribute(o.Attr.Protected,"True"),e.textContent=e.protectedValue.toString())}))},e.exports.protectPlainValues=function(e){k(e,(function(e){w(e.getAttribute(o.Attr.ProtectedInMemPlainXml))&&(e.protectedValue=s.fromString(e.textContent),e.textContent=e.protectedValue.toString(),e.removeAttribute(o.Attr.ProtectedInMemPlainXml),e.setAttribute(o.Attr.Protected,"True"))}))}}).call(this,r(13))},function(e,t,r){"use strict";var i="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;t.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var r=t.shift();if(r){if("object"!=typeof r)throw new TypeError(r+"must be non-object");for(var i in r)r.hasOwnProperty(i)&&(e[i]=r[i])}}return e},t.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var n={arraySet:function(e,t,r,i,n){if(t.subarray&&e.subarray)e.set(t.subarray(r,r+i),n);else for(var o=0;o=2097152)throw new Error("too large number");return 4294967296*this.hi+this.lo}return this.lo}}),i.prototype.valueOf=function(){return this.value},i.from=function(e){if(e>9007199254740991)throw new Error("too large number");var t=e>>>0;return new i(t,(e-t)/4294967296>>>0)},e.exports=i},function(e,t,r){"use strict";var i=r(0),n=r(3),o=r(10),a=function(e,t){Object.defineProperty(this,"_value",{value:new Uint8Array(e)}),Object.defineProperty(this,"_salt",{value:new Uint8Array(t)})};a.prototype.toString=function(){return i.bytesToBase64(this._value)},a.fromString=function(e){for(var t=i.stringToBytes(e),r=o.getBytes(t.length),n=0,s=t.length;n=0;i--)r[i]=e[i]^t[i];return r},a.prototype.setSalt=function(e){for(var t=new Uint8Array(e),r=this._value,i=this._salt,n=0,o=r.length;n=0;--i)t[i]^=r[i];return t}},function(e,t,r){"use strict";function i(e){this._arrayBuffer=e||new ArrayBuffer(1024),this._dataView=new DataView(this._arrayBuffer),this._pos=0,this._canExpand=!e}["Int","Uint","Float"].forEach((function(e){("Float"===e?[4,8]:[1,2,4]).forEach((function(t){var r="get"+e+8*t;i.prototype[r]=function(e){var i=this._dataView[r].call(this._dataView,this._pos,e);return this._pos+=t,i};var n="set"+e+8*t;i.prototype[n]=function(e,r){this._checkCapacity(t),this._dataView[n].call(this._dataView,this._pos,e,r),this._pos+=t}}))})),i.prototype.getUint64=function(e){var t=this.getUint32(e),r=this.getUint32(e);return e?r*=4294967296:t*=4294967296,t+r},i.prototype.setUint64=function(e,t){t?(this.setUint32(4294967295&e,!0),this.setUint32(Math.floor(e/4294967296),!0)):(this._checkCapacity(8),this.setUint32(Math.floor(e/4294967296),!1),this.setUint32(4294967295&e,!1))},i.prototype.readBytes=function(e){var t=this._arrayBuffer.slice(this._pos,this._pos+e);return this._pos+=e,t},i.prototype.readBytesToEnd=function(){var e=this._arrayBuffer.byteLength-this._pos;return this.readBytes(e)},i.prototype.readBytesNoAdvance=function(e,t){return this._arrayBuffer.slice(e,t)},i.prototype.writeBytes=function(e){e instanceof ArrayBuffer&&(e=new Uint8Array(e)),this._checkCapacity(e.length),new Uint8Array(this._arrayBuffer).set(e,this._pos),this._pos+=e.length},i.prototype.getWrittenBytes=function(){return this._arrayBuffer.slice(0,this._pos)},i.prototype._checkCapacity=function(e){var t=this._arrayBuffer.byteLength-this._pos;if(this._canExpand&&t1)throw new i(n.ErrorCodes.InvalidVersion)},d.prototype._readItem=function(e){var t=e.getUint8();if(!t)return!1;var r=e.getInt32(!0);if(r<=0)throw new i(n.ErrorCodes.FileCorrupt,"bad key length");var d,h=o.bytesToString(e.readBytes(r)),u=e.getInt32(!0);if(u<0)throw new i(n.ErrorCodes.FileCorrupt,"bad value length");switch(t){case s.UInt32:if(4!==u)throw new i(n.ErrorCodes.FileCorrupt,"bad uint32");d=e.getUint32(!0);break;case s.UInt64:if(8!==u)throw new i(n.ErrorCodes.FileCorrupt,"bad uint64");var l=e.getUint32(!0),c=e.getUint32(!0);d=new a(l,c);break;case s.Bool:if(1!==u)throw new i(n.ErrorCodes.FileCorrupt,"bad bool");d=0!==e.getUint8();break;case s.Int32:if(4!==u)throw new i(n.ErrorCodes.FileCorrupt,"bad int32");d=e.getInt32(!0);break;case s.Int64:if(8!==u)throw new i(n.ErrorCodes.FileCorrupt,"bad int64");var f=e.getUint32(!0),p=e.getUint32(!0);d=new a(f,p);break;case s.String:d=o.bytesToString(e.readBytes(u));break;case s.Bytes:d=e.readBytes(u);break;default:throw new i(n.ErrorCodes.FileCorrupt,"bad value type: "+t)}return{key:h,type:t,value:d}},d.prototype.write=function(e){this._writeVersion(e),Object.keys(this._items).forEach((function(t){this._writeItem(e,this._items[t])}),this),e.setUint8(0)},d.prototype._writeVersion=function(e){e.setUint16(256,!0)},d.prototype._writeItem=function(e,t){e.setUint8(t.type);var r=o.stringToBytes(t.key);switch(e.setInt32(r.length,!0),e.writeBytes(r),t.type){case s.UInt32:e.setInt32(4,!0),e.setUint32(t.value,!0);break;case s.UInt64:e.setInt32(8,!0),e.setUint32(t.value.lo,!0),e.setUint32(t.value.hi,!0);break;case s.Bool:e.setInt32(1,!0),e.setUint8(t.value?1:0);break;case s.Int32:e.setInt32(4,!0),e.setInt32(t.value,!0);break;case s.Int64:e.setInt32(8,!0),e.setUint32(t.value.lo,!0),e.setUint32(t.value.hi,!0);break;case s.String:var a=o.stringToBytes(t.value);e.setInt32(a.length,!0),e.writeBytes(a);break;case s.Bytes:var d=o.arrayToBuffer(t.value);e.setInt32(d.byteLength,!0),e.writeBytes(d);break;default:throw new i(n.ErrorCodes.Unsupported)}},e.exports=d},function(e,t,r){"use strict";var i=r(6),n=r(4),o={read:function(e){for(var t={},r=0,n=e.childNodes,a=n.length;r>>16&65535|0,a=0;0!==r;){r-=a=r>2e3?2e3:r;do{o=o+(n=n+t[i++]|0)|0}while(--a);n%=65521,o%=65521}return n|o<<16|0}},function(e,t,r){"use strict";var i=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var i=0;i<8;i++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();e.exports=function(e,t,r,n){var o=i,a=n+r;e^=-1;for(var s=n;s>>8^o[255&(e^t[s])];return-1^e}},function(e,t,r){"use strict";var i=r(5),n=!0,o=!0;try{String.fromCharCode.apply(null,[0])}catch(e){n=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(e){o=!1}for(var a=new i.Buf8(256),s=0;s<256;s++)a[s]=s>=252?6:s>=248?5:s>=240?4:s>=224?3:s>=192?2:1;function d(e,t){if(t<65537&&(e.subarray&&o||!e.subarray&&n))return String.fromCharCode.apply(null,i.shrinkBuf(e,t));for(var r="",a=0;a>>6,t[a++]=128|63&r):r<65536?(t[a++]=224|r>>>12,t[a++]=128|r>>>6&63,t[a++]=128|63&r):(t[a++]=240|r>>>18,t[a++]=128|r>>>12&63,t[a++]=128|r>>>6&63,t[a++]=128|63&r);return t},t.buf2binstring=function(e){return d(e,e.length)},t.binstring2buf=function(e){for(var t=new i.Buf8(e.length),r=0,n=t.length;r4)h[i++]=65533,r+=o-1;else{for(n&=2===o?31:3===o?15:7;o>1&&r1?h[i++]=65533:n<65536?h[i++]=n:(n-=65536,h[i++]=55296|n>>10&1023,h[i++]=56320|1023&n)}return d(h,i)},t.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;r>=0&&128==(192&e[r]);)r--;return r<0||0===r?t:r+a[e[r]]>t?r:t}},function(e,t,r){"use strict";e.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},function(e,t,r){"use strict";e.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},function(e,t,r){"use strict";var i=r(7),n=r(1),o=r(9),a=r(2),s=r(11),d=r(0),h=r(14),u=r(8),l=r(10),c=[{name:"EndOfHeader"},{name:"Comment"},{name:"CipherID"},{name:"CompressionFlags"},{name:"MasterSeed"},{name:"TransformSeed",ver:[3]},{name:"TransformRounds",ver:[3]},{name:"EncryptionIV"},{name:"ProtectedStreamKey",ver:[3]},{name:"StreamStartBytes",ver:[3]},{name:"InnerRandomStreamID",ver:[3]},{name:"KdfParameters",ver:[4]},{name:"PublicCustomData",ver:[4]}],f=[{name:"EndOfHeader"},{name:"InnerRandomStreamID"},{name:"InnerRandomStreamKey"},{name:"Binary",skipHeader:!0}],p={DefaultFileVersionMajor:4,DefaultFileVersionMinor:0,MaxFileVersionMajor:4,MaxFileVersionMinor:1,MaxSupportedVersion:4,FlagBinaryProtected:1,InnerHeaderBinaryFieldId:3,DefaultKdfAlgo:n.KdfId.Argon2,DefaultKdfSaltLength:32,DefaultKdfParallelism:1,DefaultKdfIterations:2,DefaultKdfMemory:1048576,DefaultKdfVersion:19},m={3:1,4:0},y=function(){this.versionMajor=void 0,this.versionMinor=void 0,this.dataCipherUuid=void 0,this.compression=void 0,this.masterSeed=void 0,this.transformSeed=void 0,this.keyEncryptionRounds=void 0,this.encryptionIV=void 0,this.protectedStreamKey=void 0,this.streamStartBytes=void 0,this.crsAlgorithm=void 0,this.endPos=void 0,this.kdfParameters=void 0,this.publicCustomData=void 0,Object.preventExtensions(this)};y.prototype._readSignature=function(e){if(e.byteLength<8)throw new a(n.ErrorCodes.FileCorrupt,"not enough data");var t=e.getUint32(!0),r=e.getUint32(!0);if(t!==n.Signatures.FileMagic||r!==n.Signatures.Sig2Kdbx)throw new a(n.ErrorCodes.BadSignature)},y.prototype._writeSignature=function(e){e.setUint32(n.Signatures.FileMagic,!0),e.setUint32(n.Signatures.Sig2Kdbx,!0)},y.prototype._readVersion=function(e){var t=e.getUint16(!0),r=e.getUint16(!0);if(r>p.MaxSupportedVersion)throw new a(n.ErrorCodes.InvalidVersion);this.versionMinor=t,this.versionMajor=r},y.prototype._writeVersion=function(e){e.setUint16(this.versionMinor,!0),e.setUint16(this.versionMajor,!0)},y.prototype._readCipherID=function(e){if(16!==e.byteLength)throw new a(n.ErrorCodes.Unsupported,"cipher");this.dataCipherUuid=new i(e)},y.prototype._writeCipherID=function(e){this._writeFieldSize(e,16),e.writeBytes(this.dataCipherUuid.bytes)},y.prototype._readCompressionFlags=function(e){var t=new DataView(e).getUint32(e,!0);if(t<0||t>=Object.keys(n.CompressionAlgorithm).length)throw new a(n.ErrorCodes.Unsupported,"compression");this.compression=t},y.prototype._writeCompressionFlags=function(e){this._writeFieldSize(e,4),e.setUint32(this.compression,!0)},y.prototype._readMasterSeed=function(e){this.masterSeed=e},y.prototype._writeMasterSeed=function(e){this._writeFieldBytes(e,this.masterSeed)},y.prototype._readTransformSeed=function(e){this.transformSeed=e},y.prototype._writeTransformSeed=function(e){this._writeFieldBytes(e,this.transformSeed)},y.prototype._readTransformRounds=function(e){this.keyEncryptionRounds=new s(e).getUint64(!0)},y.prototype._writeTransformRounds=function(e){this._writeFieldSize(e,8),e.setUint64(this.keyEncryptionRounds,!0)},y.prototype._readEncryptionIV=function(e){this.encryptionIV=e},y.prototype._writeEncryptionIV=function(e){this._writeFieldBytes(e,this.encryptionIV)},y.prototype._readProtectedStreamKey=function(e){this.protectedStreamKey=e},y.prototype._writeProtectedStreamKey=function(e){this._writeFieldBytes(e,this.protectedStreamKey)},y.prototype._readStreamStartBytes=function(e){this.streamStartBytes=e},y.prototype._writeStreamStartBytes=function(e){this._writeFieldBytes(e,this.streamStartBytes)},y.prototype._readInnerRandomStreamID=function(e){this.crsAlgorithm=new DataView(e).getUint32(e,!0)},y.prototype._writeInnerRandomStreamID=function(e){this._writeFieldSize(e,4),e.setUint32(this.crsAlgorithm,!0)},y.prototype._readInnerRandomStreamKey=function(e){this.protectedStreamKey=e},y.prototype._writeInnerRandomStreamKey=function(e){this._writeFieldBytes(e,this.protectedStreamKey)},y.prototype._readKdfParameters=function(e){this.kdfParameters=h.read(new s(e))},y.prototype._writeKdfParameters=function(e){var t=new s;this.kdfParameters.write(t),this._writeFieldBytes(e,t.getWrittenBytes())},y.prototype._readPublicCustomData=function(e){this.publicCustomData=h.read(new s(e))},y.prototype._hasPublicCustomData=function(){return this.publicCustomData},y.prototype._writePublicCustomData=function(e){if(this.publicCustomData){var t=new s;this.publicCustomData.write(t),this._writeFieldBytes(e,t.getWrittenBytes())}},y.prototype._readBinary=function(e,t){var r=new DataView(e).getUint8(0)&p.FlagBinaryProtected,i=e.slice(1),n=r?o.fromBinary(i):i,a=Object.keys(t.kdbx.binaries).length;t.kdbx.binaries[a]=n},y.prototype._writeBinary=function(e,t){if(!(this.versionMajor<4))for(var r=t.kdbx.binaries.hashOrder,i=0;i0&&(i=e.readBytes(o));var a=t[n];if(a){var s=this["_read"+a.name];s&&s.call(this,i,r)}return 0!==n},y.prototype._writeField=function(e,t,r,i){var n=r[t];if(n){if(n.ver&&n.ver.indexOf(this.versionMajor)<0)return;var o=this["_write"+n.name];if(o){var a=this["_has"+n.name];if(a&&!a.call(this))return;n.skipHeader||e.setUint8(t),o.call(this,e,i)}}},y.prototype._readFieldSize=function(e){return this.versionMajor>=4?e.getUint32(!0):e.getUint16(!0)},y.prototype._writeFieldSize=function(e,t){this.versionMajor>=4?e.setUint32(t,!0):e.setUint16(t,!0)},y.prototype._writeFieldBytes=function(e,t){this._writeFieldSize(e,t.byteLength),e.writeBytes(t)},y.prototype._validate=function(){if(void 0===this.dataCipherUuid)throw new a(n.ErrorCodes.FileCorrupt,"no cipher in header");if(void 0===this.compression)throw new a(n.ErrorCodes.FileCorrupt,"no compression in header");if(!this.masterSeed)throw new a(n.ErrorCodes.FileCorrupt,"no master seed in header");if(this.versionMajor<4&&!this.transformSeed)throw new a(n.ErrorCodes.FileCorrupt,"no transform seed in header");if(this.versionMajor<4&&!this.keyEncryptionRounds)throw new a(n.ErrorCodes.FileCorrupt,"no key encryption rounds in header");if(!this.encryptionIV)throw new a(n.ErrorCodes.FileCorrupt,"no encryption iv in header");if(this.versionMajor<4&&!this.protectedStreamKey)throw new a(n.ErrorCodes.FileCorrupt,"no protected stream key in header");if(this.versionMajor<4&&!this.streamStartBytes)throw new a(n.ErrorCodes.FileCorrupt,"no stream start bytes in header");if(this.versionMajor<4&&!this.crsAlgorithm)throw new a(n.ErrorCodes.FileCorrupt,"no crs algorithm in header");if(this.versionMajor>=4&&!this.kdfParameters)throw new a(n.ErrorCodes.FileCorrupt,"no kdf parameters in header")},y.prototype._validateInner=function(){if(!this.protectedStreamKey)throw new a(n.ErrorCodes.FileCorrupt,"no protected stream key in header");if(!this.crsAlgorithm)throw new a(n.ErrorCodes.FileCorrupt,"no crs algorithm in header")},y.prototype._createKdfParameters=function(e){switch(e||(e=p.DefaultKdfAlgo),e){case n.KdfId.Argon2:this.kdfParameters=new h,this.kdfParameters.set("$UUID",h.ValueType.Bytes,d.base64ToBytes(n.KdfId.Argon2)),this.kdfParameters.set("S",h.ValueType.Bytes,l.getBytes(p.DefaultKdfSaltLength)),this.kdfParameters.set("P",h.ValueType.UInt32,p.DefaultKdfParallelism),this.kdfParameters.set("I",h.ValueType.UInt64,new u(p.DefaultKdfIterations)),this.kdfParameters.set("M",h.ValueType.UInt64,new u(p.DefaultKdfMemory)),this.kdfParameters.set("V",h.ValueType.UInt32,p.DefaultKdfVersion);break;case n.KdfId.Aes:this.kdfParameters=new h,this.kdfParameters.set("$UUID",h.ValueType.Bytes,d.base64ToBytes(n.KdfId.Aes)),this.kdfParameters.set("S",h.ValueType.Bytes,l.getBytes(p.DefaultKdfSaltLength)),this.kdfParameters.set("R",h.ValueType.UInt64,new u(n.Defaults.KeyEncryptionRounds));break;default:throw new a(n.ErrorCodes.InvalidArg,"bad KDF algo")}},y.prototype.write=function(e){this._validate(),this._writeSignature(e),this._writeVersion(e);for(var t=1;t>4&15]),r.push(t[15&i[n]]);return r.join("")},i.prototype._reset=function(){this.counterWords[0]=0,this.counterWords[1]=0,this.blockUsed=64},i.prototype._incrementCounter=function(){this.counterWords[0]=this.counterWords[0]+1&4294967295,0===this.counterWords[0]&&(this.counterWords[1]=this.counterWords[1]+1&4294967295)},i.prototype._generateBlock=function(){for(var e,t=this.sigmaWords[0],r=this.keyWords[0],i=this.keyWords[1],n=this.keyWords[2],o=this.keyWords[3],a=this.sigmaWords[1],s=this.nonceWords[0],d=this.nonceWords[1],h=this.counterWords[0],u=this.counterWords[1],l=this.sigmaWords[2],c=this.keyWords[4],f=this.keyWords[5],p=this.keyWords[6],m=this.keyWords[7],y=this.sigmaWords[3],g=t,_=r,b=i,v=n,w=o,k=a,C=s,x=d,E=h,B=u,T=l,A=c,S=f,U=p,D=m,I=y,N=0;N>>25)+g)<<9|e>>>23)+w)<<13|e>>>19)+E)<<18|e>>>14,k^=(e=(_^=(e=(U^=(e=(B^=(e=k+_)<<7|e>>>25)+k)<<9|e>>>23)+B)<<13|e>>>19)+U)<<18|e>>>14,T^=(e=(C^=(e=(b^=(e=(D^=(e=T+C)<<7|e>>>25)+T)<<9|e>>>23)+D)<<13|e>>>19)+b)<<18|e>>>14,I^=(e=(A^=(e=(x^=(e=(v^=(e=I+A)<<7|e>>>25)+I)<<9|e>>>23)+v)<<13|e>>>19)+x)<<18|e>>>14,g^=(e=(v^=(e=(b^=(e=(_^=(e=g+v)<<7|e>>>25)+g)<<9|e>>>23)+_)<<13|e>>>19)+b)<<18|e>>>14,k^=(e=(w^=(e=(x^=(e=(C^=(e=k+w)<<7|e>>>25)+k)<<9|e>>>23)+C)<<13|e>>>19)+x)<<18|e>>>14,T^=(e=(B^=(e=(E^=(e=(A^=(e=T+B)<<7|e>>>25)+T)<<9|e>>>23)+A)<<13|e>>>19)+E)<<18|e>>>14,I^=(e=(D^=(e=(U^=(e=(S^=(e=I+D)<<7|e>>>25)+I)<<9|e>>>23)+S)<<13|e>>>19)+U)<<18|e>>>14;g+=t,_+=r,b+=i,v+=n,w+=o,k+=a,C+=s,x+=d,E+=h,B+=u,T+=l,A+=c,S+=f,U+=p,D+=m,I+=y,this.block[0]=g>>>0&255,this.block[1]=g>>>8&255,this.block[2]=g>>>16&255,this.block[3]=g>>>24&255,this.block[4]=_>>>0&255,this.block[5]=_>>>8&255,this.block[6]=_>>>16&255,this.block[7]=_>>>24&255,this.block[8]=b>>>0&255,this.block[9]=b>>>8&255,this.block[10]=b>>>16&255,this.block[11]=b>>>24&255,this.block[12]=v>>>0&255,this.block[13]=v>>>8&255,this.block[14]=v>>>16&255,this.block[15]=v>>>24&255,this.block[16]=w>>>0&255,this.block[17]=w>>>8&255,this.block[18]=w>>>16&255,this.block[19]=w>>>24&255,this.block[20]=k>>>0&255,this.block[21]=k>>>8&255,this.block[22]=k>>>16&255,this.block[23]=k>>>24&255,this.block[24]=C>>>0&255,this.block[25]=C>>>8&255,this.block[26]=C>>>16&255,this.block[27]=C>>>24&255,this.block[28]=x>>>0&255,this.block[29]=x>>>8&255,this.block[30]=x>>>16&255,this.block[31]=x>>>24&255,this.block[32]=E>>>0&255,this.block[33]=E>>>8&255,this.block[34]=E>>>16&255,this.block[35]=E>>>24&255,this.block[36]=B>>>0&255,this.block[37]=B>>>8&255,this.block[38]=B>>>16&255,this.block[39]=B>>>24&255,this.block[40]=T>>>0&255,this.block[41]=T>>>8&255,this.block[42]=T>>>16&255,this.block[43]=T>>>24&255,this.block[44]=A>>>0&255,this.block[45]=A>>>8&255,this.block[46]=A>>>16&255,this.block[47]=A>>>24&255,this.block[48]=S>>>0&255,this.block[49]=S>>>8&255,this.block[50]=S>>>16&255,this.block[51]=S>>>24&255,this.block[52]=U>>>0&255,this.block[53]=U>>>8&255,this.block[54]=U>>>16&255,this.block[55]=U>>>24&255,this.block[56]=D>>>0&255,this.block[57]=D>>>8&255,this.block[58]=D>>>16&255,this.block[59]=D>>>24&255,this.block[60]=I>>>0&255,this.block[61]=I>>>8&255,this.block[62]=I>>>16&255,this.block[63]=I>>>24&255},e.exports=i},function(e,t,r){"use strict";function i(e,t){this.sigmaWords=[1634760805,857760878,2036477234,1797285236],this.block=new Uint8Array(64),this.blockUsed=64,this.x=new Uint32Array(16);var r=new Uint32Array(16);r[0]=this.sigmaWords[0],r[1]=this.sigmaWords[1],r[2]=this.sigmaWords[2],r[3]=this.sigmaWords[3],r[4]=o(e,0),r[5]=o(e,4),r[6]=o(e,8),r[7]=o(e,12),r[8]=o(e,16),r[9]=o(e,20),r[10]=o(e,24),r[11]=o(e,28),r[12]=0,12===t.length?(r[13]=o(t,0),r[14]=o(t,4),r[15]=o(t,8)):(r[13]=0,r[14]=o(t,0),r[15]=o(t,4)),this.input=r}function n(e,t,r,i,n){e[t]+=e[r],e[n]=s(e[n]^e[t],16),e[i]+=e[n],e[r]=s(e[r]^e[i],12),e[t]+=e[r],e[n]=s(e[n]^e[t],8),e[i]+=e[n],e[r]=s(e[r]^e[i],7)}function o(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function a(e,t,r){e[t]=r,r>>>=8,e[t+1]=r,r>>>=8,e[t+2]=r,r>>>=8,e[t+3]=r}function s(e,t){return e<>>32-t}i.prototype.getBytes=function(e){for(var t=new Uint8Array(e),r=0;r0;e-=2)n(r,0,4,8,12),n(r,1,5,9,13),n(r,2,6,10,14),n(r,3,7,11,15),n(r,0,5,10,15),n(r,1,6,11,12),n(r,2,7,8,13),n(r,3,4,9,14);for(e=16;e--;)r[e]+=t[e];for(e=16;e--;)a(i,4*e,r[e]);t[12]+=1,t[12]||(t[13]+=1)},i.prototype.encrypt=function(e){for(var t=e.length,r=new Uint8Array(t),i=0,n=this.block;i0;){var d=Math.min(r,1e4);r-=d;var h=o*d;n=s(e,n,a.length===h?a.buffer:i.arrayToBuffer(a.subarray(0,h)))}return n.then((function(e){return new Uint8Array(e)}))}function s(e,t,r){return t.then((function(t){return e.encrypt(r,t)})).then((function(e){var t=i.arrayToBuffer(new Uint8Array(e).subarray(-32,-16));return i.zeroBuffer(e),t}))}e.exports.encrypt=function(e,t,r){var s=n.createAesCbc();return s.importKey(i.arrayToBuffer(t)).then((function(){for(var t=[],i=0;i<32;i+=o)t.push(a(s,e.subarray(i,i+o),r));return Promise.all(t)})).then((function(e){var t=new Uint8Array(32);return e.forEach((function(e,r){for(var n=r*o,a=0;a\n \n";return a.stringToBytes(t)},e.exports=u},function(e,t,r){"use strict";var i=r(6),n=r(4),o=function(){this.creationTime=void 0,this.lastModTime=void 0,this.lastAccessTime=void 0,this.expiryTime=void 0,this.expires=void 0,this.usageCount=void 0,this.locationChanged=new Date,Object.preventExtensions(this)};o.prototype._readNode=function(e){switch(e.tagName){case i.Elem.CreationTime:this.creationTime=n.getDate(e);break;case i.Elem.LastModTime:this.lastModTime=n.getDate(e);break;case i.Elem.LastAccessTime:this.lastAccessTime=n.getDate(e);break;case i.Elem.ExpiryTime:this.expiryTime=n.getDate(e);break;case i.Elem.Expires:this.expires=n.getBoolean(e);break;case i.Elem.UsageCount:this.usageCount=n.getNumber(e);break;case i.Elem.LocationChanged:this.locationChanged=n.getDate(e)}},o.prototype.clone=function(){var e=new o;return e.creationTime=this.creationTime,e.lastModTime=this.lastModTime,e.lastAccessTime=this.lastAccessTime,e.expiryTime=this.expiryTime,e.expires=this.expires,e.usageCount=this.usageCount,e.locationChanged=this.locationChanged,e},o.prototype.update=function(){var e=new Date;this.lastModTime=e,this.lastAccessTime=e},o.prototype.write=function(e,t){var r=n.addChildNode(e,i.Elem.Times);t.setXmlDate(n.addChildNode(r,i.Elem.CreationTime),this.creationTime),t.setXmlDate(n.addChildNode(r,i.Elem.LastModTime),this.lastModTime),t.setXmlDate(n.addChildNode(r,i.Elem.LastAccessTime),this.lastAccessTime),t.setXmlDate(n.addChildNode(r,i.Elem.ExpiryTime),this.expiryTime),n.setBoolean(n.addChildNode(r,i.Elem.Expires),this.expires),n.setNumber(n.addChildNode(r,i.Elem.UsageCount),this.usageCount),t.setXmlDate(n.addChildNode(r,i.Elem.LocationChanged),this.locationChanged)},o.create=function(){var e=new o,t=new Date;return e.creationTime=t,e.lastModTime=t,e.lastAccessTime=t,e.expiryTime=t,e.expires=!1,e.usageCount=0,e.locationChanged=t,e},o.read=function(e){for(var t=new o,r=0,i=e.childNodes,n=i.length;rt.times.lastModTime){if(!this.history.some((function(e){return+e.times.lastModTime==+t.times.lastModTime}))){var i=new l;i.copyFrom(t),r.push(i)}}this.history=this._mergeHistory(r,t.times.lastModTime)}},l.prototype._mergeHistory=function(e,t){this.history.sort((function(e,t){return e.times.lastModTime-t.times.lastModTime})),e.sort((function(e,t){return e.times.lastModTime-t.times.lastModTime}));var r={},i={};this.history.forEach((function(e){r[e.times.lastModTime.getTime()]=e})),e.forEach((function(e){i[e.times.lastModTime.getTime()]=e}));for(var n=0,o=0,a=[];nu){if(!this._editState||this._editState.deleted.indexOf(u)<0){var c=new l;c.copyFrom(d),a.push(c)}o++}else(this._editState&&this._editState.added.indexOf(h)>=0||h>t)&&a.push(s),n++;else a.push(s),n++,o++}return a},l.create=function(e,t){var r=new l(t);return r.uuid=d.random(),r.icon=a.Icons.Key,r.times=h.create(),r.parentGroup=t,r._setField("Title","",e.memoryProtection.title),r._setField("UserName",e.defaultUser||"",e.memoryProtection.userName),r._setField("Password","",e.memoryProtection.password),r._setField("URL","",e.memoryProtection.url),r._setField("Notes","",e.memoryProtection.notes),r.autoType.enabled="boolean"!=typeof t.enableAutoType||t.enableAutoType,r.autoType.obfuscation=a.AutoTypeObfuscationOptions.None,r},l.read=function(e,t,r){for(var i=new l,n=0,o=e.childNodes,a=o.length;n=0?t[i].splice(r,0,e):t[i].push(e);else{var a=new Date;e instanceof h?e.forEach((function(e,t){this.addDeletedObject((e||t).uuid,a)}),this):this.addDeletedObject(e.uuid,a)}e.parentGroup=t,e.times.locationChanged=new Date}},y.prototype.addDeletedObject=function(e,t){var r=new l;r.uuid=e,r.deletionTime=t,this.deletedObjects.push(r)},y.prototype.remove=function(e){var t=null;this.meta.recycleBinEnabled&&(this.createRecycleBin(),t=this.getGroup(this.meta.recycleBinUuid)),this.move(e,t)},y.prototype.createBinary=function(e){return this.binaries.add(e)},y.prototype.importEntry=function(e,t,r){var i=new u,n=c.random();i.copyFrom(e),i.uuid=n,e.history.forEach((function(e){var t=new u;t.copyFrom(e),t.uuid=n,i.history.push(t)}));var o={},a={};return i.history.concat(i).forEach((function(e){e.customIcon&&(a[e.customIcon]=e.customIcon),Object.values(e.binaries).forEach((function(e){e.ref&&(o[e.ref]=e)}))})),Object.values(o).forEach((function(e){var t=r.binaries[e.ref];t&&!this.binaries[e.ref]&&(this.binaries[e.ref]=t)}),this),Object.values(a).forEach((function(e){var t=r.meta.customIcons[e];t&&(this.meta.customIcons[e]=t)}),this),t.entries.push(i),i.parentGroup=t,i.times.update(),i},y.prototype.cleanup=function(e){var t=new Date,r=e&&e.historyRules&&"number"==typeof this.meta.historyMaxItems&&this.meta.historyMaxItems>=0?this.meta.historyMaxItems:1/0,i={},n={},o=function(e){e&&e.customIcon&&(i[e.customIcon]=!0),e&&e.binaries&&Object.keys(e.binaries).forEach((function(t){e.binaries[t]&&e.binaries[t].ref&&(n[e.binaries[t].ref]=!0)}))};this.getDefaultGroup().forEach((function(e,t){e&&e.history.length>r&&e.removeHistory(0,e.history.length-r),e&&o(e),e&&e.history&&e.history.forEach((function(e){o(e)})),t&&t.customIcon&&(i[t.customIcon]=!0)})),e&&e.customIcons&&Object.keys(this.meta.customIcons).forEach((function(e){if(!i[e]){var r=new c(e);this.addDeletedObject(r,t),delete this.meta.customIcons[e]}}),this),e&&e.binaries&&Object.keys(this.binaries).forEach((function(e){n[e]||delete this.binaries[e]}),this)},y.prototype.merge=function(e){var t=this.getDefaultGroup(),r=e.getDefaultGroup();if(!t||!r)throw new n(f.ErrorCodes.MergeError,"no default group");if(!t.uuid.equals(r.uuid))throw new n(f.ErrorCodes.MergeError,"default group is different");var i=this._getObjectMap();e.deletedObjects.forEach((function(e){i.deleted[e.uuid]||(this.deletedObjects.push(e),i.deleted[e.uuid]=e.deletionTime)}),this),Object.keys(e.binaries).forEach((function(t){this.binaries[t]||i.deleted[t]||(this.binaries[t]=e.binaries[t])}),this),i.remote=e._getObjectMap().objects,this.meta.merge(e.meta,i),t.merge(i),this.cleanup({historyRules:!0,customIcons:!0,binaries:!0})},y.prototype.getLocalEditState=function(){var e={};return this.getDefaultGroup().forEach((function(t){t&&t._editState&&(e[t.uuid]=t._editState)})),this.meta._editState&&(e.meta=this.meta._editState),e},y.prototype.setLocalEditState=function(e){this.getDefaultGroup().forEach((function(t){t&&e[t.uuid]&&(t._editState=e[t.uuid])})),e.meta&&(this.meta._editState=e.meta)},y.prototype.removeLocalEditState=function(){this.getDefaultGroup().forEach((function(e){e&&(e._editState=void 0)})),this.meta._editState=void 0},y.prototype.upgrade=function(){this.setVersion(a.MaxFileVersion)},y.prototype.setVersion=function(e){this.meta.headerHash=null,this.meta.settingsChanged=new Date,this.header.setVersion(e)},y.prototype.setKdf=function(e){this.meta.headerHash=null,this.meta.settingsChanged=new Date,this.header.setKdf(e)},y.prototype._getObjectMap=function(){var e={},t={};return this.getDefaultGroup().forEach((function(t,r){var i=t||r;if(e[i.uuid])throw new n(f.ErrorCodes.MergeError,"Duplicate: "+i.uuid);e[i.uuid]=i})),this.deletedObjects.forEach((function(e){t[e.uuid]=e.deletionTime})),{objects:e,deleted:t}},y.prototype._loadFromXml=function(e){if(this.xml.documentElement.tagName!==p.Elem.DocNode)throw new n(f.ErrorCodes.FileCorrupt,"bad xml root");this._parseMeta(e);var t=this;return this.binaries.hash().then((function(){return t._parseRoot(e),t}))},y.prototype._parseMeta=function(e){var t=m.getChildNode(this.xml.documentElement,p.Elem.Meta,"no meta node");this.meta=s.read(t,e)},y.prototype._parseRoot=function(e){this.groups=[],this.deletedObjects=[];for(var t=0,r=m.getChildNode(this.xml.documentElement,p.Elem.Root,"no root node").childNodes,i=r.length;t0?t.windowBits=-t.windowBits:t.gzip&&t.windowBits>0&&t.windowBits<16&&(t.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new s,this.strm.avail_out=0;var r=i.deflateInit2(this.strm,t.level,t.method,t.windowBits,t.memLevel,t.strategy);if(0!==r)throw new Error(a[r]);if(t.header&&i.deflateSetHeader(this.strm,t.header),t.dictionary){var u;if(u="string"==typeof t.dictionary?o.string2buf(t.dictionary):"[object ArrayBuffer]"===d.call(t.dictionary)?new Uint8Array(t.dictionary):t.dictionary,0!==(r=i.deflateSetDictionary(this.strm,u)))throw new Error(a[r]);this._dict_set=!0}}function u(e,t){var r=new h(t);if(r.push(e,!0),r.err)throw r.msg;return r.result}h.prototype.push=function(e,t){var r,a,s=this.strm,h=this.options.chunkSize;if(this.ended)return!1;a=t===~~t?t:!0===t?4:0,"string"==typeof e?s.input=o.string2buf(e):"[object ArrayBuffer]"===d.call(e)?s.input=new Uint8Array(e):s.input=e,s.next_in=0,s.avail_in=s.input.length;do{if(0===s.avail_out&&(s.output=new n.Buf8(h),s.next_out=0,s.avail_out=h),1!==(r=i.deflate(s,a))&&0!==r)return this.onEnd(r),this.ended=!0,!1;0!==s.avail_out&&(0!==s.avail_in||4!==a&&2!==a)||("string"===this.options.to?this.onData(o.buf2binstring(n.shrinkBuf(s.output,s.next_out))):this.onData(n.shrinkBuf(s.output,s.next_out)))}while((s.avail_in>0||0===s.avail_out)&&1!==r);return 4===a?(r=i.deflateEnd(this.strm),this.onEnd(r),this.ended=!0,0===r):2!==a||(this.onEnd(0),s.avail_out=0,!0)},h.prototype.onData=function(e){this.chunks.push(e)},h.prototype.onEnd=function(e){0===e&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=n.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},t.Deflate=h,t.deflate=u,t.deflateRaw=function(e,t){return(t=t||{}).raw=!0,u(e,t)},t.gzip=function(e,t){return(t=t||{}).gzip=!0,u(e,t)}},function(e,t,r){"use strict";var i,n=r(5),o=r(34),a=r(17),s=r(18),d=r(12),h=-2,u=258,l=262,c=103,f=113,p=666;function m(e,t){return e.msg=d[t],t}function y(e){return(e<<1)-(e>4?9:0)}function g(e){for(var t=e.length;--t>=0;)e[t]=0}function _(e){var t=e.state,r=t.pending;r>e.avail_out&&(r=e.avail_out),0!==r&&(n.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function b(e,t){o._tr_flush_block(e,e.block_start>=0?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,_(e.strm)}function v(e,t){e.pending_buf[e.pending++]=t}function w(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function k(e,t){var r,i,n=e.max_chain_length,o=e.strstart,a=e.prev_length,s=e.nice_match,d=e.strstart>e.w_size-l?e.strstart-(e.w_size-l):0,h=e.window,c=e.w_mask,f=e.prev,p=e.strstart+u,m=h[o+a-1],y=h[o+a];e.prev_length>=e.good_match&&(n>>=2),s>e.lookahead&&(s=e.lookahead);do{if(h[(r=t)+a]===y&&h[r+a-1]===m&&h[r]===h[o]&&h[++r]===h[o+1]){o+=2,r++;do{}while(h[++o]===h[++r]&&h[++o]===h[++r]&&h[++o]===h[++r]&&h[++o]===h[++r]&&h[++o]===h[++r]&&h[++o]===h[++r]&&h[++o]===h[++r]&&h[++o]===h[++r]&&oa){if(e.match_start=t,a=i,i>=s)break;m=h[o+a-1],y=h[o+a]}}}while((t=f[t&c])>d&&0!=--n);return a<=e.lookahead?a:e.lookahead}function C(e){var t,r,i,o,d,h,u,c,f,p,m=e.w_size;do{if(o=e.window_size-e.lookahead-e.strstart,e.strstart>=m+(m-l)){n.arraySet(e.window,e.window,m,m,0),e.match_start-=m,e.strstart-=m,e.block_start-=m,t=r=e.hash_size;do{i=e.head[--t],e.head[t]=i>=m?i-m:0}while(--r);t=r=m;do{i=e.prev[--t],e.prev[t]=i>=m?i-m:0}while(--r);o+=m}if(0===e.strm.avail_in)break;if(h=e.strm,u=e.window,c=e.strstart+e.lookahead,f=o,p=void 0,(p=h.avail_in)>f&&(p=f),r=0===p?0:(h.avail_in-=p,n.arraySet(u,h.input,h.next_in,p,c),1===h.state.wrap?h.adler=a(h.adler,u,p,c):2===h.state.wrap&&(h.adler=s(h.adler,u,p,c)),h.next_in+=p,h.total_in+=p,p),e.lookahead+=r,e.lookahead+e.insert>=3)for(d=e.strstart-e.insert,e.ins_h=e.window[d],e.ins_h=(e.ins_h<=3&&(e.ins_h=(e.ins_h<=3)if(i=o._tr_tally(e,e.strstart-e.match_start,e.match_length-3),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=3){e.match_length--;do{e.strstart++,e.ins_h=(e.ins_h<=3&&(e.ins_h=(e.ins_h<4096)&&(e.match_length=2)),e.prev_length>=3&&e.match_length<=e.prev_length){n=e.strstart+e.lookahead-3,i=o._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-3),e.lookahead-=e.prev_length-1,e.prev_length-=2;do{++e.strstart<=n&&(e.ins_h=(e.ins_h<15&&(s=2,i-=16),o<1||o>9||8!==r||i<8||i>15||t<0||t>9||a<0||a>4)return m(e,h);8===i&&(i=9);var d=new T;return e.state=d,d.strm=e,d.wrap=s,d.gzhead=null,d.w_bits=i,d.w_size=1<e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(C(e),0===e.lookahead&&0===t)return 1;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var i=e.block_start+r;if((0===e.strstart||e.strstart>=i)&&(e.lookahead=e.strstart-i,e.strstart=i,b(e,!1),0===e.strm.avail_out))return 1;if(e.strstart-e.block_start>=e.w_size-l&&(b(e,!1),0===e.strm.avail_out))return 1}return e.insert=0,4===t?(b(e,!0),0===e.strm.avail_out?3:4):(e.strstart>e.block_start&&(b(e,!1),e.strm.avail_out),1)})),new B(4,4,8,4,x),new B(4,5,16,8,x),new B(4,6,32,32,x),new B(4,4,16,16,E),new B(8,16,32,32,E),new B(8,16,128,128,E),new B(8,32,128,256,E),new B(32,128,258,1024,E),new B(32,258,258,4096,E)],t.deflateInit=function(e,t){return U(e,t,8,15,8,0)},t.deflateInit2=U,t.deflateReset=S,t.deflateResetKeep=A,t.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?h:(e.state.gzhead=t,0):h},t.deflate=function(e,t){var r,n,a,d;if(!e||!e.state||t>5||t<0)return e?m(e,h):h;if(n=e.state,!e.output||!e.input&&0!==e.avail_in||n.status===p&&4!==t)return m(e,0===e.avail_out?-5:h);if(n.strm=e,r=n.last_flush,n.last_flush=t,42===n.status)if(2===n.wrap)e.adler=0,v(n,31),v(n,139),v(n,8),n.gzhead?(v(n,(n.gzhead.text?1:0)+(n.gzhead.hcrc?2:0)+(n.gzhead.extra?4:0)+(n.gzhead.name?8:0)+(n.gzhead.comment?16:0)),v(n,255&n.gzhead.time),v(n,n.gzhead.time>>8&255),v(n,n.gzhead.time>>16&255),v(n,n.gzhead.time>>24&255),v(n,9===n.level?2:n.strategy>=2||n.level<2?4:0),v(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(v(n,255&n.gzhead.extra.length),v(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=s(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=69):(v(n,0),v(n,0),v(n,0),v(n,0),v(n,0),v(n,9===n.level?2:n.strategy>=2||n.level<2?4:0),v(n,3),n.status=f);else{var l=8+(n.w_bits-8<<4)<<8;l|=(n.strategy>=2||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(l|=32),l+=31-l%31,n.status=f,w(n,l),0!==n.strstart&&(w(n,e.adler>>>16),w(n,65535&e.adler)),e.adler=1}if(69===n.status)if(n.gzhead.extra){for(a=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>a&&(e.adler=s(e.adler,n.pending_buf,n.pending-a,a)),_(e),a=n.pending,n.pending!==n.pending_buf_size));)v(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>a&&(e.adler=s(e.adler,n.pending_buf,n.pending-a,a)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=73)}else n.status=73;if(73===n.status)if(n.gzhead.name){a=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>a&&(e.adler=s(e.adler,n.pending_buf,n.pending-a,a)),_(e),a=n.pending,n.pending===n.pending_buf_size)){d=1;break}d=n.gzindexa&&(e.adler=s(e.adler,n.pending_buf,n.pending-a,a)),0===d&&(n.gzindex=0,n.status=91)}else n.status=91;if(91===n.status)if(n.gzhead.comment){a=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>a&&(e.adler=s(e.adler,n.pending_buf,n.pending-a,a)),_(e),a=n.pending,n.pending===n.pending_buf_size)){d=1;break}d=n.gzindexa&&(e.adler=s(e.adler,n.pending_buf,n.pending-a,a)),0===d&&(n.status=c)}else n.status=c;if(n.status===c&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&_(e),n.pending+2<=n.pending_buf_size&&(v(n,255&e.adler),v(n,e.adler>>8&255),e.adler=0,n.status=f)):n.status=f),0!==n.pending){if(_(e),0===e.avail_out)return n.last_flush=-1,0}else if(0===e.avail_in&&y(t)<=y(r)&&4!==t)return m(e,-5);if(n.status===p&&0!==e.avail_in)return m(e,-5);if(0!==e.avail_in||0!==n.lookahead||0!==t&&n.status!==p){var k=2===n.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(C(e),0===e.lookahead)){if(0===t)return 1;break}if(e.match_length=0,r=o._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(b(e,!1),0===e.strm.avail_out))return 1}return e.insert=0,4===t?(b(e,!0),0===e.strm.avail_out?3:4):e.last_lit&&(b(e,!1),0===e.strm.avail_out)?1:2}(n,t):3===n.strategy?function(e,t){for(var r,i,n,a,s=e.window;;){if(e.lookahead<=u){if(C(e),e.lookahead<=u&&0===t)return 1;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=3&&e.strstart>0&&(i=s[n=e.strstart-1])===s[++n]&&i===s[++n]&&i===s[++n]){a=e.strstart+u;do{}while(i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&ne.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=3?(r=o._tr_tally(e,1,e.match_length-3),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=o._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(b(e,!1),0===e.strm.avail_out))return 1}return e.insert=0,4===t?(b(e,!0),0===e.strm.avail_out?3:4):e.last_lit&&(b(e,!1),0===e.strm.avail_out)?1:2}(n,t):i[n.level].func(n,t);if(3!==k&&4!==k||(n.status=p),1===k||3===k)return 0===e.avail_out&&(n.last_flush=-1),0;if(2===k&&(1===t?o._tr_align(n):5!==t&&(o._tr_stored_block(n,0,0,!1),3===t&&(g(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),_(e),0===e.avail_out))return n.last_flush=-1,0}return 4!==t?0:n.wrap<=0?1:(2===n.wrap?(v(n,255&e.adler),v(n,e.adler>>8&255),v(n,e.adler>>16&255),v(n,e.adler>>24&255),v(n,255&e.total_in),v(n,e.total_in>>8&255),v(n,e.total_in>>16&255),v(n,e.total_in>>24&255)):(w(n,e.adler>>>16),w(n,65535&e.adler)),_(e),n.wrap>0&&(n.wrap=-n.wrap),0!==n.pending?0:1)},t.deflateEnd=function(e){var t;return e&&e.state?42!==(t=e.state.status)&&69!==t&&73!==t&&91!==t&&t!==c&&t!==f&&t!==p?m(e,h):(e.state=null,t===f?m(e,-3):0):h},t.deflateSetDictionary=function(e,t){var r,i,o,s,d,u,l,c,f=t.length;if(!e||!e.state)return h;if(2===(s=(r=e.state).wrap)||1===s&&42!==r.status||r.lookahead)return h;for(1===s&&(e.adler=a(e.adler,t,f,0)),r.wrap=0,f>=r.w_size&&(0===s&&(g(r.head),r.strstart=0,r.block_start=0,r.insert=0),c=new n.Buf8(r.w_size),n.arraySet(c,t,f-r.w_size,r.w_size,0),t=c,f=r.w_size),d=e.avail_in,u=e.next_in,l=e.input,e.avail_in=f,e.next_in=0,e.input=t,C(r);r.lookahead>=3;){i=r.strstart,o=r.lookahead-2;do{r.ins_h=(r.ins_h<=0;)e[t]=0}var o=256,a=286,s=30,d=15,h=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],u=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],l=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],c=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],f=new Array(576);n(f);var p=new Array(60);n(p);var m=new Array(512);n(m);var y=new Array(256);n(y);var g=new Array(29);n(g);var _,b,v,w=new Array(s);function k(e,t,r,i,n){this.static_tree=e,this.extra_bits=t,this.extra_base=r,this.elems=i,this.max_length=n,this.has_stree=e&&e.length}function C(e,t){this.dyn_tree=e,this.max_code=0,this.stat_desc=t}function x(e){return e<256?m[e]:m[256+(e>>>7)]}function E(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function B(e,t,r){e.bi_valid>16-r?(e.bi_buf|=t<>16-e.bi_valid,e.bi_valid+=r-16):(e.bi_buf|=t<>>=1,r<<=1}while(--t>0);return r>>>1}function S(e,t,r){var i,n,o=new Array(16),a=0;for(i=1;i<=d;i++)o[i]=a=a+r[i-1]<<1;for(n=0;n<=t;n++){var s=e[2*n+1];0!==s&&(e[2*n]=A(o[s]++,s))}}function U(e){var t;for(t=0;t8?E(e,e.bi_buf):e.bi_valid>0&&(e.pending_buf[e.pending++]=e.bi_buf),e.bi_buf=0,e.bi_valid=0}function I(e,t,r,i){var n=2*t,o=2*r;return e[n]>1;r>=1;r--)N(e,o,r);n=h;do{r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],N(e,o,1),i=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=i,o[2*n]=o[2*r]+o[2*i],e.depth[n]=(e.depth[r]>=e.depth[i]?e.depth[r]:e.depth[i])+1,o[2*r+1]=o[2*i+1]=n,e.heap[1]=n++,N(e,o,1)}while(e.heap_len>=2);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,i,n,o,a,s,h=t.dyn_tree,u=t.max_code,l=t.stat_desc.static_tree,c=t.stat_desc.has_stree,f=t.stat_desc.extra_bits,p=t.stat_desc.extra_base,m=t.stat_desc.max_length,y=0;for(o=0;o<=d;o++)e.bl_count[o]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<573;r++)(o=h[2*h[2*(i=e.heap[r])+1]+1]+1)>m&&(o=m,y++),h[2*i+1]=o,i>u||(e.bl_count[o]++,a=0,i>=p&&(a=f[i-p]),s=h[2*i],e.opt_len+=s*(o+a),c&&(e.static_len+=s*(l[2*i+1]+a)));if(0!==y){do{for(o=m-1;0===e.bl_count[o];)o--;e.bl_count[o]--,e.bl_count[o+1]+=2,e.bl_count[m]--,y-=2}while(y>0);for(o=m;0!==o;o--)for(i=e.bl_count[o];0!==i;)(n=e.heap[--r])>u||(h[2*n+1]!==o&&(e.opt_len+=(o-h[2*n+1])*h[2*n],h[2*n+1]=o),i--)}}(e,t),S(o,u,e.bl_count)}function F(e,t,r){var i,n,o=-1,a=t[1],s=0,d=7,h=4;for(0===a&&(d=138,h=3),t[2*(r+1)+1]=65535,i=0;i<=r;i++)n=a,a=t[2*(i+1)+1],++s>=7;i0?(2===e.strm.data_type&&(e.strm.data_type=function(e){var t,r=4093624447;for(t=0;t<=31;t++,r>>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return 0;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return 1;for(t=32;t=3&&0===e.bl_tree[2*c[t]+1];t--);return e.opt_len+=3*(t+1)+5+5+4,t}(e),n=e.opt_len+3+7>>>3,(a=e.static_len+3+7>>>3)<=n&&(n=a)):n=a=r+5,r+4<=n&&-1!==t?V(e,t,r,i):4===e.strategy||a===n?(B(e,2+(i?1:0),3),P(e,f,p)):(B(e,4+(i?1:0),3),function(e,t,r,i){var n;for(B(e,t-257,5),B(e,r-1,5),B(e,i-4,4),n=0;n>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(y[r]+o+1)]++,e.dyn_dtree[2*x(t)]++),e.last_lit===e.lit_bufsize-1},t._tr_align=function(e){B(e,2,3),T(e,256,f),function(e){16===e.bi_valid?(E(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):e.bi_valid>=8&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},function(e,t,r){"use strict";var i=r(36),n=r(5),o=r(19),a=r(21),s=r(12),d=r(20),h=r(39),u=Object.prototype.toString;function l(e){if(!(this instanceof l))return new l(e);this.options=n.assign({chunkSize:16384,windowBits:0,to:""},e||{});var t=this.options;t.raw&&t.windowBits>=0&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(t.windowBits>=0&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),t.windowBits>15&&t.windowBits<48&&0==(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new d,this.strm.avail_out=0;var r=i.inflateInit2(this.strm,t.windowBits);if(r!==a.Z_OK)throw new Error(s[r]);this.header=new h,i.inflateGetHeader(this.strm,this.header)}function c(e,t){var r=new l(t);if(r.push(e,!0),r.err)throw r.msg;return r.result}l.prototype.push=function(e,t){var r,s,d,h,l,c,f=this.strm,p=this.options.chunkSize,m=this.options.dictionary,y=!1;if(this.ended)return!1;s=t===~~t?t:!0===t?a.Z_FINISH:a.Z_NO_FLUSH,"string"==typeof e?f.input=o.binstring2buf(e):"[object ArrayBuffer]"===u.call(e)?f.input=new Uint8Array(e):f.input=e,f.next_in=0,f.avail_in=f.input.length;do{if(0===f.avail_out&&(f.output=new n.Buf8(p),f.next_out=0,f.avail_out=p),(r=i.inflate(f,a.Z_NO_FLUSH))===a.Z_NEED_DICT&&m&&(c="string"==typeof m?o.string2buf(m):"[object ArrayBuffer]"===u.call(m)?new Uint8Array(m):m,r=i.inflateSetDictionary(this.strm,c)),r===a.Z_BUF_ERROR&&!0===y&&(r=a.Z_OK,y=!1),r!==a.Z_STREAM_END&&r!==a.Z_OK)return this.onEnd(r),this.ended=!0,!1;f.next_out&&(0!==f.avail_out&&r!==a.Z_STREAM_END&&(0!==f.avail_in||s!==a.Z_FINISH&&s!==a.Z_SYNC_FLUSH)||("string"===this.options.to?(d=o.utf8border(f.output,f.next_out),h=f.next_out-d,l=o.buf2string(f.output,d),f.next_out=h,f.avail_out=p-h,h&&n.arraySet(f.output,f.output,d,h,0),this.onData(l)):this.onData(n.shrinkBuf(f.output,f.next_out)))),0===f.avail_in&&0===f.avail_out&&(y=!0)}while((f.avail_in>0||0===f.avail_out)&&r!==a.Z_STREAM_END);return r===a.Z_STREAM_END&&(s=a.Z_FINISH),s===a.Z_FINISH?(r=i.inflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===a.Z_OK):s!==a.Z_SYNC_FLUSH||(this.onEnd(a.Z_OK),f.avail_out=0,!0)},l.prototype.onData=function(e){this.chunks.push(e)},l.prototype.onEnd=function(e){e===a.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=n.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},t.Inflate=l,t.inflate=c,t.inflateRaw=function(e,t){return(t=t||{}).raw=!0,c(e,t)},t.ungzip=c},function(e,t,r){"use strict";var i=r(5),n=r(17),o=r(18),a=r(37),s=r(38),d=-2,h=12,u=30;function l(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function c(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new i.Buf16(320),this.work=new i.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=1,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new i.Buf32(852),t.distcode=t.distdyn=new i.Buf32(592),t.sane=1,t.back=-1,0):d}function p(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,f(e)):d}function m(e,t){var r,i;return e&&e.state?(i=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||t>15)?d:(null!==i.window&&i.wbits!==t&&(i.window=null),i.wrap=r,i.wbits=t,p(e))):d}function y(e,t){var r,i;return e?(i=new c,e.state=i,i.window=null,0!==(r=m(e,t))&&(e.state=null),r):d}var g,_,b=!0;function v(e){if(b){var t;for(g=new i.Buf32(512),_=new i.Buf32(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(s(1,e.lens,0,288,g,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;s(2,e.lens,0,32,_,0,e.work,{bits:5}),b=!1}e.lencode=g,e.lenbits=9,e.distcode=_,e.distbits=5}function w(e,t,r,n){var o,a=e.state;return null===a.window&&(a.wsize=1<=a.wsize?(i.arraySet(a.window,t,r-a.wsize,a.wsize,0),a.wnext=0,a.whave=a.wsize):((o=a.wsize-a.wnext)>n&&(o=n),i.arraySet(a.window,t,r-n,o,a.wnext),(n-=o)?(i.arraySet(a.window,t,r-n,n,0),a.wnext=n,a.whave=a.wsize):(a.wnext+=o,a.wnext===a.wsize&&(a.wnext=0),a.whave>>8&255,r.check=o(r.check,O,2,0),_=0,b=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&_)<<8)+(_>>8))%31){e.msg="incorrect header check",r.mode=u;break}if(8!=(15&_)){e.msg="unknown compression method",r.mode=u;break}if(b-=4,N=8+(15&(_>>>=4)),0===r.wbits)r.wbits=N;else if(N>r.wbits){e.msg="invalid window size",r.mode=u;break}r.dmax=1<>8&1),512&r.flags&&(O[0]=255&_,O[1]=_>>>8&255,r.check=o(r.check,O,2,0)),_=0,b=0,r.mode=3;case 3:for(;b<32;){if(0===y)break e;y--,_+=c[p++]<>>8&255,O[2]=_>>>16&255,O[3]=_>>>24&255,r.check=o(r.check,O,4,0)),_=0,b=0,r.mode=4;case 4:for(;b<16;){if(0===y)break e;y--,_+=c[p++]<>8),512&r.flags&&(O[0]=255&_,O[1]=_>>>8&255,r.check=o(r.check,O,2,0)),_=0,b=0,r.mode=5;case 5:if(1024&r.flags){for(;b<16;){if(0===y)break e;y--,_+=c[p++]<>>8&255,r.check=o(r.check,O,2,0)),_=0,b=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&((x=r.length)>y&&(x=y),x&&(r.head&&(N=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),i.arraySet(r.head.extra,c,p,x,N)),512&r.flags&&(r.check=o(r.check,c,x,p)),y-=x,p+=x,r.length-=x),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===y)break e;x=0;do{N=c[p+x++],r.head&&N&&r.length<65536&&(r.head.name+=String.fromCharCode(N))}while(N&&x>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=h;break;case 10:for(;b<32;){if(0===y)break e;y--,_+=c[p++]<>>=7&b,b-=7&b,r.mode=27;break}for(;b<3;){if(0===y)break e;y--,_+=c[p++]<>>=1)){case 0:r.mode=14;break;case 1:if(v(r),r.mode=20,6===t){_>>>=2,b-=2;break e}break;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=u}_>>>=2,b-=2;break;case 14:for(_>>>=7&b,b-=7&b;b<32;){if(0===y)break e;y--,_+=c[p++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=u;break}if(r.length=65535&_,_=0,b=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(x=r.length){if(x>y&&(x=y),x>g&&(x=g),0===x)break e;i.arraySet(f,c,p,x,m),y-=x,p+=x,g-=x,m+=x,r.length-=x;break}r.mode=h;break;case 17:for(;b<14;){if(0===y)break e;y--,_+=c[p++]<>>=5,b-=5,r.ndist=1+(31&_),_>>>=5,b-=5,r.ncode=4+(15&_),_>>>=4,b-=4,r.nlen>286||r.ndist>30){e.msg="too many length or distance symbols",r.mode=u;break}r.have=0,r.mode=18;case 18:for(;r.have>>=3,b-=3}for(;r.have<19;)r.lens[V[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,M={bits:r.lenbits},P=s(0,r.lens,0,19,r.lencode,0,r.work,M),r.lenbits=M.bits,P){e.msg="invalid code lengths set",r.mode=u;break}r.have=0,r.mode=19;case 19:for(;r.have>>16&255,S=65535&z,!((T=z>>>24)<=b);){if(0===y)break e;y--,_+=c[p++]<>>=T,b-=T,r.lens[r.have++]=S;else{if(16===S){for(F=T+2;b>>=T,b-=T,0===r.have){e.msg="invalid bit length repeat",r.mode=u;break}N=r.lens[r.have-1],x=3+(3&_),_>>>=2,b-=2}else if(17===S){for(F=T+3;b>>=T)),_>>>=3,b-=3}else{for(F=T+7;b>>=T)),_>>>=7,b-=7}if(r.have+x>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=u;break}for(;x--;)r.lens[r.have++]=N}}if(r.mode===u)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=u;break}if(r.lenbits=9,M={bits:r.lenbits},P=s(1,r.lens,0,r.nlen,r.lencode,0,r.work,M),r.lenbits=M.bits,P){e.msg="invalid literal/lengths set",r.mode=u;break}if(r.distbits=6,r.distcode=r.distdyn,M={bits:r.distbits},P=s(2,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,M),r.distbits=M.bits,P){e.msg="invalid distances set",r.mode=u;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(y>=6&&g>=258){e.next_out=m,e.avail_out=g,e.next_in=p,e.avail_in=y,r.hold=_,r.bits=b,a(e,C),m=e.next_out,f=e.output,g=e.avail_out,p=e.next_in,c=e.input,y=e.avail_in,_=r.hold,b=r.bits,r.mode===h&&(r.back=-1);break}for(r.back=0;A=(z=r.lencode[_&(1<>>16&255,S=65535&z,!((T=z>>>24)<=b);){if(0===y)break e;y--,_+=c[p++]<>U)])>>>16&255,S=65535&z,!(U+(T=z>>>24)<=b);){if(0===y)break e;y--,_+=c[p++]<>>=U,b-=U,r.back+=U}if(_>>>=T,b-=T,r.back+=T,r.length=S,0===A){r.mode=26;break}if(32&A){r.back=-1,r.mode=h;break}if(64&A){e.msg="invalid literal/length code",r.mode=u;break}r.extra=15&A,r.mode=22;case 22:if(r.extra){for(F=r.extra;b>>=r.extra,b-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;A=(z=r.distcode[_&(1<>>16&255,S=65535&z,!((T=z>>>24)<=b);){if(0===y)break e;y--,_+=c[p++]<>U)])>>>16&255,S=65535&z,!(U+(T=z>>>24)<=b);){if(0===y)break e;y--,_+=c[p++]<>>=U,b-=U,r.back+=U}if(_>>>=T,b-=T,r.back+=T,64&A){e.msg="invalid distance code",r.mode=u;break}r.offset=S,r.extra=15&A,r.mode=24;case 24:if(r.extra){for(F=r.extra;b>>=r.extra,b-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=u;break}r.mode=25;case 25:if(0===g)break e;if(x=C-g,r.offset>x){if((x=r.offset-x)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=u;break}x>r.wnext?(x-=r.wnext,E=r.wsize-x):E=r.wnext-x,x>r.length&&(x=r.length),B=r.window}else B=f,E=m-r.offset,x=r.length;x>g&&(x=g),g-=x,r.length-=x;do{f[m++]=B[E++]}while(--x);0===r.length&&(r.mode=21);break;case 26:if(0===g)break e;f[m++]=r.length,g--,r.mode=21;break;case 27:if(r.wrap){for(;b<32;){if(0===y)break e;y--,_|=c[p++]<>>=v=b>>>24,p-=v,0===(v=b>>>16&255))B[o++]=65535&b;else{if(!(16&v)){if(0==(64&v)){b=m[(65535&b)+(f&(1<>>=v,p-=v),p<15&&(f+=E[i++]<>>=v=b>>>24,p-=v,!(16&(v=b>>>16&255))){if(0==(64&v)){b=y[(65535&b)+(f&(1<d){e.msg="invalid distance too far back",r.mode=30;break e}if(f>>>=v,p-=v,k>(v=o-a)){if((v=k-v)>u&&r.sane){e.msg="invalid distance too far back",r.mode=30;break e}if(C=0,x=c,0===l){if(C+=h-v,v2;)B[o++]=x[C++],B[o++]=x[C++],B[o++]=x[C++],w-=3;w&&(B[o++]=x[C++],w>1&&(B[o++]=x[C++]))}else{C=o-k;do{B[o++]=B[C++],B[o++]=B[C++],B[o++]=B[C++],w-=3}while(w>2);w&&(B[o++]=B[C++],w>1&&(B[o++]=B[C++]))}break}}break}}while(i>3,f&=(1<<(p-=w<<3))-1,e.next_in=i,e.next_out=o,e.avail_in=i=1&&0===F[T];T--);if(A>T&&(A=T),0===T)return u[l++]=20971520,u[l++]=20971520,f.bits=1,0;for(B=1;B0&&(0===e||1!==T))return-1;for(z[1]=0,x=1;x852||2===e&&I>592)return 1;for(;;){v=x-U,c[E]b?(w=O[V+c[E]],k=P[M+c[E]]):(w=96,k=0),p=1<>U)+(m-=p)]=v<<24|w<<16|k|0}while(0!==m);for(p=1<>=1;if(0!==p?(N&=p-1,N+=p):N=0,E++,0==--F[x]){if(x===T)break;x=t[r+c[E]]}if(x>A&&(N&g)!==y){for(0===U&&(U=A),_+=B,D=1<<(S=x-U);S+U852||2===e&&I>592)return 1;u[y=N&g]=A<<24|S<<16|_-l|0}}return 0!==N&&(u[_+N]=x-U<<24|64<<16|0),f.bits=A,0}},function(e,t,r){"use strict";e.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},function(e,t,r){var i=r(41);e.exports={TextEncoder:i.TextEncoder,TextDecoder:i.TextDecoder}},function(e,t,r){!function(t){"use strict";function r(e,t,r){return t<=e&&e<=r}function i(e){if(void 0===e)return{};if(e===Object(e))return e;throw TypeError("Could not convert argument to dictionary")}var n=-1;function o(e){this.tokens=[].slice.call(e),this.tokens.reverse()}o.prototype={endOfStream:function(){return!this.tokens.length},read:function(){return this.tokens.length?this.tokens.pop():n},prepend:function(e){if(Array.isArray(e))for(var t=e;t.length;)this.tokens.push(t.pop());else this.tokens.push(e)},push:function(e){if(Array.isArray(e))for(var t=e;t.length;)this.tokens.unshift(t.shift());else this.tokens.unshift(e)}};var a=-1;function s(e,t){if(e)throw TypeError("Decoder error");return t||65533}function d(e){return e=String(e).trim().toLowerCase(),Object.prototype.hasOwnProperty.call(h,e)?h[e]:null}var h={};[{encodings:[{labels:["unicode-1-1-utf-8","utf-8","utf8"],name:"UTF-8"}],heading:"The Encoding"}].forEach((function(e){e.encodings.forEach((function(e){e.labels.forEach((function(t){h[t]=e}))}))}));var u={},l={};function c(e,t){if(!(this instanceof c))throw TypeError("Called as a function. Did you forget 'new'?");e=void 0!==e?String(e):"utf-8",t=i(t),this._encoding=null,this._decoder=null,this._ignoreBOM=!1,this._BOMseen=!1,this._error_mode="replacement",this._do_not_flush=!1;var r=d(e);if(null===r||"replacement"===r.name)throw RangeError("Unknown encoding: "+e);if(!l[r.name])throw Error("Decoder not present. Did you forget to include encoding-indexes.js?");var n=this;return n._encoding=r,Boolean(t.fatal)&&(n._error_mode="fatal"),Boolean(t.ignoreBOM)&&(n._ignoreBOM=!0),n}function f(e,r){if(!(this instanceof f))throw TypeError("Called as a function. Did you forget 'new'?");r=i(r),this._encoding=null,this._encoder=null,this._do_not_flush=!1,this._fatal=Boolean(r.fatal)?"fatal":"replacement";return this._encoding=d("utf-8"),void 0!==e&&"console"in t&&console.warn("TextEncoder constructor called with encoding label, which is ignored."),this}function p(e){var t=e.fatal,i=0,o=0,d=0,h=128,u=191;this.handler=function(e,l){if(l===n&&0!==d)return d=0,s(t);if(l===n)return a;if(0===d){if(r(l,0,127))return l;if(r(l,194,223))d=1,i=31&l;else if(r(l,224,239))224===l&&(h=160),237===l&&(u=159),d=2,i=15&l;else{if(!r(l,240,244))return s(t);240===l&&(h=144),244===l&&(u=143),d=3,i=7&l}return null}if(!r(l,h,u))return i=d=o=0,h=128,u=191,e.prepend(l),s(t);if(h=128,u=191,i=i<<6|63&l,(o+=1)!==d)return null;var c=i;return i=d=o=0,c}}function m(e){e.fatal;this.handler=function(e,t){if(t===n)return a;if(r(t,0,127))return t;var i,o;r(t,128,2047)?(i=1,o=192):r(t,2048,65535)?(i=2,o=224):r(t,65536,1114111)&&(i=3,o=240);for(var s=[(t>>6*i)+o];i>0;){var d=t>>6*(i-1);s.push(128|63&d),i-=1}return s}}Object.defineProperty&&(Object.defineProperty(c.prototype,"encoding",{get:function(){return this._encoding.name.toLowerCase()}}),Object.defineProperty(c.prototype,"fatal",{get:function(){return"fatal"===this._error_mode}}),Object.defineProperty(c.prototype,"ignoreBOM",{get:function(){return this._ignoreBOM}})),c.prototype.decode=function(e,t){var r;r="object"==typeof e&&e instanceof ArrayBuffer?new Uint8Array(e):"object"==typeof e&&"buffer"in e&&e.buffer instanceof ArrayBuffer?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(0),t=i(t),this._do_not_flush||(this._decoder=l[this._encoding.name]({fatal:"fatal"===this._error_mode}),this._BOMseen=!1),this._do_not_flush=Boolean(t.stream);for(var s,d=new o(r),h=[];;){var u=d.read();if(u===n)break;if((s=this._decoder.handler(d,u))===a)break;null!==s&&(Array.isArray(s)?h.push.apply(h,s):h.push(s))}if(!this._do_not_flush){do{if((s=this._decoder.handler(d,d.read()))===a)break;null!==s&&(Array.isArray(s)?h.push.apply(h,s):h.push(s))}while(!d.endOfStream());this._decoder=null}return function(e){var t,r;return t=["UTF-8","UTF-16LE","UTF-16BE"],r=this._encoding.name,-1===t.indexOf(r)||this._ignoreBOM||this._BOMseen||(e.length>0&&65279===e[0]?(this._BOMseen=!0,e.shift()):e.length>0&&(this._BOMseen=!0)),function(e){for(var t="",r=0;r>10),56320+(1023&i)))}return t}(e)}.call(this,h)},Object.defineProperty&&Object.defineProperty(f.prototype,"encoding",{get:function(){return this._encoding.name.toLowerCase()}}),f.prototype.encode=function(e,t){e=e?String(e):"",t=i(t),this._do_not_flush||(this._encoder=u[this._encoding.name]({fatal:"fatal"===this._fatal})),this._do_not_flush=Boolean(t.stream);for(var r,s=new o(function(e){for(var t=String(e),r=t.length,i=0,n=[];i57343)n.push(o);else if(56320<=o&&o<=57343)n.push(65533);else if(55296<=o&&o<=56319)if(i===r-1)n.push(65533);else{var a=t.charCodeAt(i+1);if(56320<=a&&a<=57343){var s=1023&o,d=1023&a;n.push(65536+(s<<10)+d),i+=1}else n.push(65533)}i+=1}return n}(e)),d=[];;){var h=s.read();if(h===n)break;if((r=this._encoder.handler(s,h))===a)break;Array.isArray(r)?d.push.apply(d,r):d.push(r)}if(!this._do_not_flush){for(;(r=this._encoder.handler(s,s.read()))!==a;)Array.isArray(r)?d.push.apply(d,r):d.push(r);this._encoder=null}return new Uint8Array(d)},u["UTF-8"]=function(e){return new m(e)},l["UTF-8"]=function(e){return new p(e)},t.TextEncoder||(t.TextEncoder=f),t.TextDecoder||(t.TextDecoder=c),e.exports&&(e.exports={TextEncoder:t.TextEncoder,TextDecoder:t.TextDecoder})}(this)},function(t,r){t.exports=e},function(e,t,r){"use strict";var i=r(4),n=function(e){this.kdbx=e.kdbx,this.exportXml=e.exportXml||!1};n.prototype.setXmlDate=function(e,t){var r=this.kdbx.header.versionMajor>=4&&!this.exportXml;i.setDate(e,t,r)},e.exports=n},function(e,r){e.exports=t},function(e,t,r){"use strict";var i=r(11),n=r(2),o=r(1),a=r(0),s=r(3);e.exports.decrypt=function(e){return Promise.resolve().then((function(){var t,r=new i(e),d=[],h=0,u=0,l=function(){if(r.getUint32(!0),t=r.readBytes(32),(h=r.getUint32(!0))>0){u+=h;var e=r.readBytes(h);return s.sha256(e).then((function(r){if(a.arrayBufferEquals(r,t))return d.push(e),l();throw new n(o.ErrorCodes.FileCorrupt,"invalid hash block")}))}for(var i=new Uint8Array(u),c=0,f=0;f0){var h=Math.min(1048576,t);t-=h;var u=e.slice(r,r+h);return s.sha256(u).then((function(e){var t=new ArrayBuffer(40),s=new i(t);return s.setUint32(n,!0),s.writeBytes(e),s.setUint32(h,!0),a.push(t),o+=t.byteLength,a.push(u),o+=u.byteLength,n++,r+=h,d()}))}var l=new ArrayBuffer(40);new DataView(l).setUint32(0,n,!0),a.push(l),o+=l.byteLength;for(var c=new Uint8Array(o),f=0,p=0;p0){h+=d;var c=r.readBytes(d);return u(t,s,d,c).then((function(t){if(a.arrayBufferEquals(t,e))return i.push(c),s++,l();throw new n(o.ErrorCodes.FileCorrupt,"invalid hash block")}))}for(var f=new Uint8Array(h),p=0,m=0;m0)return a.push(l),o+=l.byteLength,n++,i+=h,d();for(var u=new Uint8Array(o),c=0,f=0;fthis.nameChanged&&(this._name=e.name,this.nameChanged=e.nameChanged),e.descChanged>this.descChanged&&(this._desc=e.desc,this.descChanged=e.descChanged),e.defaultUserChanged>this.defaultUserChanged&&(this._defaultUser=e.defaultUser,this.defaultUserChanged=e.defaultUserChanged),e.keyChanged>this.keyChanged&&(this.keyChanged=e.keyChanged),e.settingsChanged>this.settingsChanged&&(this.settingsChanged=e.settingsChanged),e.recycleBinChanged>this.recycleBinChanged&&(this._recycleBinEnabled=e.recycleBinEnabled,this._recycleBinUuid=e.recycleBinUuid,this.recycleBinChanged=e.recycleBinChanged),e.entryTemplatesGroupChanged>this.entryTemplatesGroupChanged&&(this._entryTemplatesGroup=e.entryTemplatesGroup,this.entryTemplatesGroupChanged=e.entryTemplatesGroupChanged),Object.keys(e.customData).forEach((function(r){this.customData[r]||t.deleted[r]||(this.customData[r]=e.customData[r])}),this),Object.keys(e.customIcons).forEach((function(r){this.customIcons[r]||t.deleted[r]||(this.customIcons[r]=e.customIcons[r])}),this),this._editState&&this._editState.historyMaxItems||(this.historyMaxItems=e.historyMaxItems),this._editState&&this._editState.historyMaxSize||(this.historyMaxSize=e.historyMaxSize),this._editState&&this._editState.keyChangeRec||(this.keyChangeRec=e.keyChangeRec),this._editState&&this._editState.keyChangeForce||(this.keyChangeForce=e.keyChangeForce),this._editState&&this._editState.mntncHistoryDays||(this.mntncHistoryDays=e.mntncHistoryDays),this._editState&&this._editState.color||(this.color=e.color)},h.create=function(){var e=new Date,t=new h;return t.generator=d.Generator,t.settingsChanged=e,t.mntncHistoryDays=s.Defaults.MntncHistoryDays,t.recycleBinEnabled=!0,t.historyMaxItems=s.Defaults.HistoryMaxItems,t.historyMaxSize=s.Defaults.HistoryMaxSize,t.nameChanged=e,t.descChanged=e,t.defaultUserChanged=e,t.recycleBinChanged=e,t.keyChangeRec=-1,t.keyChangeForce=-1,t.entryTemplatesGroup=new n,t.entryTemplatesGroupChanged=e,t.memoryProtection={title:!1,userName:!1,password:!0,url:!1,notes:!1},t},h.read=function(e,t){for(var r=new h,i=0,n=e.childNodes,o=n.length;ithis.times.lastModTime&&this.copyFrom(t),this.groups=this._mergeCollection(this.groups,t.groups,e),this.entries=this._mergeCollection(this.entries,t.entries,e),this.groups.forEach((function(t){t.merge(e)})),this.entries.forEach((function(t){t.merge(e)})))},u.prototype._mergeCollection=function(e,t,r){var i=[];return e.forEach((function(e){if(!r.deleted[e.uuid]){var t=r.remote[e.uuid];t?t.times.locationChanged<=e.times.locationChanged&&i.push(e):i.push(e)}}),this),t.forEach((function(e,n){if(!r.deleted[e.uuid]){var o=r.objects[e.uuid];if(o&&e.times.locationChanged>o.times.locationChanged)o.parentGroup=this,i.splice(this._findInsertIx(i,t,n),0,o);else if(!o){var a=new e.constructor;a.copyFrom(e),a.parentGroup=this,i.splice(this._findInsertIx(i,t,n),0,a)}}}),this),i},u.prototype._findInsertIx=function(e,t,r){for(var i=e.length,n=-1,o=0;o<=e.length;o++){var a=0,s=r>0?t[r-1].uuid.id:void 0,d=r+10?e[o-1].uuid.id:void 0,u=on&&(i=o,n=a)}return i},u.prototype.copyFrom=function(e){this.uuid=e.uuid,this.name=e.name,this.notes=e.notes,this.icon=e.icon,this.customIcon=e.customIcon,this.times=e.times.clone(),this.expanded=e.expanded,this.defaultAutoTypeSeq=e.defaultAutoTypeSeq,this.enableAutoType=e.enableAutoType,this.enableSearching=e.enableSearching,this.lastTopVisibleEntry=e.lastTopVisibleEntry},u.create=function(e,t){var r=new u;return r.uuid=d.random(),r.icon=o.Icons.Folder,r.times=s.create(),r.name=e,r.parentGroup=t,r.expanded=!0,r.enableAutoType=null,r.enableSearching=null,r.lastTopVisibleEntry=new d,r},u.read=function(e,t,r){for(var i=new u,n=0,o=e.childNodes,a=o.length;n").html(problems.join("
\n")), + }); + } + + if (!verify) { + await this.rpc("/vault/replace", {data: changes}); + await this.model.root.load(); + } + } finally { + framework.unblockUI(); + } + }, + + /** + * Call the right importer in the import wizard onchange of the content field + * + * @private + */ + async _vaultImportWizard() { + const record = this.model.root; + if (record.resModel !== "vault.import.wizard") return; + + // Try to import the file on the fly and store the compatible JSON in the + // crypted_content field for the python backend + const importer = new Importer(); + const data = await importer.import( + await vault.unwrap(record.data.master_key), + record.data.name, + atob(record.data.content) + ); + + if (data) await record.update({crypted_content: JSON.stringify(data)}); + }, + + /** + * Ensure that a vault.right as the shared master_key set + * + * @private + * @param {Object} root + * @param {Object} right + */ + async _vaultEnsureRightKey(root, right) { + if (!root.data.master_key || right.data.key) return; + + const params = {user_id: right.data.user_id[0]}; + const user = await this.rpc("/vault/public", params); + + if (!user || !user.public_key) throw new TypeError("User has no public key"); + + await right.update({ + key: await vault.share(root.data.master_key, user.public_key), + }); + }, + + /** + * Ensures that the master_key of the vault and right lines are set + * + * @private + */ + async _vaultEnsureKeys() { + const root = this.model.root; + if (root.resModel !== "vault") return; + + if (!root.data.master_key) + await root.update({ + master_key: await vault.wrap(await utils.generate_key()), + }); + + if (root.data.right_ids) + for (const right of root.data.right_ids.records) + await this._vaultEnsureRightKey(root, right); + }, + + /** + * Check the model of the form and call the above functions for the right case + * + * @private + * @param {Object} button + */ + async _vaultAction(button) { + if (!utils.supported()) { + await this.dialogService.add(AlertDialog, { + title: _lt("Vault is not supported"), + body: _lt( + "A secure browser context is required. Please switch to " + + "https or contact your administrator" + ), + }); + return false; + } + + const root = this.model.root; + switch (root.resModel) { + case "res.users": + if (button && button.name === "vault_generate_key") { + await this._vaultRegenerateKey(); + return false; + } + break; + case "vault": + if (button && button.name === "vault_reencrypt") { + await this._reencryptVault(false, true); + return false; + } else if (button && button.name === "vault_verify") { + await this._reencryptVault(true, false); + return false; + } + + await this._vaultEnsureKeys(); + break; + + case "vault.send.wizard": + await this._vaultSendWizard(); + break; + + case "vault.store.wizard": + await this._vaultStoreWizard(); + break; + + case "vault.import.wizard": + await this._vaultImportWizard(); + break; + } + + return true; + }, + + /** + * Add the required rpc service to the controller which will be used to + * get/store information from/to the vault controller + */ + setup() { + if (this.props.resModel === "vault" && !utils.supported()) { + this.props.preventCreate = true; + this.props.preventEdit = true; + } + + this._super(...arguments); + this.rpc = useService("rpc"); + }, + + /** + * Hook into the relevant functions + */ + async create() { + const _super = this._super.bind(this); + if (this.model.root.isDirty) await this._vaultAction(); + + const ret = await _super(...arguments); + return ret; + }, + + async onPagerUpdate() { + const _super = this._super.bind(this); + if (this.model.root.isDirty) await this._vaultAction(); + return await _super(...arguments); + }, + + async saveButtonClicked() { + const _super = this._super.bind(this); + if (this.model.root.isDirty) await this._vaultAction(); + return await _super(...arguments); + }, + + async beforeLeave() { + const _super = this._super.bind(this); + if (this.model.root.isDirty) await this._vaultAction(); + return await _super(...arguments); + }, + + async beforeUnload() { + const _super = this._super.bind(this); + if (this.model.root.isDirty) await this._vaultAction(); + return await _super(...arguments); + }, + + async beforeExecuteActionButton(clickParams) { + const _super = this._super.bind(this); + if (clickParams.special !== "cancel") { + const _continue = await this._vaultAction(clickParams); + if (!_continue) return false; + } + + return await _super(...arguments); + }, +}); + +patch(ListController.prototype, "vault", { + setup() { + this._super(...arguments); + if (this.props.resModel === "vault" && !utils.supported()) + this.props.showButtons = false; + }, +}); diff --git a/vault/static/src/backend/export.esm.js b/vault/static/src/backend/export.esm.js new file mode 100644 index 0000000000..f14ac14cec --- /dev/null +++ b/vault/static/src/backend/export.esm.js @@ -0,0 +1,128 @@ +/** @odoo-module alias=vault.export **/ +// © 2021-2024 Florian Kantelberg - initOS GmbH +// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import {_lt} from "@web/core/l10n/translation"; +import utils from "vault.utils"; + +// This class handles the export to different formats by using a standardize +// JSON formatted data generated by the python backend. +// +// JSON format description: +// +// Entries are represented as objects with the following attributes +// `name`, `uuid`, `url`, `note` +// Specific fields of the entry. `uuid` is used for updating existing records +// `childs` +// Child entries +// `fields`, `files` +// List of encypted fields/files with `name`, `iv`, and `value` +// +export default class VaultExporter { + /** + * Encrypt a field of the above format properly for the backend to store. + * The changes are done inplace. + * + * @private + * @param {CryptoKey} master_key + * @param {Object} node + */ + async _export_json_entry(master_key, node) { + const fields = []; + for (const field of node.fields || []) + fields.push({ + name: field.name, + value: await utils.sym_decrypt(master_key, field.value, field.iv), + }); + + const files = []; + for (const file of node.files || []) + files.push({ + name: file.name, + value: await utils.sym_decrypt(master_key, file.value, file.iv), + }); + + const childs = []; + for (const entry of node.childs || []) + childs.push(await this._export_json_entry(master_key, entry)); + + return { + name: node.name || "", + uuid: node.uuid || null, + url: node.url || "", + note: node.note || "", + childs: childs, + fields: fields, + files: files, + }; + } + + /** + * Decrypt the data fro the JSON export. + * + * @private + * @param {CryptoKey} master_key + * @param {Object} data + * @returns the encrypted entry for the database + */ + async _export_json_data(master_key, data) { + const result = []; + for (const node of data) + result.push(await this._export_json_entry(master_key, node)); + return JSON.stringify(result); + } + + /** + * Export using JSON format. The database is stored in the `data` field of the JSON + * type and is an encrypted JSON object. For the encryption the needed encryption + * parameter `iv`, `salt` and `iterations` are stored in the file. + * This will add `iv` to fields and files and encrypt the `value` + * + * @private + * @param {CryptoKey} master_key + * @param {String} data + * @returns the encrypted entry for the database + */ + async _export_json(master_key, data) { + // Get the password for the exported file from the user + const askpass = await utils.askpass( + _lt("Please enter the password for the database") + ); + let password = askpass.password || ""; + if (askpass.keyfile) + password += await utils.digest(utils.toBinary(askpass.keyfile)); + + const iv = utils.generate_iv_base64(); + const salt = utils.generate_bytes(utils.SaltLength).buffer; + const iterations = utils.Derive.iterations; + const key = await utils.derive_key(password, salt, iterations); + + // Unwrap the master key and decrypt the entries + const content = await this._export_json_data(master_key, JSON.parse(data)); + return { + type: "encrypted", + iv: iv, + salt: utils.toBase64(salt), + data: await utils.sym_encrypt(key, content, iv), + iterations: iterations, + }; + } + + /** + * The main export functions which checks the file ending and calls the right function + * to handle the rest of the export + * + * @private + * @param {CryptoKey} master_key + * @param {String} filename + * @param {String} content + * @returns the data importable by the backend or false on error + */ + async export(master_key, filename, content) { + if (!utils.supported()) return false; + + if (filename.endsWith(".json")) + return await this._export_json(master_key, content); + return false; + } +} diff --git a/vault/static/src/backend/fields/templates.xml b/vault/static/src/backend/fields/templates.xml new file mode 100644 index 0000000000..b5619af48b --- /dev/null +++ b/vault/static/src/backend/fields/templates.xml @@ -0,0 +1,121 @@ + + + +