Skip to content

Conversation

@steventux
Copy link
Contributor

@steventux steventux commented Oct 20, 2025

Description

https://screening-discovery.slack.com/archives/C08R0BT5HH6/p1760623960488199

Jira link

https://nhsd-jira.digital.nhs.uk/browse/DTOSS-11319

Review notes

@MatMoore @malcolmbaig after investigating this further the problem was as Mat mentioned in the Slack thread ie. how other decorators using functools.wraps return a wrapped function which can't then be matched using view_func in _basic_auth_exempt_views because the function we add to that set is wrapped.
There are other decorators which might need the same treatment but wanted to get some feedback on this approach to solving it.

[Edit] see discussion, @malcolmbaig 's suggestion seemed a better general approach to identifying the decorated function

@steventux steventux force-pushed the fix-middleware-exemption-check branch 3 times, most recently from 2ca1b4f to ebd0aef Compare October 20, 2025 15:06
@steventux steventux force-pushed the fix-middleware-exemption-check branch from ebd0aef to 2184b36 Compare October 21, 2025 09:28
@steventux steventux marked this pull request as ready for review October 21, 2025 09:29
return True
return is_basic_auth_exempt(view_func.__wrapped__)
except AttributeError:
return False
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense to me and accounts for varying decorator implementations. login_not_required, for example, doesn't use wraps.

Another option might be (continuing your idea in the Slack thread of using __qualname__):

def view_func_identifier(view_func: Callable) -> str:
    return f"{view_func.__module__}.{view_func.__qualname__}"


def basic_auth_exempt(view_func: Callable) -> Callable:
    """Mark a view function as exempt from BasicAuthMiddleware.

    Uses a registry approach that is decorator-order independent.
    """
    _basic_auth_exempt_views.add(view_func_identifier(view_func))
    return view_func


def is_basic_auth_exempt(view_func: Callable) -> bool:
    """Check if a view function is exempt from BasicAuthMiddleware."""
    return view_func_identifier(view_func) in _basic_auth_exempt_views

The needs some minor amendments to the assertions to get the existing tests to pass, and passes for your newly added test without modifications.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm happy to go with this suggestion. The one misgiving I had around the __wrapped__ solution was that it addressed one specific scenario whereas the module + function name detection seems a better general approach.

Copy link
Contributor Author

@steventux steventux Oct 22, 2025

Choose a reason for hiding this comment

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

@malcolmbaig I've amended to use view_func_identifier I've also tested locally with curl and basic auth is disabled for the notifications callback view.

@steventux steventux force-pushed the fix-middleware-exemption-check branch from 2184b36 to ec4ee10 Compare October 22, 2025 08:49
@steventux steventux force-pushed the fix-middleware-exemption-check branch from ec4ee10 to 424d33d Compare October 22, 2025 08:57
Copy link
Contributor

@malcolmbaig malcolmbaig left a comment

Choose a reason for hiding this comment

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

LG 👍🏼 .

@steventux steventux merged commit 870da05 into main Oct 22, 2025
12 checks passed
@steventux steventux deleted the fix-middleware-exemption-check branch October 22, 2025 09:27
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.

2 participants