feat(shopfloor): _tablet_session_audit helper for audit-log writes

Single source for sha256(session sid), ua trim, ip/acting_uid capture
from request. Used by unlock_session, lock_session, and force-lock cron.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-24 12:53:03 -04:00
parent 765b095035
commit 96e33834bd

View File

@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"""Helper for writing fp.tablet.session.event rows from the new
unlock_session / lock_session endpoints and the force-lock cron.
Single source of truth for hashing the session sid, trimming the
user-agent, and capturing forensic ip / acting_uid.
"""
import hashlib
from odoo import fields
from odoo.http import request
def _sha256_session_sid(sid):
"""Return sha256 hex digest of the session sid. Stored in the audit
log so DB leaks can't be replayed."""
if not sid:
return ''
return hashlib.sha256(sid.encode('utf-8')).hexdigest()
def _trim_ua(ua):
"""Trim user-agent to 256 chars (Odoo's standard Char width)."""
if not ua:
return ''
return ua[:256]
def write_event(env, *, event_type, user_id=None, attempted_user_id=None,
session_id_hash=None, session_started_at=None,
session_ended_at=None, duration_seconds=None,
failure_reason=None, notes=None):
"""Append an fp.tablet.session.event row. All writes sudo'd.
The acting_uid + ip + ua are pulled from the current request
automatically so callers never forget them.
"""
vals = {
'event_type': event_type,
'user_id': user_id,
'attempted_user_id': attempted_user_id,
'session_id_hash': session_id_hash,
'session_started_at': session_started_at,
'session_ended_at': session_ended_at,
'duration_seconds': duration_seconds,
'failure_reason': failure_reason,
'notes': notes,
'acting_uid': env.uid,
}
if request:
vals['ip_address'] = request.httprequest.remote_addr or ''
vals['user_agent'] = _trim_ua(
request.httprequest.headers.get('User-Agent', '')
)
return env['fp.tablet.session.event'].sudo().create(vals)