Browse Source

ref(auth): Create base authindex endpoint class (#62282)

Refactor `AuthIndexEndpoint` to subclass a new base class
`BaseAuthIndexEndpoint`. The base class contains shared:
1. shared helper functions
   - `_reauthenticate_with_sso`
   - `_verify_user_via_inputs`
3. auth classes
4. permission classes
5. GET

The new staff endpoint differs b/c:
1. Does not contain a POST
2. The delete does not logout, it only kills the superuser and staff
session
3. PUT validates normal requests and grants staff instead of superuser
Seiji Chew 1 year ago
parent
commit
9f515c2fe1
1 changed files with 31 additions and 25 deletions
  1. 31 25
      src/sentry/api/endpoints/auth_index.py

+ 31 - 25
src/sentry/api/endpoints/auth_index.py

@@ -38,19 +38,10 @@ DISABLE_SU_FORM_U2F_CHECK_FOR_LOCAL = getattr(
 
 
 @control_silo_endpoint
-class AuthIndexEndpoint(Endpoint):
-    publish_status = {
-        "DELETE": ApiPublishStatus.UNKNOWN,
-        "GET": ApiPublishStatus.UNKNOWN,
-        "PUT": ApiPublishStatus.UNKNOWN,
-        "POST": ApiPublishStatus.UNKNOWN,
-    }
+class BaseAuthIndexEndpoint(Endpoint):
     """
-    Manage session authentication
-
-    Intended to be used by the internal Sentry application to handle
-    authentication methods from JS endpoints by relying on internal sessions
-    and simple HTTP authentication.
+    Base endpoint to manage session authentication. Shared between
+    AuthIndexEndpoint and StaffAuthIndexEndpoint (in getsentry)
     """
 
     owner = ApiOwner.ENTERPRISE
@@ -58,8 +49,15 @@ class AuthIndexEndpoint(Endpoint):
 
     permission_classes = ()
 
+    def get(self, request: Request) -> Response:
+        if not request.user.is_authenticated:
+            return Response(status=status.HTTP_400_BAD_REQUEST)
+
+        user = promote_request_rpc_user(request)
+        return Response(serialize(user, user, DetailedSelfUserSerializer()))
+
     @staticmethod
-    def _reauthenticate_with_sso(request, org_id):
+    def _reauthenticate_with_sso(request: Request, org_id: int) -> None:
         """
         If a user without a password is hitting this, it means they need to re-identify with SSO.
         """
@@ -75,7 +73,7 @@ class AuthIndexEndpoint(Endpoint):
         )
 
     @staticmethod
-    def _verify_user_via_inputs(validator, request):
+    def _verify_user_via_inputs(validator: AuthVerifyValidator, request: Request) -> bool:
         # See if we have a u2f challenge/response
         if "challenge" in validator.validated_data and "response" in validator.validated_data:
             try:
@@ -113,9 +111,26 @@ class AuthIndexEndpoint(Endpoint):
             return authenticated
         return False
 
+
+@control_silo_endpoint
+class AuthIndexEndpoint(BaseAuthIndexEndpoint):
+    publish_status = {
+        "DELETE": ApiPublishStatus.PRIVATE,
+        "GET": ApiPublishStatus.PRIVATE,
+        "PUT": ApiPublishStatus.PRIVATE,
+        "POST": ApiPublishStatus.PRIVATE,
+    }
+    """
+    Manage session authentication
+
+    Intended to be used by the internal Sentry application to handle
+    authentication methods from JS endpoints by relying on internal sessions
+    and simple HTTP authentication.
+    """
+
     def _validate_superuser(
         self, validator: AuthVerifyValidator, request: Request, verify_authenticator: bool
-    ):
+    ) -> bool:
         """
         For a superuser, they need to be validated before we can grant an active superuser session.
         If the user has a password or u2f device, authenticate the password/challenge that was sent is valid.
@@ -145,13 +160,6 @@ class AuthIndexEndpoint(Endpoint):
 
         return authenticated
 
-    def get(self, request: Request) -> Response:
-        if not request.user.is_authenticated:
-            return Response(status=status.HTTP_400_BAD_REQUEST)
-
-        user = promote_request_rpc_user(request)
-        return Response(serialize(user, user, DetailedSelfUserSerializer()))
-
     def post(self, request: Request) -> Response:
         """
         Authenticate a User
@@ -197,7 +205,7 @@ class AuthIndexEndpoint(Endpoint):
 
         return self.get(request)
 
-    def put(self, request: Request):
+    def put(self, request: Request) -> Response:
         """
         Verify a User
         `````````````
@@ -252,12 +260,10 @@ class AuthIndexEndpoint(Endpoint):
             auth.login(request._request, promote_request_rpc_user(request))
             metrics.incr(
                 "sudo_modal.success",
-                sample_rate=1.0,
             )
         except auth.AuthUserPasswordExpired:
             metrics.incr(
                 "sudo_modal.failure",
-                sample_rate=1.0,
             )
             return Response(
                 {