Skip to content

Commit

Permalink
fix: email validation (#4707)
Browse files Browse the repository at this point in the history
* fix: email validation on complete login or sign up functionality

* dev: add try catch block

* dev: split up code

* dev: empty return
  • Loading branch information
pablohashescobar authored Jun 5, 2024
1 parent 52d8d6e commit 249e71e
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 42 deletions.
137 changes: 100 additions & 37 deletions apiserver/plane/authentication/adapter/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

# Django imports
from django.utils import timezone
from django.core.validators import validate_email
from django.core.exceptions import ValidationError

# Third party imports
from zxcvbn import zxcvbn
Expand Down Expand Up @@ -46,60 +48,124 @@ def create_update_account(self, user):
def authenticate(self):
raise NotImplementedError

def sanitize_email(self, email):
# Check if email is present
if not email:
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["INVALID_EMAIL"],
error_message="INVALID_EMAIL",
payload={"email": email},
)

# Sanitize email
email = str(email).lower().strip()

# validate email
try:
validate_email(email)
except ValidationError:
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["INVALID_EMAIL"],
error_message="INVALID_EMAIL",
payload={"email": email},
)
# Return email
return email

def validate_password(self, email):
"""Validate password strength"""
results = zxcvbn(self.code)
if results["score"] < 3:
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
error_message="INVALID_PASSWORD",
payload={"email": email},
)
return

def __check_signup(self, email):
"""Check if sign up is enabled or not and raise exception if not enabled"""

# Get configuration value
(ENABLE_SIGNUP,) = get_configuration_value(
[
{
"key": "ENABLE_SIGNUP",
"default": os.environ.get("ENABLE_SIGNUP", "1"),
},
]
)

# Check if sign up is disabled and invite is present or not
if (
ENABLE_SIGNUP == "0"
and not WorkspaceMemberInvite.objects.filter(
email=email,
).exists()
):
# Raise exception
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["SIGNUP_DISABLED"],
error_message="SIGNUP_DISABLED",
payload={"email": email},
)

return True

def save_user_data(self, user):
# Update user details
user.last_login_medium = self.provider
user.last_active = timezone.now()
user.last_login_time = timezone.now()
user.last_login_ip = self.request.META.get("REMOTE_ADDR")
user.last_login_uagent = self.request.META.get("HTTP_USER_AGENT")
user.token_updated_at = timezone.now()
user.save()
return user

def complete_login_or_signup(self):
# Get email
email = self.user_data.get("email")

# Sanitize email
email = self.sanitize_email(email)

# Check if the user is present
user = User.objects.filter(email=email).first()
# Check if sign up case or login
is_signup = bool(user)
# If user is not present, create a new user
if not user:
# New user
(ENABLE_SIGNUP,) = get_configuration_value(
[
{
"key": "ENABLE_SIGNUP",
"default": os.environ.get("ENABLE_SIGNUP", "1"),
},
]
)
if (
ENABLE_SIGNUP == "0"
and not WorkspaceMemberInvite.objects.filter(
email=email,
).exists()
):
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["SIGNUP_DISABLED"],
error_message="SIGNUP_DISABLED",
payload={"email": email},
)
self.__check_signup(email)

# Initialize user
user = User(email=email, username=uuid.uuid4().hex)

# Check if password is autoset
if self.user_data.get("user").get("is_password_autoset"):
user.set_password(uuid.uuid4().hex)
user.is_password_autoset = True
user.is_email_verified = True

# Validate password
else:
# Validate password
results = zxcvbn(self.code)
if results["score"] < 3:
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES[
"INVALID_PASSWORD"
],
error_message="INVALID_PASSWORD",
payload={"email": email},
)

self.validate_password(email)
# Set password
user.set_password(self.code)
user.is_password_autoset = False

# Set user details
avatar = self.user_data.get("user", {}).get("avatar", "")
first_name = self.user_data.get("user", {}).get("first_name", "")
last_name = self.user_data.get("user", {}).get("last_name", "")
user.avatar = avatar if avatar else ""
user.first_name = first_name if first_name else ""
user.last_name = last_name if last_name else ""
user.save()

# Create profile
Profile.objects.create(user=user)

if not user.is_active:
Expand All @@ -108,23 +174,20 @@ def complete_login_or_signup(self):
error_message="USER_ACCOUNT_DEACTIVATED",
)

# Update user details
user.last_login_medium = self.provider
user.last_active = timezone.now()
user.last_login_time = timezone.now()
user.last_login_ip = self.request.META.get("REMOTE_ADDR")
user.last_login_uagent = self.request.META.get("HTTP_USER_AGENT")
user.token_updated_at = timezone.now()
user.save()
# Save user data
user = self.save_user_data(user=user)

# Call callback if present
if self.callback:
self.callback(
user,
is_signup,
self.request,
)

# Create or update account if token data is present
if self.token_data:
self.create_update_account(user=user)

# Return user
return user
2 changes: 2 additions & 0 deletions apiserver/plane/authentication/adapter/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
"ADMIN_USER_DEACTIVATED": 5190,
# Rate limit
"RATE_LIMIT_EXCEEDED": 5900,
# Unknown
"AUTHENTICATION_FAILED": 5999,
}


Expand Down
10 changes: 5 additions & 5 deletions apiserver/plane/authentication/adapter/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ def get_user_response(self):
response.raise_for_status()
return response.json()
except requests.RequestException:
code = (
"GOOGLE_OAUTH_PROVIDER_ERROR"
if self.provider == "google"
else "GITHUB_OAUTH_PROVIDER_ERROR"
)
if self.provider == "google":
code = "GOOGLE_OAUTH_PROVIDER_ERROR"
if self.provider == "github":
code = "GITHUB_OAUTH_PROVIDER_ERROR"

raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES[code],
error_message=str(code),
Expand Down

0 comments on commit 249e71e

Please sign in to comment.