Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/custom_auth/oauth/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
UserModel = get_user_model()


class OAuthTokenSerializer(serializers.Serializer): # type: ignore[type-arg]
key = serializers.CharField(read_only=True)
is_new_user = serializers.BooleanField(read_only=True)


class OAuthLoginSerializer(InviteLinkValidationMixin, serializers.Serializer): # type: ignore[type-arg]
access_token = serializers.CharField(
required=True,
Expand All @@ -42,6 +47,7 @@ class OAuthLoginSerializer(InviteLinkValidationMixin, serializers.Serializer):
utm_data = UTMDataSerializer(required=False, allow_null=True)
auth_type: AuthType | None = None
user_model_id_attribute: str = "id"
is_new_user: bool = False

class Meta:
abstract = True
Expand Down Expand Up @@ -98,6 +104,7 @@ def _get_user(self, user_data: dict): # type: ignore[type-arg,no-untyped-def]
user = FFAdminUser.objects.create(
**user_data, email=email.lower(), sign_up_type=sign_up_type
)
self.is_new_user = True

# On first OAuth signup, we register the hubspot cookies and utms before creating the hubspot contact
if request := self.context.get("request"):
Expand Down
18 changes: 13 additions & 5 deletions api/custom_auth/oauth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
from custom_auth.oauth.serializers import (
GithubLoginSerializer,
GoogleLoginSerializer,
OAuthTokenSerializer,
)
from custom_auth.serializers import CustomTokenSerializer

logger = logging.getLogger(__name__)

Expand All @@ -26,7 +26,7 @@

@extend_schema(
request=GoogleLoginSerializer,
responses={200: CustomTokenSerializer, 502: ErrorSerializer},
responses={200: OAuthTokenSerializer, 502: ErrorSerializer},
)
@api_view(["POST"])
@permission_classes([AllowAny])
Expand All @@ -39,7 +39,11 @@ def login_with_google(request): # type: ignore[no-untyped-def]
token = serializer.save()
if settings.COOKIE_AUTH_ENABLED:
return authorise_response(token.user, Response(status=HTTP_204_NO_CONTENT))
return Response(data=CustomTokenSerializer(instance=token).data)
return Response(
data=OAuthTokenSerializer(
{"key": token.key, "is_new_user": serializer.is_new_user}
).data
)
except GoogleError as e:
logger.warning("%s: %s" % (GOOGLE_AUTH_ERROR_MESSAGE, str(e)))
return Response(
Expand All @@ -50,7 +54,7 @@ def login_with_google(request): # type: ignore[no-untyped-def]

@extend_schema(
request=GithubLoginSerializer,
responses={200: CustomTokenSerializer, 502: ErrorSerializer},
responses={200: OAuthTokenSerializer, 502: ErrorSerializer},
)
@api_view(["POST"])
@permission_classes([AllowAny])
Expand All @@ -63,7 +67,11 @@ def login_with_github(request): # type: ignore[no-untyped-def]
token = serializer.save()
if settings.COOKIE_AUTH_ENABLED:
return authorise_response(token.user, Response(status=HTTP_204_NO_CONTENT))
return Response(data=CustomTokenSerializer(instance=token).data)
return Response(
data=OAuthTokenSerializer(
{"key": token.key, "is_new_user": serializer.is_new_user}
).data
)
except GithubError as e:
logger.warning("%s: %s" % (GITHUB_AUTH_ERROR_MESSAGE, str(e)))
return Response(
Expand Down
4 changes: 4 additions & 0 deletions api/tests/unit/custom_auth/oauth/test_unit_oauth_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def test_google_oauth_login__invite_exists_and_registration_disabled__returns_20

# Then
assert response.status_code == status.HTTP_200_OK
assert response.json()["is_new_user"] is True


@mock.patch("custom_auth.oauth.serializers.GithubUser")
Expand Down Expand Up @@ -107,6 +108,7 @@ def test_github_oauth_login__invite_exists_and_registration_disabled__returns_20

# Then
assert response.status_code == status.HTTP_200_OK
assert response.json()["is_new_user"] is True


@mock.patch("custom_auth.oauth.serializers.get_user_info")
Expand All @@ -133,6 +135,7 @@ def test_google_oauth_login__existing_user_and_registration_disabled__returns_20
# Then
assert response.status_code == status.HTTP_200_OK
assert "key" in response.json()
assert response.json()["is_new_user"] is False


@mock.patch("custom_auth.oauth.serializers.GithubUser")
Expand Down Expand Up @@ -161,6 +164,7 @@ def test_github_oauth_login__existing_user_and_registration_disabled__returns_20
# Then
assert response.status_code == status.HTTP_200_OK
assert "key" in response.json()
assert response.json()["is_new_user"] is False


def test_google_oauth_login__case_insensitive_email__updates_existing_user(
Expand Down
21 changes: 11 additions & 10 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/CustomToken'
$ref: '#/components/schemas/OAuthToken'
'502':
description: ''
content:
Expand Down Expand Up @@ -531,7 +531,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/CustomToken'
$ref: '#/components/schemas/OAuthToken'
'502':
description: ''
content:
Expand Down Expand Up @@ -19140,14 +19140,6 @@ components:
$ref: '#/components/schemas/MultivariateFeatureStateValue'
required:
- feature_state_value
CustomToken:
type: object
properties:
key:
type: string
maxLength: 40
required:
- key
CustomUserCreate:
type: object
properties:
Expand Down Expand Up @@ -22049,6 +22041,15 @@ components:
- app_id
NullEnum:
type: 'null'
OAuthToken:
type: object
properties:
key:
type: string
readOnly: true
is_new_user:
type: boolean
readOnly: true
OrganisationAPIUsageNotification:
type: object
properties:
Expand Down
Loading