mirror of
https://github.com/gosticks/plane.git
synced 2025-10-16 12:45:33 +00:00
[WEB-4900]: validated authentication redirection paths (#7798)
* refactor: replace validate_next_path with get_safe_redirect_url for safer URL redirection across authentication views * refactor: use get_safe_redirect_url for improved URL redirection in SignInAuthSpaceEndpoint and SignUpAuthSpaceEndpoint * fix: redirect paths --------- Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
parent
116c8118ab
commit
345dfce25d
@ -1,6 +1,3 @@
|
|||||||
# Python imports
|
|
||||||
from urllib.parse import urlencode, urljoin
|
|
||||||
|
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import validate_email
|
||||||
@ -19,7 +16,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class SignInAuthEndpoint(View):
|
class SignInAuthEndpoint(View):
|
||||||
@ -34,11 +31,11 @@ class SignInAuthEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
|
||||||
# Base URL join
|
# Base URL join
|
||||||
url = urljoin(
|
url = get_safe_redirect_url(
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -58,10 +55,10 @@ class SignInAuthEndpoint(View):
|
|||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
# Next path
|
# Next path
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -76,10 +73,10 @@ class SignInAuthEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -92,10 +89,10 @@ class SignInAuthEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -112,19 +109,23 @@ class SignInAuthEndpoint(View):
|
|||||||
user_login(request=request, user=user, is_app=True)
|
user_login(request=request, user=user, is_app=True)
|
||||||
# Get the redirection path
|
# Get the redirection path
|
||||||
if next_path:
|
if next_path:
|
||||||
path = str(validate_next_path(next_path))
|
path = next_path
|
||||||
else:
|
else:
|
||||||
path = get_redirection_path(user=user)
|
path = get_redirection_path(user=user)
|
||||||
|
|
||||||
# redirect to referer path
|
# Get the safe redirect URL
|
||||||
url = urljoin(base_host(request=request, is_app=True), path)
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={},
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -141,10 +142,10 @@ class SignUpAuthEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -161,10 +162,10 @@ class SignUpAuthEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
# Validate the email
|
# Validate the email
|
||||||
@ -179,10 +180,10 @@ class SignUpAuthEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -197,10 +198,10 @@ class SignUpAuthEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -217,17 +218,21 @@ class SignUpAuthEndpoint(View):
|
|||||||
user_login(request=request, user=user, is_app=True)
|
user_login(request=request, user=user, is_app=True)
|
||||||
# Get the redirection path
|
# Get the redirection path
|
||||||
if next_path:
|
if next_path:
|
||||||
path = str(validate_next_path(next_path))
|
path = next_path
|
||||||
else:
|
else:
|
||||||
path = get_redirection_path(user=user)
|
path = get_redirection_path(user=user)
|
||||||
# redirect to referer path
|
|
||||||
url = urljoin(base_host(request=request, is_app=True), path)
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={},
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode, urljoin
|
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -16,8 +16,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class GitHubOauthInitiateEndpoint(View):
|
class GitHubOauthInitiateEndpoint(View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
@ -35,10 +34,10 @@ class GitHubOauthInitiateEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
try:
|
try:
|
||||||
@ -49,10 +48,10 @@ class GitHubOauthInitiateEndpoint(View):
|
|||||||
return HttpResponseRedirect(auth_url)
|
return HttpResponseRedirect(auth_url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -70,9 +69,11 @@ class GitHubCallbackEndpoint(View):
|
|||||||
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
@ -81,9 +82,11 @@ class GitHubCallbackEndpoint(View):
|
|||||||
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -93,17 +96,23 @@ class GitHubCallbackEndpoint(View):
|
|||||||
user = provider.authenticate()
|
user = provider.authenticate()
|
||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_app=True)
|
user_login(request=request, user=user, is_app=True)
|
||||||
# Get the redirection path
|
|
||||||
if next_path:
|
if next_path:
|
||||||
path = str(validate_next_path(next_path))
|
path = next_path
|
||||||
else:
|
else:
|
||||||
path = get_redirection_path(user=user)
|
path = get_redirection_path(user=user)
|
||||||
# redirect to referer path
|
|
||||||
url = urljoin(base_host, path)
|
# Get the safe redirect URL
|
||||||
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={}
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode, urljoin
|
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -16,7 +16,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class GitLabOauthInitiateEndpoint(View):
|
class GitLabOauthInitiateEndpoint(View):
|
||||||
@ -25,7 +25,7 @@ class GitLabOauthInitiateEndpoint(View):
|
|||||||
request.session["host"] = base_host(request=request, is_app=True)
|
request.session["host"] = base_host(request=request, is_app=True)
|
||||||
next_path = request.GET.get("next_path")
|
next_path = request.GET.get("next_path")
|
||||||
if next_path:
|
if next_path:
|
||||||
request.session["next_path"] = str(validate_next_path(next_path))
|
request.session["next_path"] = str(next_path)
|
||||||
|
|
||||||
# Check instance configuration
|
# Check instance configuration
|
||||||
instance = Instance.objects.first()
|
instance = Instance.objects.first()
|
||||||
@ -35,10 +35,10 @@ class GitLabOauthInitiateEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
try:
|
try:
|
||||||
@ -49,10 +49,10 @@ class GitLabOauthInitiateEndpoint(View):
|
|||||||
return HttpResponseRedirect(auth_url)
|
return HttpResponseRedirect(auth_url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -70,9 +70,11 @@ class GitLabCallbackEndpoint(View):
|
|||||||
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(next_path)
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
@ -81,9 +83,11 @@ class GitLabCallbackEndpoint(View):
|
|||||||
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -94,16 +98,23 @@ class GitLabCallbackEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_app=True)
|
user_login(request=request, user=user, is_app=True)
|
||||||
# Get the redirection path
|
# Get the redirection path
|
||||||
|
|
||||||
if next_path:
|
if next_path:
|
||||||
path = str(validate_next_path(next_path))
|
path = next_path
|
||||||
else:
|
else:
|
||||||
path = get_redirection_path(user=user)
|
path = get_redirection_path(user=user)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(base_host, path)
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={}
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode, urljoin
|
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -18,7 +17,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class GoogleOauthInitiateEndpoint(View):
|
class GoogleOauthInitiateEndpoint(View):
|
||||||
@ -36,10 +35,10 @@ class GoogleOauthInitiateEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -51,10 +50,10 @@ class GoogleOauthInitiateEndpoint(View):
|
|||||||
return HttpResponseRedirect(auth_url)
|
return HttpResponseRedirect(auth_url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -72,9 +71,11 @@ class GoogleCallbackEndpoint(View):
|
|||||||
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
if not code:
|
if not code:
|
||||||
exc = AuthenticationException(
|
exc = AuthenticationException(
|
||||||
@ -82,9 +83,11 @@ class GoogleCallbackEndpoint(View):
|
|||||||
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
try:
|
try:
|
||||||
provider = GoogleOAuthProvider(
|
provider = GoogleOAuthProvider(
|
||||||
@ -94,15 +97,21 @@ class GoogleCallbackEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_app=True)
|
user_login(request=request, user=user, is_app=True)
|
||||||
# Get the redirection path
|
# Get the redirection path
|
||||||
path = get_redirection_path(user=user)
|
if next_path:
|
||||||
# redirect to referer path
|
path = next_path
|
||||||
url = urljoin(
|
else:
|
||||||
base_host, str(validate_next_path(next_path)) if next_path else path
|
path = get_redirection_path(user=user)
|
||||||
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={}
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(base_host, "?" + urlencode(params))
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
# Python imports
|
|
||||||
from urllib.parse import urlencode, urljoin
|
|
||||||
|
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import validate_email
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -26,7 +23,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.authentication.rate_limit import AuthenticationThrottle
|
from plane.authentication.rate_limit import AuthenticationThrottle
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class MagicGenerateEndpoint(APIView):
|
class MagicGenerateEndpoint(APIView):
|
||||||
@ -72,10 +69,10 @@ class MagicSignInEndpoint(View):
|
|||||||
error_message="MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED",
|
error_message="MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -88,10 +85,10 @@ class MagicSignInEndpoint(View):
|
|||||||
error_message="USER_DOES_NOT_EXIST",
|
error_message="USER_DOES_NOT_EXIST",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -117,15 +114,19 @@ class MagicSignInEndpoint(View):
|
|||||||
else str(get_redirection_path(user=user))
|
else str(get_redirection_path(user=user))
|
||||||
)
|
)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(base_host(request=request, is_app=True), path)
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={},
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -145,10 +146,10 @@ class MagicSignUpEndpoint(View):
|
|||||||
error_message="MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED",
|
error_message="MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
# Existing user
|
# Existing user
|
||||||
@ -160,9 +161,11 @@ class MagicSignUpEndpoint(View):
|
|||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
if next_path:
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
params["next_path"] = str(next_path)
|
||||||
url = urljoin(
|
url = get_safe_redirect_url(
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@ -178,18 +181,22 @@ class MagicSignUpEndpoint(View):
|
|||||||
user_login(request=request, user=user, is_app=True)
|
user_login(request=request, user=user, is_app=True)
|
||||||
# Get the redirection path
|
# Get the redirection path
|
||||||
if next_path:
|
if next_path:
|
||||||
path = str(validate_next_path(next_path))
|
path = next_path
|
||||||
else:
|
else:
|
||||||
path = get_redirection_path(user=user)
|
path = get_redirection_path(user=user)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = urljoin(base_host(request=request, is_app=True), path)
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_app=True),
|
||||||
|
next_path=path,
|
||||||
|
params={},
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_app=True),
|
||||||
url = urljoin(
|
next_path=next_path,
|
||||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
params=params,
|
||||||
)
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
# Python imports
|
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import validate_email
|
||||||
@ -17,7 +14,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class SignInAuthSpaceEndpoint(View):
|
class SignInAuthSpaceEndpoint(View):
|
||||||
@ -32,9 +29,11 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# set the referer as session to redirect after login
|
# set the referer as session to redirect after login
|
||||||
@ -51,9 +50,11 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Validate email
|
# Validate email
|
||||||
@ -67,9 +68,11 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Existing User
|
# Existing User
|
||||||
@ -82,9 +85,11 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -95,13 +100,19 @@ class SignInAuthSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to next path
|
# redirect to next path
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params={}
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -117,9 +128,11 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
email = request.POST.get("email", False)
|
email = request.POST.get("email", False)
|
||||||
@ -135,9 +148,11 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
# Validate the email
|
# Validate the email
|
||||||
email = email.strip().lower()
|
email = email.strip().lower()
|
||||||
@ -151,9 +166,11 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Existing User
|
# Existing User
|
||||||
@ -166,9 +183,11 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
payload={"email": str(email)},
|
payload={"email": str(email)},
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -179,11 +198,17 @@ class SignUpAuthSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params={}
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -15,7 +14,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class GitHubOauthInitiateSpaceEndpoint(View):
|
class GitHubOauthInitiateSpaceEndpoint(View):
|
||||||
@ -23,9 +22,6 @@ class GitHubOauthInitiateSpaceEndpoint(View):
|
|||||||
# Get host and next path
|
# Get host and next path
|
||||||
request.session["host"] = base_host(request=request, is_space=True)
|
request.session["host"] = base_host(request=request, is_space=True)
|
||||||
next_path = request.GET.get("next_path")
|
next_path = request.GET.get("next_path")
|
||||||
if next_path:
|
|
||||||
request.session["next_path"] = str(next_path)
|
|
||||||
|
|
||||||
# Check instance configuration
|
# Check instance configuration
|
||||||
instance = Instance.objects.first()
|
instance = Instance.objects.first()
|
||||||
if instance is None or not instance.is_setup_done:
|
if instance is None or not instance.is_setup_done:
|
||||||
@ -34,9 +30,11 @@ class GitHubOauthInitiateSpaceEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -47,9 +45,11 @@ class GitHubOauthInitiateSpaceEndpoint(View):
|
|||||||
return HttpResponseRedirect(auth_url)
|
return HttpResponseRedirect(auth_url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(next_path)
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -66,9 +66,11 @@ class GitHubCallbackSpaceEndpoint(View):
|
|||||||
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
@ -77,9 +79,11 @@ class GitHubCallbackSpaceEndpoint(View):
|
|||||||
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -89,11 +93,17 @@ class GitHubCallbackSpaceEndpoint(View):
|
|||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# Process workspace and project invitations
|
# Process workspace and project invitations
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -15,7 +14,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class GitLabOauthInitiateSpaceEndpoint(View):
|
class GitLabOauthInitiateSpaceEndpoint(View):
|
||||||
@ -23,8 +22,6 @@ class GitLabOauthInitiateSpaceEndpoint(View):
|
|||||||
# Get host and next path
|
# Get host and next path
|
||||||
request.session["host"] = base_host(request=request, is_space=True)
|
request.session["host"] = base_host(request=request, is_space=True)
|
||||||
next_path = request.GET.get("next_path")
|
next_path = request.GET.get("next_path")
|
||||||
if next_path:
|
|
||||||
request.session["next_path"] = str(next_path)
|
|
||||||
|
|
||||||
# Check instance configuration
|
# Check instance configuration
|
||||||
instance = Instance.objects.first()
|
instance = Instance.objects.first()
|
||||||
@ -34,9 +31,11 @@ class GitLabOauthInitiateSpaceEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -47,9 +46,11 @@ class GitLabOauthInitiateSpaceEndpoint(View):
|
|||||||
return HttpResponseRedirect(auth_url)
|
return HttpResponseRedirect(auth_url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(next_path)
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -66,9 +67,11 @@ class GitLabCallbackSpaceEndpoint(View):
|
|||||||
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
@ -77,9 +80,11 @@ class GitLabCallbackSpaceEndpoint(View):
|
|||||||
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -89,11 +94,17 @@ class GitLabCallbackSpaceEndpoint(View):
|
|||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# Process workspace and project invitations
|
# Process workspace and project invitations
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import uuid
|
import uuid
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
# Django import
|
# Django import
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -15,15 +14,13 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class GoogleOauthInitiateSpaceEndpoint(View):
|
class GoogleOauthInitiateSpaceEndpoint(View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
request.session["host"] = base_host(request=request, is_space=True)
|
request.session["host"] = base_host(request=request, is_space=True)
|
||||||
next_path = request.GET.get("next_path")
|
next_path = request.GET.get("next_path")
|
||||||
if next_path:
|
|
||||||
request.session["next_path"] = str(next_path)
|
|
||||||
|
|
||||||
# Check instance configuration
|
# Check instance configuration
|
||||||
instance = Instance.objects.first()
|
instance = Instance.objects.first()
|
||||||
@ -33,9 +30,11 @@ class GoogleOauthInitiateSpaceEndpoint(View):
|
|||||||
error_message="INSTANCE_NOT_CONFIGURED",
|
error_message="INSTANCE_NOT_CONFIGURED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -46,9 +45,11 @@ class GoogleOauthInitiateSpaceEndpoint(View):
|
|||||||
return HttpResponseRedirect(auth_url)
|
return HttpResponseRedirect(auth_url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -65,9 +66,11 @@ class GoogleCallbackSpaceEndpoint(View):
|
|||||||
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
if not code:
|
if not code:
|
||||||
exc = AuthenticationException(
|
exc = AuthenticationException(
|
||||||
@ -75,9 +78,11 @@ class GoogleCallbackSpaceEndpoint(View):
|
|||||||
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
try:
|
try:
|
||||||
provider = GoogleOAuthProvider(request=request, code=code)
|
provider = GoogleOAuthProvider(request=request, code=code)
|
||||||
@ -85,11 +90,17 @@ class GoogleCallbackSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
# Python imports
|
|
||||||
from urllib.parse import urlencode
|
|
||||||
|
|
||||||
# Django imports
|
# Django imports
|
||||||
from django.core.validators import validate_email
|
from django.core.validators import validate_email
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@ -23,7 +20,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
AUTHENTICATION_ERROR_CODES,
|
AUTHENTICATION_ERROR_CODES,
|
||||||
)
|
)
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class MagicGenerateSpaceEndpoint(APIView):
|
class MagicGenerateSpaceEndpoint(APIView):
|
||||||
@ -66,9 +63,11 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
error_message="MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED",
|
error_message="MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
existing_user = User.objects.filter(email=email).first()
|
existing_user = User.objects.filter(email=email).first()
|
||||||
@ -79,9 +78,11 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
error_message="USER_DOES_NOT_EXIST",
|
error_message="USER_DOES_NOT_EXIST",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Active User
|
# Active User
|
||||||
@ -93,15 +94,19 @@ class MagicSignInSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
path = str(next_path) if next_path else ""
|
url = get_safe_redirect_url(
|
||||||
url = f"{base_host(request=request, is_space=True)}{path}"
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
base_url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(next_path)
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path
|
||||||
|
)
|
||||||
|
url = urljoin(base_url, "?" + urlencode(params))
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
@ -120,9 +125,11 @@ class MagicSignUpSpaceEndpoint(View):
|
|||||||
error_message="MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED",
|
error_message="MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
# Existing User
|
# Existing User
|
||||||
existing_user = User.objects.filter(email=email).first()
|
existing_user = User.objects.filter(email=email).first()
|
||||||
@ -133,9 +140,11 @@ class MagicSignUpSpaceEndpoint(View):
|
|||||||
error_message="USER_ALREADY_EXIST",
|
error_message="USER_ALREADY_EXIST",
|
||||||
)
|
)
|
||||||
params = exc.get_error_dict()
|
params = exc.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -146,12 +155,17 @@ class MagicSignUpSpaceEndpoint(View):
|
|||||||
# Login the user and record his device info
|
# Login the user and record his device info
|
||||||
user_login(request=request, user=user, is_space=True)
|
user_login(request=request, user=user, is_space=True)
|
||||||
# redirect to referer path
|
# redirect to referer path
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(next_path) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
except AuthenticationException as e:
|
except AuthenticationException as e:
|
||||||
params = e.get_error_dict()
|
params = e.get_error_dict()
|
||||||
if next_path:
|
url = get_safe_redirect_url(
|
||||||
params["next_path"] = str(validate_next_path(next_path))
|
base_url=base_host(request=request, is_space=True),
|
||||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
next_path=next_path,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from django.utils import timezone
|
|||||||
# Module imports
|
# Module imports
|
||||||
from plane.authentication.utils.host import base_host, user_ip
|
from plane.authentication.utils.host import base_host, user_ip
|
||||||
from plane.db.models import User
|
from plane.db.models import User
|
||||||
from plane.utils.path_validator import validate_next_path
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class SignOutAuthSpaceEndpoint(View):
|
class SignOutAuthSpaceEndpoint(View):
|
||||||
@ -22,8 +22,14 @@ class SignOutAuthSpaceEndpoint(View):
|
|||||||
user.save()
|
user.save()
|
||||||
# Log the user out
|
# Log the user out
|
||||||
logout(request)
|
logout(request)
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(validate_next_path(next_path)) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except Exception:
|
except Exception:
|
||||||
url = f"{base_host(request=request, is_space=True)}{str(validate_next_path(next_path)) if next_path else ''}"
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_space=True),
|
||||||
|
next_path=next_path
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -34,6 +34,7 @@ from plane.authentication.adapter.error import (
|
|||||||
AuthenticationException,
|
AuthenticationException,
|
||||||
)
|
)
|
||||||
from plane.utils.ip_address import get_client_ip
|
from plane.utils.ip_address import get_client_ip
|
||||||
|
from plane.utils.path_validator import get_safe_redirect_url
|
||||||
|
|
||||||
|
|
||||||
class InstanceAdminEndpoint(BaseAPIView):
|
class InstanceAdminEndpoint(BaseAPIView):
|
||||||
@ -392,7 +393,14 @@ class InstanceAdminSignOutEndpoint(View):
|
|||||||
user.save()
|
user.save()
|
||||||
# Log the user out
|
# Log the user out
|
||||||
logout(request)
|
logout(request)
|
||||||
url = urljoin(base_host(request=request, is_admin=True))
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_admin=True),
|
||||||
|
next_path=""
|
||||||
|
)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
except Exception:
|
except Exception:
|
||||||
return HttpResponseRedirect(base_host(request=request, is_admin=True))
|
url = get_safe_redirect_url(
|
||||||
|
base_url=base_host(request=request, is_admin=True),
|
||||||
|
next_path=""
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@ -2,9 +2,55 @@
|
|||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
|
||||||
|
def _contains_suspicious_patterns(path: str) -> bool:
|
||||||
|
"""
|
||||||
|
Check for suspicious patterns that might indicate malicious intent.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): The path to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if suspicious patterns found, False otherwise
|
||||||
|
"""
|
||||||
|
suspicious_patterns = [
|
||||||
|
r'javascript:', # JavaScript injection
|
||||||
|
r'data:', # Data URLs
|
||||||
|
r'vbscript:', # VBScript injection
|
||||||
|
r'file:', # File protocol
|
||||||
|
r'ftp:', # FTP protocol
|
||||||
|
r'%2e%2e', # URL encoded path traversal
|
||||||
|
r'%2f%2f', # URL encoded double slash
|
||||||
|
r'%5c%5c', # URL encoded backslashes
|
||||||
|
r'<script', # Script tags
|
||||||
|
r'<iframe', # Iframe tags
|
||||||
|
r'<object', # Object tags
|
||||||
|
r'<embed', # Embed tags
|
||||||
|
r'<form', # Form tags
|
||||||
|
r'onload=', # Event handlers
|
||||||
|
r'onerror=', # Event handlers
|
||||||
|
r'onclick=', # Event handlers
|
||||||
|
]
|
||||||
|
|
||||||
|
path_lower = path.lower()
|
||||||
|
for pattern in suspicious_patterns:
|
||||||
|
if pattern in path_lower:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate_next_path(next_path: str) -> str:
|
def validate_next_path(next_path: str) -> str:
|
||||||
"""Validates that next_path is a safe relative path for redirection."""
|
"""Validates that next_path is a safe relative path for redirection."""
|
||||||
# Browsers interpret backslashes as forward slashes. Remove all backslashes.
|
# Browsers interpret backslashes as forward slashes. Remove all backslashes.
|
||||||
|
if not next_path or not isinstance(next_path, str):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
# Limit input length to prevent DoS attacks
|
||||||
|
if len(next_path) > 500:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
next_path = next_path.replace("\\", "")
|
next_path = next_path.replace("\\", "")
|
||||||
parsed_url = urlparse(next_path)
|
parsed_url = urlparse(next_path)
|
||||||
|
|
||||||
@ -20,4 +66,33 @@ def validate_next_path(next_path: str) -> str:
|
|||||||
if ".." in next_path:
|
if ".." in next_path:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
# Additional security checks
|
||||||
|
if _contains_suspicious_patterns(next_path):
|
||||||
|
return ""
|
||||||
|
|
||||||
return next_path
|
return next_path
|
||||||
|
|
||||||
|
|
||||||
|
def get_safe_redirect_url(base_url: str, next_path: str = "", params: dict = {}) -> str:
|
||||||
|
"""
|
||||||
|
Safely construct a redirect URL with validated next_path.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
base_url (str): The base URL to redirect to
|
||||||
|
next_path (str): The next path to append
|
||||||
|
params (dict): The parameters to append
|
||||||
|
Returns:
|
||||||
|
str: The safe redirect URL
|
||||||
|
"""
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
|
# Validate the next path
|
||||||
|
validated_path = validate_next_path(next_path)
|
||||||
|
|
||||||
|
# Add the next path to the parameters
|
||||||
|
if validated_path:
|
||||||
|
params["next_path"] = validated_path
|
||||||
|
|
||||||
|
# Return the safe redirect URL
|
||||||
|
return f"{base_url.rstrip('/')}?{urlencode(params)}"
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user