Judging a Python decorator by what its definition does: the Flask and
Django auth taggers both read a project decorator's body (and the
functions it calls) to decide whether it turns an unauthenticated caller
away, and fall back to a name list only for a library decorator the scan
does not hold. The including tagger supplies decorator_description.
Constants
ANY_VIEW_CALL = /(?<![\w.])\w+\s*\(\s*(?:\w+\s*,\s*)?\*\w+\s*,\s*\*\*\w+\s*\)/
The view called from a function wrapper or a method one (f(self, *args, **kwargs)).
CALLEE = /@([A-Za-z_]\w*)|(?<![\w.])([A-Za-z_]\w*)\s*\(/
A function a body calls, or a decorator it applies to a nested def.
CALLER_IDENTITY = /\bcurrent_user\b|\bis_authenticated\b|\bg\.user\b/
CONDITION_WORDS = ["not", "is", "
None", "
True", "
False", "in", "and", "or"] of ::
StringDECORATOR_NAME = /^@([A-Za-z_][\w.]*)/
DOCSTRING = /"""[\s\S]*?"""|'''[\s\S]*?'''/
FORBIDDEN = /\braise\s+(?:\w+\.)*\w*(?:Forbidden|PermissionDenied|AccessDenied)\w*\b|\babort\s*\(\s*(?:403\b|(?:\w+\.)*FORBIDDEN\b)|\breturn\b.*,\s*403\b|\.response_403\s*\(/
LOGIN_REDIRECT = /\bredirect\s*\(.*\b(?:log_?in|sign_?in)\b/i
Sending the caller to the login page is how a browser view refuses
an anonymous one.
NEGATED_TEST = /\A\s*not\b|\bis\s+None\b|==\s*None\b|\bis\s+False\b|==\s*False\b|\bnot\s+in\b|!=/
A condition that holds when its subject is absent or does not match.
REFUSAL_LINE = /\A(?:return|raise)\b|\babort\s*\(/
REJECTION = /\braise\s+[A-Za-z_]|\babort\s*\(|\breturn\b.*,\s*4\d\d\b/
REQUEST_CREDENTIAL = /\brequest\.(?:authorization\b|(?:headers|cookies|args)(?:\.get\s*\(|\[)\s*["'][\w-]*(?:key|token|auth|secret|signature|password|session)[\w-]*["'])/i
REQUEST_READ = /(?<![\w.])request\./
SESSION_READ = /(?<![\w.])session\s*(?:\.get\s*\(|\[)/
Flask keeps the logged-in user in session; a helper such as
authed() reads it there.
TOP_LEVEL_DEF = /^(?:async\s+)?def\s+(\w+)/
UNAUTHENTICATED = /\braise\s+(?:\w+\.)*\w*(?:
Unauthori[sz]ed|
Unauthenticated|
NotAuthenticated|
AuthenticationFailed)(?:
Error|
Exception)?\b|\babort\s*\(\s*(?:401\b|(?:\w+\.)*
UNAUTHORIZED\b)|\.unauthorized\s*\(|\.response_401\s*\(|\bverify_jwt_in_request\s*\((?=\s*(?:\)|[
A-
Za-z_]\w*\s*=))(?![^)]*\boptional\s*=\s*(?!
False\b))|\breturn\b.*,\s*401\b|\bstatus(?:_code)?\s*=\s*401\b|\b
HTTP_401_UNAUTHORIZED\b/
What makes a decorator definition an auth guard: it answers 401 in any
spelling, or it reads a credential off the request and turns the request
away (Dify's inner-API key check answers 404), or it reads the logged-in
caller and denies with 403. A 403 alone is not enough: Dify's
email_password_login_enabled aborts 403 on a feature flag, which says
nothing about the caller.
VIEW_CALL = /(?<![\w.])\w+\s*\(\s*\*\w+\s*,\s*\*\*\w+\s*\)/
A wrapper calling the view it decorates.