Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added encryption in registry documents #233

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ addon | version | maintainers | summary
[g2p_registry_base](g2p_registry_base/) | 17.0.1.4.0 | | G2P Registry: Base
[g2p_registry_datashare_websub](g2p_registry_datashare_websub/) | 17.0.1.4.0 | | G2P Registry Datashare: WebSub
[g2p_registry_deduplication_deduplicator](g2p_registry_deduplication_deduplicator/) | 17.0.0.0.0 | | OpenG2P Registry Deduplication - Deduplicator
[g2p_registry_document_encryption](g2p_registry_document_encryption/) | 17.0.1.4.0 | | G2P Registry: Documents Encryption
[g2p_registry_documents](g2p_registry_documents/) | 17.0.1.4.0 | | G2P Registry: Documents
[g2p_registry_encryption](g2p_registry_encryption/) | 17.0.1.4.0 | | G2P Registry: Encryption
[g2p_registry_group](g2p_registry_group/) | 17.0.1.4.0 | | G2P Registry: Groups
Expand Down
3 changes: 3 additions & 0 deletions g2p_registry_document_encryption/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# G2P Registry Document Encryption

Refer to https://docs.openg2p.org.
2 changes: 2 additions & 0 deletions g2p_registry_document_encryption/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import controllers
from . import models
24 changes: 24 additions & 0 deletions g2p_registry_document_encryption/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Part of OpenG2P. See LICENSE file for full copyright and licensing details.
{
"name": "G2P Registry: Documents Encryption",
"category": "G2P",
"version": "17.0.1.4.0",
"sequence": 1,
"author": "OpenG2P",
"website": "https://openg2p.org",
"license": "LGPL-3",
"depends": ["g2p_registry_documents", "g2p_registry_encryption", "g2p_documents"],
"data": [
"views/registrant_document_views.xml",
],
"assets": {
"web.assets_backend": [
"g2p_registry_document_encryption/static/src/js/preview_document.js",
],
},
"demo": [],
"images": [],
"application": True,
"installable": True,
"auto_install": False,
}
1 change: 1 addition & 0 deletions g2p_registry_document_encryption/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import main
31 changes: 31 additions & 0 deletions g2p_registry_document_encryption/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import base64

from odoo import http
from odoo.http import request

from odoo.addons.storage_file.controllers.main import StorageFileController


class CustomStorageFileController(StorageFileController):
@http.route(["/storage.file/<string:slug_name_with_id>"], type="http", auth="public")
def content_common(self, slug_name_with_id, token=None, download=None, **kw):
storage_file = request.env["storage.file"].get_from_slug_name_with_id(slug_name_with_id)
is_decrypt_fields = (
request.env["ir.config_parameter"]
.sudo()
.get_param("g2p_registry_encryption.decrypt_registry", default=False)
)

if not is_decrypt_fields or not storage_file.is_encrypted:
return request.env["ir.binary"]._get_image_stream_from(storage_file, "data").get_response()

prov = request.env["g2p.encryption.provider"].get_registry_provider()
decrypted_data = prov.decrypt_data(base64.b64decode(storage_file.data))
return request.make_response(
decrypted_data,
headers=[
("Content-Type", storage_file.mimetype),
("Content-Disposition", f"inline; filename={storage_file.name}"),
("Cache-Control", "no-cache"),
],
)
2 changes: 2 additions & 0 deletions g2p_registry_document_encryption/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import document_file
from . import document_store
34 changes: 34 additions & 0 deletions g2p_registry_document_encryption/models/document_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import base64

from odoo import fields, models


class G2PDocumentRegistry(models.Model):
_inherit = "storage.file"

is_encrypted = fields.Boolean(string="Encrypted", default=False)

def _inverse_data(self):
for record in self:
record.write(record._prepare_meta_for_file())
if not record.mimetype:
binary_data = base64.b64decode(record.data)
mime = self._get_mime_type(binary_data)
record.mimetype = mime

is_encrypt_fields = (
self.env["ir.config_parameter"]
.sudo()
.get_param("g2p_registry_encryption.encrypt_registry", default=False)
)

if is_encrypt_fields and not record.program_membership_id:
record.is_encrypted = True

record.backend_id.sudo().add(
record.relative_path,
record.data,
mimetype=record.mimetype,
binary=False,
program_membership_id=record.program_membership_id.id,
)
23 changes: 23 additions & 0 deletions g2p_registry_document_encryption/models/document_store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import base64

from odoo import models


