feat(shopfloor): fp_tablet_pin custom auth manager
Validates PIN hash + shop-branch role membership when the credential type is fp_tablet_pin. Goes through Odoo's standard _check_credentials chain so future 2FA / IP-gate modules layer cleanly on top. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -139,3 +139,50 @@ class ResUsers(models.Model):
|
||||
'name': 'Set Tablet PIN',
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def _check_credentials(self, credential, env):
|
||||
"""Custom auth manager: accept `type='fp_tablet_pin'` credential.
|
||||
|
||||
Validates the PIN hash, that the user is active, and that they hold
|
||||
at least one shop-branch plating role. On success, returns the auth
|
||||
info dict Odoo's session expects. On failure, raises AccessDenied
|
||||
so the standard auth chain returns a 401.
|
||||
|
||||
See docs/superpowers/specs/2026-05-24-tablet-pin-session-redesign-design.md
|
||||
Section 2 — Auth path.
|
||||
"""
|
||||
from odoo.exceptions import AccessDenied
|
||||
if isinstance(credential, dict) and credential.get('type') == 'fp_tablet_pin':
|
||||
login = credential.get('login')
|
||||
pin = credential.get('pin')
|
||||
if not login or not pin:
|
||||
raise AccessDenied()
|
||||
user_sudo = self.sudo().search([('login', '=', login)], limit=1)
|
||||
if not user_sudo or not user_sudo.active:
|
||||
raise AccessDenied()
|
||||
# Must hold a shop-branch role (otherwise they can't operate the tablet)
|
||||
shop_branch_xmlids = (
|
||||
'fusion_plating.group_fp_technician',
|
||||
'fusion_plating.group_fp_shop_manager_v2',
|
||||
'fusion_plating.group_fp_manager',
|
||||
'fusion_plating.group_fp_quality_manager',
|
||||
'fusion_plating.group_fp_owner',
|
||||
)
|
||||
shop_branch_ids = {
|
||||
g.id for g in (
|
||||
self.env.ref(x, raise_if_not_found=False)
|
||||
for x in shop_branch_xmlids
|
||||
) if g
|
||||
}
|
||||
user_group_ids = set(user_sudo.group_ids.ids)
|
||||
if not (shop_branch_ids & user_group_ids):
|
||||
raise AccessDenied()
|
||||
# Verify the PIN hash. verify_tablet_pin already exists.
|
||||
if not user_sudo.verify_tablet_pin(pin):
|
||||
raise AccessDenied()
|
||||
return {
|
||||
'uid': user_sudo.id,
|
||||
'auth_method': 'fp_tablet_pin',
|
||||
'mfa': 'default',
|
||||
}
|
||||
return super()._check_credentials(credential, env)
|
||||
|
||||
Reference in New Issue
Block a user