+
Skip to content

Conversation

BT-pgaiser
Copy link

Fixes the comparison with old values when setting fields to empty values.

The old values for the comparison when using fast log mode were initialized with False. This causes the problem that when a field is set to an emty value by the user, auditlog does not create a log line because internal checks compare False to False and do not consider logging the change. Full log mode is not affected by this as there everything is logged by default. However, even in fast log mode, some companies have regulatory requirements which force them to log user actions that set empty values to fields, so that should be logged properly.

@BT-pgaiser BT-pgaiser force-pushed the 16.0.fix-audit-empty-field-write branch from 613f0e8 to 0f3383d Compare September 24, 2025 07:30
Copy link

@BT-mlopez BT-mlopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, unit test look quite complete.

Copy link

@BT-ojossen BT-ojossen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but you should add yourself to the contributors

@BT-pgaiser
Copy link
Author

@amh-mw @StefanRijnhart
Could someone please take a look at this and potentially merge? I don't know who's maintaining the auditlog module.

Copy link
Member

@StefanRijnhart StefanRijnhart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I see the issue. But doing a read is undermining the 'fast' aspect of the 'fast' type rule. Would it work to force any falsy value in the written vals to show up in the log lines (conditionally overriding the result of DictDiffer)?

@BT-pgaiser
Copy link
Author

Thanks for the prompt response. Indeed, if we change the initial old value from False to None here, then the DictDiffer object will track the change and a log line is created. However, that log line will still show a change from "empty" to "empty" value, which is incorrect. As I have mentioned, some companies have regulatory requirements that oblige them to log these changes too.
Regarding the performance, yes, doing a round-trip to the DB has an additional cost but in many cases the field values are first read before they are written, which results in a high likelihood that on the side of the DB those values are still in cache so it won't hit the disk. Is there another way to obtain the old field values?

@StefanRijnhart
Copy link
Member

Isn't it the case that one never gets the old values with 'fast' logging? So having both an empty value for old and new is what is to be expected.

@BT-pgaiser BT-pgaiser force-pushed the 16.0.fix-audit-empty-field-write branch from 43e2eaf to b8cae5a Compare September 25, 2025 09:10
@BT-pgaiser
Copy link
Author

That seems to be the case, yeah. So this is an intentional performance optimisation? How about we add an option to the auditlog rules (applicable only for the fast mode) to let the user decide whether old values should be logged?

@StefanRijnhart
Copy link
Member

@BT-pgaiser Isn't that what 'full' logging is for?

@BT-pgaiser
Copy link
Author

If that's the only difference between "fast" and "full" log mode, then yes, simply activating the "full" mode solves the issue. I was thinking about having something in between those two modes, but maybe that does not make a lot of sense.
Can you confirm? If yes, I'd keep the fix for the missing log lines when logging empty values but remove the read of old values.

@StefanRijnhart
Copy link
Member

StefanRijnhart commented Sep 25, 2025

@BT-pgaiser Yes please! Keep logging the empty values when specified explicitely in the write vals (in the case of write 'fast'), but don't read old values to compare.

Copy link
Member

@StefanRijnhart StefanRijnhart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you squash commits afterwards?

Fix the comparison with old values when setting fields to empty values.
The old values for the comparison when using fast log mode were initialized
with False. This causes the problem that when a field is set to an emty value
by the user, auditlog does not create a log line because internal checks
compare False to False and do not consider logging the change. Full log mode
is not affected by this as there everything is logged by default. However,
even in fast log mode, some companies have regulatory requirements which
force them to log user actions that set empty values to fields.
@BT-pgaiser BT-pgaiser force-pushed the 16.0.fix-audit-empty-field-write branch from c7e77b4 to 99fa146 Compare September 25, 2025 15:23
@BT-pgaiser
Copy link
Author

Commits squashed and test case refactored.

Copy link
Member

@StefanRijnhart StefanRijnhart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looking good now!

@OCA-git-bot
Copy link
Contributor

This PR has the approved label and has been created more than 5 days ago. It should therefore be ready to merge by a maintainer (or a PSC member if the concerned addon has no declared maintainer). 🤖

@BT-pgaiser
Copy link
Author

@StefanRijnhart Can we please merge this? Thanks.

@StefanRijnhart
Copy link
Member

@BT-pgaiser I would like to see another review from a tools maintainer or previous contributor to this module. The other reviews on this PR so far are clearly 'team service' because I don't see any other reviews in the OCA from them except for one or two other 'BT' PRs.

@BT-pgaiser
Copy link
Author

@StefanRijnhart Fair enough.
@amh-mw @mymage @tarteo @hbrunn Would one of you be so kind :)

cls.auditlog_rule.subscribe()

def test_when_removing_field_value_a_log_line_is_created(self):
self.test_record.write({"phone": False})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do the same test with writing None here? Both are valid input, and I suspect you're just replacing when the misbehavior happens.

chances are you need some sentinel object like

class FalsyValue():
    def __bool__(self):
        return False

to initialize the dict above with

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a test for writing None values. However, AFAIK, Odoo always represents missing/empty values as False and this is consistent with how the web client behaves. Anyhow, I've never seen None being used for that in Odoo. Surely, if I write a separate program that directly communicates with the Odoo backend, then I can send it None values, but I'd say that's unspecified behaviour so it does not need to be supported. Anyways, the introduced sentinel object will handle both cases now.

Introduce sentinel object as a placeholder for absent values
when comparing diff.
Add test for setting None values.
# of the data in the database
vals2 = dict(vals)
old_vals2 = dict.fromkeys(list(vals2.keys()), None)
old_vals2 = dict.fromkeys(list(vals2.keys()), _Sentinel())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait, for better performance, please create an instance of this above and recycle this object, no need to keep creating it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载