class G2PDocumentStore(models.Model):
_inherit = "storage.backend"

def add(self, relative_path, data, binary=True, program_membership_id=None, **kwargs):
if not binary:
data = base64.b64decode(data)

is_encrypt_fields = (
self.env["ir.config_parameter"]
.sudo()
.get_param("g2p_registry_encryption.encrypt_registry", default=False)
)

if is_encrypt_fields and not program_membership_id:
prov = self.env["g2p.encryption.provider"].get_registry_provider()
data = prov.encrypt_data(data)

return self._forward("add", relative_path, data, **kwargs)
3 changes: 3 additions & 0 deletions g2p_registry_document_encryption/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
110 changes: 110 additions & 0 deletions g2p_registry_document_encryption/static/src/js/preview_document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/** @odoo-module **/
import {Component, onWillStart, xml} from "@odoo/owl";
import {registry} from "@web/core/registry";
import {useFileViewer} from "@web/core/file_viewer/file_viewer_hook";
import {useService} from "@web/core/utils/hooks";

// Unregister the existing widget (if any)
registry.category("view_widgets").remove("action_preview");

class Widgetpreview extends Component {
static template = xml`
<t>
<button
class="btn btn-primary"
icon="fa-file-text-o"
t-on-click="clickPreview"
t-if="canPreview"
>
Preview
</button>
<span t-else="">Encrypted</span>
</t>
`;

setup() {
super.setup();
this.fileViewer = useFileViewer();
this.store = useService("mail.store");
this.rpc = useService("rpc");

// Fetch and check the decrypt registry value on start
onWillStart(async () => {
this.decryptRegistry = await this._getDecryptRegistryValue();
this.canPreview = this._checkPreviewConditions();
});
}

// Fetch the decryption parameter from the ir.config_parameter model
async _getDecryptRegistryValue() {
const result = await this.rpc("/web/dataset/call_kw/ir.config_parameter/get_param", {
model: "ir.config_parameter",
method: "get_param",
args: ["g2p_registry_encryption.decrypt_registry"],
kwargs: {},
});
return result === "True";
}

// Check conditions for enabling the preview button
_checkPreviewConditions() {
const is_encrypted = this.props.record.data.is_encrypted;
const decrypt_registry = this.decryptRegistry;
return !is_encrypted || (is_encrypted && decrypt_registry);
}

// Handle preview button click
clickPreview(ev) {
const currentRow = ev.target.closest(".o_data_row");
if (currentRow) {
const slugElement = currentRow.querySelector('.o_data_cell[name="slug"]');
if (slugElement) {
const slugValue = slugElement.textContent.trim();

let recordID = 0;
if (slugValue.includes("-")) {
const parts = slugValue.split("-");
const lastPart = parts[parts.length - 1].split(".")[0];
if (!isNaN(lastPart)) {
recordID = parseInt(lastPart, 10);
}
}
if (recordID) {
this._onPreviewButtonClick(recordID);
}
}
}
}

// Fetch the record and show the preview
async _onPreviewButtonClick(recordID) {
const result = await this.rpc("/web/dataset/call_kw/storage.file/get_record", {
model: "storage.file",
method: "get_record",
args: [[recordID]],
kwargs: {},
});
const mimetype = result.mimetype;
if (typeof mimetype === "string" && mimetype) {
const file = {
id: recordID,
displayName: result.name,
downloadUrl: result.url,
isViewable: mimetype.includes("image") || mimetype.includes("pdf"),
defaultSource: result.url,
isImage: mimetype.includes("image"),
isPdf: mimetype.includes("pdf"),
};
if (file.isViewable) {
this.fileViewer.open(file);
} else {
window.open(result.url, "_blank");
}
} else {
window.open(result.url, "_blank");
}
}
}

// Register the new widget to replace the existing one
registry.category("view_widgets").add("action_preview", {component: Widgetpreview});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_registrant_documents_form_individual" model="ir.ui.view">
<field name="name">view_registrant_documents_form_individual</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="g2p_registry_individual.view_individuals_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='supporting_documents_ids']/tree" position="inside">
<field name="is_encrypted" string="Encrypted" />
</xpath>
</field>
</record>

<record id="view_registrant_documents_form_group" model="ir.ui.view">
<field name="name">view_registrant_documents_form_group</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="g2p_registry_group.view_groups_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='supporting_documents_ids']/tree" position="inside">
<field name="is_encrypted" string="Encrypted" />
</xpath>
</field>
</record>
</odoo>
Loading