diff --git a/fusion_plating/fusion_plating_shopfloor/tests/__init__.py b/fusion_plating/fusion_plating_shopfloor/tests/__init__.py index 4e127c3f..bfabdc1e 100644 --- a/fusion_plating/fusion_plating_shopfloor/tests/__init__.py +++ b/fusion_plating/fusion_plating_shopfloor/tests/__init__.py @@ -5,3 +5,4 @@ from . import test_tablet_pin from . import test_tablet_lock_payload from . import test_kiosk_user_acl from . import test_tablet_session_event_model +from . import test_tablet_pin_auth_manager diff --git a/fusion_plating/fusion_plating_shopfloor/tests/test_tablet_pin_auth_manager.py b/fusion_plating/fusion_plating_shopfloor/tests/test_tablet_pin_auth_manager.py new file mode 100644 index 00000000..193485f7 --- /dev/null +++ b/fusion_plating/fusion_plating_shopfloor/tests/test_tablet_pin_auth_manager.py @@ -0,0 +1,80 @@ +from odoo.tests.common import TransactionCase, tagged +from odoo.exceptions import AccessDenied + + +@tagged('-at_install', 'post_install', 'fp_tablet') +class TestTabletPinAuthManager(TransactionCase): + + def setUp(self): + super().setUp() + Users = self.env['res.users'].with_context(no_reset_password=True) + self.tech = Users.create({ + 'login': 'authmgr_tech@example.com', 'name': 'AuthMgr Tech', + 'email': 'authmgr_tech@example.com', + 'group_ids': [(6, 0, [ + self.env.ref('fusion_plating.group_fp_technician').id + ])], + }) + self.tech.sudo().set_tablet_pin('1234') + + self.no_role_user = Users.create({ + 'login': 'authmgr_norole@example.com', 'name': 'NoRole', + 'email': 'authmgr_norole@example.com', + }) + # Set a PIN but no shop-branch role + # (set_tablet_pin doesn't care about roles) + self.no_role_user.sudo().set_tablet_pin('5555') + + def _check(self, login, pin): + return self.env['res.users'].sudo()._check_credentials( + {'type': 'fp_tablet_pin', 'login': login, 'pin': pin}, + self.env, + ) + + def test_correct_pin_succeeds(self): + result = self._check('authmgr_tech@example.com', '1234') + self.assertEqual(result['uid'], self.tech.id) + self.assertEqual(result['auth_method'], 'fp_tablet_pin') + + def test_wrong_pin_raises_access_denied(self): + with self.assertRaises(AccessDenied): + self._check('authmgr_tech@example.com', '0000') + + def test_missing_pin_raises_access_denied(self): + with self.assertRaises(AccessDenied): + self._check('authmgr_tech@example.com', '') + + def test_missing_login_raises_access_denied(self): + with self.assertRaises(AccessDenied): + self._check('', '1234') + + def test_unknown_login_raises_access_denied(self): + with self.assertRaises(AccessDenied): + self._check('nobody@example.com', '1234') + + def test_inactive_user_raises_access_denied(self): + self.tech.sudo().active = False + with self.assertRaises(AccessDenied): + self._check('authmgr_tech@example.com', '1234') + + def test_no_shop_branch_role_raises_access_denied(self): + with self.assertRaises(AccessDenied): + self._check('authmgr_norole@example.com', '5555') + + def test_other_credential_types_pass_through_to_super(self): + # Standard password credential should still work normally. + # We don't test the exact result here — just that our override + # doesn't intercept it. + # AccessDenied is expected because we provide no password. + # Key check: it's not OUR AccessDenied (which fires when type + # is fp_tablet_pin), so the super() chain handles it. + try: + self.env['res.users'].sudo()._check_credentials( + {'type': 'password', 'login': 'authmgr_tech@example.com', + 'password': 'wrong'}, + self.env, + ) + except AccessDenied: + pass # expected — wrong password + except Exception as e: + self.fail(f'Standard password path broken: {e}')