Skip to content

Commit 2d2fbe1

Browse files
committed
[FIX] vault: do not present exhausted inboxes as writable
An inbox that can no longer be written to (access counter at 0 or expired) still showed its writable inbox link, and submitting to it silently did nothing while the form reported 'Successfully stored'. This is misleading for received/delivered secrets which are created with accesses = 0. - Add a computed 'writable' flag (accesses left and not expired) and hide the inbox link in the list and form views when it is not writable. - Make the controller report 'This link is no longer active' when store_in_inbox performs no write instead of a false success message. - Cover the exhausted-inbox submit path in the controller test.
1 parent 4301392 commit 2d2fbe1

6 files changed

Lines changed: 64 additions & 2 deletions

File tree

vault/controllers/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def vault_inbox(self, token):
5555
return request.render("vault.inbox", ctx)
5656

5757
try:
58-
inbox.store_in_inbox(
58+
result = inbox.store_in_inbox(
5959
name,
6060
secret,
6161
secret_file,
@@ -72,6 +72,10 @@ def vault_inbox(self, token):
7272
)
7373
return request.render("vault.inbox", ctx)
7474

75+
if not result:
76+
ctx["error"] = _("This link is no longer active")
77+
return request.render("vault.inbox", ctx)
78+
7579
ctx["message"] = _("Successfully stored")
7680
return request.render("vault.inbox", ctx)
7781

vault/models/vault_inbox.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class VaultInbox(models.Model):
4343
help="If expired the inbox can't be written using the link",
4444
)
4545
log_ids = fields.One2many("vault.inbox.log", "inbox_id", "Log", readonly=True)
46+
writable = fields.Boolean(compute="_compute_writable")
4647

4748
_sql_constraints = [
4849
(
@@ -52,6 +53,14 @@ class VaultInbox(models.Model):
5253
),
5354
]
5455

56+
@api.depends("accesses", "expiration")
57+
def _compute_writable(self):
58+
now = datetime.now()
59+
for rec in self:
60+
rec.writable = rec.accesses > 0 and (
61+
not rec.expiration or now < rec.expiration
62+
)
63+
5564
@api.depends("token")
5665
def _compute_inbox_link(self):
5766
base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url")

vault/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from . import (
55
test_controller,
6+
test_inbox,
67
test_log,
78
test_rights,
89
test_user,

vault/tests/test_controller.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ def load(response):
9898
self.assertEqual(self.inbox.secret, "secret")
9999
self.assertEqual(self.inbox.secret_file, b"file")
100100

101+
exhausted = self.env["vault.inbox"].create(
102+
{
103+
"user_id": self.user.id,
104+
"name": "Exhausted",
105+
"key": "4",
106+
"iv": "1",
107+
"secret": "kept secret",
108+
"accesses": 0,
109+
}
110+
)
111+
response = load(self.controller.vault_inbox(exhausted.token))
112+
self.assertEqual(response["error"], "Invalid token")
113+
self.assertEqual(exhausted.secret, "kept secret")
114+
101115
# Test a duplicate inbox
102116
self.inbox.copy().token = self.inbox.token
103117
response = load(self.controller.vault_inbox(self.inbox.token))

vault/tests/test_inbox.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,32 @@ def test_inbox(self):
7272
self.assertEqual(inbox, model.find_inbox(inbox.token))
7373
self.assertEqual(model, model.find_inbox(uuid4()))
7474

75+
def test_writable(self):
76+
model = self.env["vault.inbox"]
77+
user = self.env.user
78+
inbox = model.store_in_inbox(
79+
name=f"Inbox {user.name}",
80+
secret="secret",
81+
iv="iv",
82+
user=user,
83+
key="key",
84+
secret_file="",
85+
filename="",
86+
)
87+
88+
inbox.accesses = 5
89+
self.assertTrue(inbox.writable)
90+
91+
inbox.accesses = 0
92+
self.assertFalse(inbox.writable)
93+
94+
inbox.accesses = 5
95+
inbox.expiration = datetime(1970, 1, 1)
96+
self.assertFalse(inbox.writable)
97+
98+
inbox.expiration = False
99+
self.assertTrue(inbox.writable)
100+
75101
def test_send_wizard(self):
76102
user = self.env.user
77103
wiz = self.env["vault.send.wizard"].create(

vault/views/vault_inbox_views.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
<record id="view_vault_inbox_tree" model="ir.ui.view">
44
<field name="model">vault.inbox</field>
55
<field name="arch" type="xml">
6-
<list create="false">
6+
<list create="false" decoration-muted="not writable">
7+
<field name="writable" column_invisible="1" />
78
<field name="name" />
89
<field name="inbox_link" widget="url" />
910
</list>
@@ -15,10 +16,17 @@
1516
<field name="arch" type="xml">
1617
<form create="false">
1718
<sheet>
19+
<widget
20+
name="web_ribbon"
21+
title="Readonly"
22+
bg_color="text-bg-danger"
23+
invisible="not writable"
24+
/>
1825
<field name="user_id" invisible="1" />
1926
<field name="iv" invisible="1" />
2027
<field name="key" invisible="1" />
2128
<field name="filename" invisible="1" />
29+
<field name="writable" invisible="1" />
2230
<group>
2331
<field name="inbox_link" widget="url" />
2432
<field name="name" />

0 commit comments

Comments
 (0)