From 8d860396bdf2f2aec2febf5ef671a555e085b923 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Fri, 17 May 2024 15:27:34 +0530 Subject: [PATCH] dev: auth callback for runing user post authentication workflows (#4498) --- .../plane/authentication/adapter/base.py | 13 ++++++++++-- .../authentication/adapter/credential.py | 4 ++-- .../plane/authentication/adapter/oauth.py | 3 ++- .../provider/credentials/email.py | 1 + .../provider/credentials/magic_code.py | 1 + .../authentication/provider/oauth/github.py | 3 ++- .../authentication/provider/oauth/google.py | 3 ++- .../utils/user_auth_workflow.py | 9 +++++++++ .../plane/authentication/views/app/email.py | 20 +++++++++++-------- .../plane/authentication/views/app/github.py | 7 +++---- .../plane/authentication/views/app/google.py | 7 +++---- .../plane/authentication/views/app/magic.py | 18 +++++++++-------- 12 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 apiserver/plane/authentication/utils/user_auth_workflow.py diff --git a/apiserver/plane/authentication/adapter/base.py b/apiserver/plane/authentication/adapter/base.py index c8e7bd316..7b899e63c 100644 --- a/apiserver/plane/authentication/adapter/base.py +++ b/apiserver/plane/authentication/adapter/base.py @@ -21,9 +21,10 @@ from .error import AuthenticationException, AUTHENTICATION_ERROR_CODES class Adapter: """Common interface for all auth providers""" - def __init__(self, request, provider): + def __init__(self, request, provider, callback=None): self.request = request self.provider = provider + self.callback = callback self.token_data = None self.user_data = None @@ -48,7 +49,8 @@ class Adapter: def complete_login_or_signup(self): email = self.user_data.get("email") user = User.objects.filter(email=email).first() - + # Check if sign up case or login + is_signup = bool(user) if not user: # New user (ENABLE_SIGNUP,) = get_configuration_value( @@ -115,6 +117,13 @@ class Adapter: user.token_updated_at = timezone.now() user.save() + if self.callback: + self.callback( + user, + is_signup, + self.request, + ) + if self.token_data: self.create_update_account(user=user) diff --git a/apiserver/plane/authentication/adapter/credential.py b/apiserver/plane/authentication/adapter/credential.py index b1fd75d02..943e6b068 100644 --- a/apiserver/plane/authentication/adapter/credential.py +++ b/apiserver/plane/authentication/adapter/credential.py @@ -4,8 +4,8 @@ from plane.authentication.adapter.base import Adapter class CredentialAdapter(Adapter): """Common interface for all credential providers""" - def __init__(self, request, provider): - super().__init__(request, provider) + def __init__(self, request, provider, callback=None): + super().__init__(request, provider, callback) self.request = request self.provider = provider diff --git a/apiserver/plane/authentication/adapter/oauth.py b/apiserver/plane/authentication/adapter/oauth.py index 91cab7c5f..634b42077 100644 --- a/apiserver/plane/authentication/adapter/oauth.py +++ b/apiserver/plane/authentication/adapter/oauth.py @@ -23,8 +23,9 @@ class OauthAdapter(Adapter): userinfo_url, client_secret=None, code=None, + callback=None, ): - super().__init__(request, provider) + super().__init__(request, provider, callback=callback) self.client_id = client_id self.scope = scope self.redirect_uri = redirect_uri diff --git a/apiserver/plane/authentication/provider/credentials/email.py b/apiserver/plane/authentication/provider/credentials/email.py index 6306399aa..eae3ea932 100644 --- a/apiserver/plane/authentication/provider/credentials/email.py +++ b/apiserver/plane/authentication/provider/credentials/email.py @@ -21,6 +21,7 @@ class EmailProvider(CredentialAdapter): key=None, code=None, is_signup=False, + callback=None, ): super().__init__(request, self.provider) self.key = key diff --git a/apiserver/plane/authentication/provider/credentials/magic_code.py b/apiserver/plane/authentication/provider/credentials/magic_code.py index f21a65a89..68322c5d6 100644 --- a/apiserver/plane/authentication/provider/credentials/magic_code.py +++ b/apiserver/plane/authentication/provider/credentials/magic_code.py @@ -24,6 +24,7 @@ class MagicCodeProvider(CredentialAdapter): request, key, code=None, + callback=None, ): ( diff --git a/apiserver/plane/authentication/provider/oauth/github.py b/apiserver/plane/authentication/provider/oauth/github.py index b52fecf97..edccea449 100644 --- a/apiserver/plane/authentication/provider/oauth/github.py +++ b/apiserver/plane/authentication/provider/oauth/github.py @@ -22,7 +22,7 @@ class GitHubOAuthProvider(OauthAdapter): provider = "github" scope = "read:user user:email" - def __init__(self, request, code=None, state=None): + def __init__(self, request, code=None, state=None, callback=None): GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET = get_configuration_value( [ @@ -67,6 +67,7 @@ class GitHubOAuthProvider(OauthAdapter): self.userinfo_url, client_secret, code, + callback=callback, ) def set_token_data(self): diff --git a/apiserver/plane/authentication/provider/oauth/google.py b/apiserver/plane/authentication/provider/oauth/google.py index 5de1ac8e2..591295cb1 100644 --- a/apiserver/plane/authentication/provider/oauth/google.py +++ b/apiserver/plane/authentication/provider/oauth/google.py @@ -20,7 +20,7 @@ class GoogleOAuthProvider(OauthAdapter): scope = "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile" provider = "google" - def __init__(self, request, code=None, state=None): + def __init__(self, request, code=None, state=None, callback=None): (GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET) = get_configuration_value( [ { @@ -66,6 +66,7 @@ class GoogleOAuthProvider(OauthAdapter): self.userinfo_url, client_secret, code, + callback=callback, ) def set_token_data(self): diff --git a/apiserver/plane/authentication/utils/user_auth_workflow.py b/apiserver/plane/authentication/utils/user_auth_workflow.py new file mode 100644 index 000000000..e7cb4942e --- /dev/null +++ b/apiserver/plane/authentication/utils/user_auth_workflow.py @@ -0,0 +1,9 @@ +from .workspace_project_join import process_workspace_project_invitations + + +def post_user_auth_workflow( + user, + is_signup, + request, +): + process_workspace_project_invitations(user=user) diff --git a/apiserver/plane/authentication/views/app/email.py b/apiserver/plane/authentication/views/app/email.py index c29bc80c4..f21e431a4 100644 --- a/apiserver/plane/authentication/views/app/email.py +++ b/apiserver/plane/authentication/views/app/email.py @@ -13,8 +13,8 @@ from plane.authentication.utils.login import user_login from plane.license.models import Instance from plane.authentication.utils.host import base_host from plane.authentication.utils.redirection_path import get_redirection_path -from plane.authentication.utils.workspace_project_join import ( - process_workspace_project_invitations, +from plane.authentication.utils.user_auth_workflow import ( + post_user_auth_workflow, ) from plane.db.models import User from plane.authentication.adapter.error import ( @@ -125,13 +125,15 @@ class SignInAuthEndpoint(View): try: provider = EmailProvider( - request=request, key=email, code=password, is_signup=False + request=request, + key=email, + code=password, + is_signup=False, + callback=post_user_auth_workflow, ) user = provider.authenticate() # Login the user and record his device info user_login(request=request, user=user, is_app=True) - # Process workspace and project invitations - process_workspace_project_invitations(user=user) # Get the redirection path if next_path: path = str(next_path) @@ -252,13 +254,15 @@ class SignUpAuthEndpoint(View): try: provider = EmailProvider( - request=request, key=email, code=password, is_signup=True + request=request, + key=email, + code=password, + is_signup=True, + callback=post_user_auth_workflow, ) user = provider.authenticate() # Login the user and record his device info user_login(request=request, user=user, is_app=True) - # Process workspace and project invitations - process_workspace_project_invitations(user=user) # Get the redirection path if next_path: path = next_path diff --git a/apiserver/plane/authentication/views/app/github.py b/apiserver/plane/authentication/views/app/github.py index 73afa674b..f93beefa3 100644 --- a/apiserver/plane/authentication/views/app/github.py +++ b/apiserver/plane/authentication/views/app/github.py @@ -9,8 +9,8 @@ from django.views import View from plane.authentication.provider.oauth.github import GitHubOAuthProvider from plane.authentication.utils.login import user_login from plane.authentication.utils.redirection_path import get_redirection_path -from plane.authentication.utils.workspace_project_join import ( - process_workspace_project_invitations, +from plane.authentication.utils.user_auth_workflow import ( + post_user_auth_workflow, ) from plane.license.models import Instance from plane.authentication.utils.host import base_host @@ -107,12 +107,11 @@ class GitHubCallbackEndpoint(View): provider = GitHubOAuthProvider( request=request, code=code, + callback=post_user_auth_workflow, ) user = provider.authenticate() # Login the user and record his device info user_login(request=request, user=user, is_app=True) - # Process workspace and project invitations - process_workspace_project_invitations(user=user) # Get the redirection path if next_path: path = next_path diff --git a/apiserver/plane/authentication/views/app/google.py b/apiserver/plane/authentication/views/app/google.py index ea3afed89..05f4511e2 100644 --- a/apiserver/plane/authentication/views/app/google.py +++ b/apiserver/plane/authentication/views/app/google.py @@ -11,8 +11,8 @@ from django.views import View from plane.authentication.provider.oauth.google import GoogleOAuthProvider from plane.authentication.utils.login import user_login from plane.authentication.utils.redirection_path import get_redirection_path -from plane.authentication.utils.workspace_project_join import ( - process_workspace_project_invitations, +from plane.authentication.utils.user_auth_workflow import ( + post_user_auth_workflow, ) from plane.license.models import Instance from plane.authentication.utils.host import base_host @@ -105,12 +105,11 @@ class GoogleCallbackEndpoint(View): provider = GoogleOAuthProvider( request=request, code=code, + callback=post_user_auth_workflow, ) user = provider.authenticate() # Login the user and record his device info user_login(request=request, user=user, is_app=True) - # Process workspace and project invitations - process_workspace_project_invitations(user=user) # Get the redirection path path = get_redirection_path(user=user) # redirect to referer path diff --git a/apiserver/plane/authentication/views/app/magic.py b/apiserver/plane/authentication/views/app/magic.py index 27e0b1bd6..bb3c72534 100644 --- a/apiserver/plane/authentication/views/app/magic.py +++ b/apiserver/plane/authentication/views/app/magic.py @@ -18,8 +18,8 @@ from plane.authentication.provider.credentials.magic_code import ( ) from plane.authentication.utils.login import user_login from plane.authentication.utils.redirection_path import get_redirection_path -from plane.authentication.utils.workspace_project_join import ( - process_workspace_project_invitations, +from plane.authentication.utils.user_auth_workflow import ( + post_user_auth_workflow, ) from plane.bgtasks.magic_link_code_task import magic_link from plane.license.models import Instance @@ -130,14 +130,15 @@ class MagicSignInEndpoint(View): try: provider = MagicCodeProvider( - request=request, key=f"magic_{email}", code=code + request=request, + key=f"magic_{email}", + code=code, + callback=post_user_auth_workflow, ) user = provider.authenticate() profile = Profile.objects.get(user=user) # Login the user and record his device info user_login(request=request, user=user, is_app=True) - # Process workspace and project invitations - process_workspace_project_invitations(user=user) if user.is_password_autoset and profile.is_onboarded: path = "accounts/set-password" else: @@ -204,13 +205,14 @@ class MagicSignUpEndpoint(View): try: provider = MagicCodeProvider( - request=request, key=f"magic_{email}", code=code + request=request, + key=f"magic_{email}", + code=code, + callback=post_user_auth_workflow, ) user = provider.authenticate() # Login the user and record his device info user_login(request=request, user=user, is_app=True) - # Process workspace and project invitations - process_workspace_project_invitations(user=user) # Get the redirection path if next_path: path = str(next_path)