1) Added email id validation on the login page.

2) Added validation for the file manager.
This commit is contained in:
Aditya Toshniwal 2020-09-11 19:55:19 +05:30 committed by Akshay Joshi
parent 6ded547a0d
commit b82e6dbdb8
6 changed files with 86 additions and 43 deletions

View File

@ -17,16 +17,18 @@ from flask_babelex import gettext
from .registry import AuthSourceRegistry
from pgadmin.model import User
from pgadmin.utils.validation_utils import validate_email
@six.add_metaclass(AuthSourceRegistry)
class BaseAuthentication(object):
DEFAULT_MSG = {
'USER_DOES_NOT_EXIST': 'Incorrect username or password.',
'LOGIN_FAILED': 'Login failed',
'EMAIL_NOT_PROVIDED': 'Email/Username not provided',
'PASSWORD_NOT_PROVIDED': 'Password not provided'
'USER_DOES_NOT_EXIST': gettext('Incorrect username or password.'),
'LOGIN_FAILED': gettext('Login failed'),
'EMAIL_NOT_PROVIDED': gettext('Email/Username not provided'),
'PASSWORD_NOT_PROVIDED': gettext('Password not provided'),
'INVALID_EMAIL': gettext('Email/Username is not valid')
}
@abstractproperty
@ -85,7 +87,10 @@ class InternalAuthentication(BaseAuthentication):
def validate(self, form):
"""User validation"""
# validate the email id first
if not validate_email(form.data['email']):
form.errors['email'] = [self.messages('INVALID_EMAIL')]
return False
# Flask security validation
return form.validate_on_submit()

View File

@ -18,6 +18,7 @@ from urllib.parse import unquote
from sys import platform as _platform
import config
import codecs
import pathlib
from werkzeug.exceptions import InternalServerError
import simplejson as json
@ -317,6 +318,11 @@ class Filemanager(object):
# Stores list of dict for filename & its encoding
loaded_file_encoding_list = []
ERROR_NOT_ALLOWED = {
'Error': gettext('Not allowed'),
'Code': 0
}
def __init__(self, trans_id):
self.trans_id = trans_id
self.patherror = encode_json(
@ -822,10 +828,7 @@ class Filemanager(object):
Rename file or folder
"""
if not self.validate_request('rename'):
return {
'Error': gettext('Not allowed'),
'Code': 0
}
return self.ERROR_NOT_ALLOWED
the_dir = self.dir if self.dir is not None else ''
@ -883,10 +886,7 @@ class Filemanager(object):
Delete file or folder
"""
if not self.validate_request('delete'):
return {
'Error': gettext('Not allowed'),
'Code': 0
}
return self.ERROR_NOT_ALLOWED
the_dir = self.dir if self.dir is not None else ''
orig_path = "{0}{1}".format(the_dir, path)
@ -924,10 +924,7 @@ class Filemanager(object):
File upload functionality
"""
if not self.validate_request('upload'):
return {
'Error': gettext('Not allowed'),
'Code': 0
}
return self.ERROR_NOT_ALLOWED
the_dir = self.dir if self.dir is not None else ''
err_msg = ''
@ -940,6 +937,12 @@ class Filemanager(object):
orig_path = "{0}{1}".format(the_dir, path)
new_name = "{0}{1}".format(orig_path, file_name)
try:
# Check if the new file is inside the users directory
pathlib.Path(new_name).relative_to(the_dir)
except ValueError as _:
return self.ERROR_NOT_ALLOWED
with open(new_name, 'wb') as f:
while True:
# 4MB chunk (4 * 1024 * 1024 Bytes)
@ -1103,10 +1106,7 @@ class Filemanager(object):
Functionality to create new folder
"""
if not self.validate_request('create'):
return {
'Error': gettext('Not allowed'),
'Code': 0
}
return self.ERROR_NOT_ALLOWED
the_dir = self.dir if self.dir is not None else ''
@ -1156,10 +1156,7 @@ class Filemanager(object):
Functionality to download file
"""
if not self.validate_request('download'):
return {
'Error': gettext('Not allowed'),
'Code': 0
}
return self.ERROR_NOT_ALLOWED
the_dir = self.dir if self.dir is not None else ''
orig_path = "{0}{1}".format(the_dir, path)

View File

@ -14,6 +14,8 @@ import os
import re
import getpass
from pgadmin.utils.validation_utils import validate_email
def user_info_desktop():
print("NOTE: Configuring authentication for DESKTOP mode.")
@ -43,14 +45,8 @@ def user_info_server():
"pgAdmin user account:\n"
)
email_filter = re.compile(
"^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9]"
"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]"
"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
)
email = input("Email address: ")
while email == '' or not email_filter.match(email):
while not validate_email(email):
print('Invalid email address. Please try again.')
email = input("Email address: ")

View File

@ -22,9 +22,10 @@ from werkzeug.exceptions import InternalServerError
import config
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_response as ajax_response, \
make_json_response, bad_request, internal_server_error
make_json_response, bad_request, internal_server_error, forbidden
from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin.utils.constants import MIMETYPE_APP_JS
from pgadmin.utils.validation_utils import validate_email
from pgadmin.model import db, Role, User, UserPreference, Server, \
ServerGroup, Process, Setting
@ -104,16 +105,11 @@ def validate_password(data, new_data):
def validate_user(data):
new_data = dict()
email_filter = re.compile(
"^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9]"
"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9]"
"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
)
validate_password(data, new_data)
if 'email' in data and data['email'] and data['email'] != "":
if email_filter.match(data['email']):
if validate_email(data['email']):
new_data['email'] = data['email']
else:
raise InternalServerError(_("Invalid email address."))
@ -383,6 +379,18 @@ def update(uid):
request.data, encoding='utf-8'
)
# Username and email can not be changed for internal users
if usr.auth_source == current_app.PGADMIN_DEFAULT_AUTH_SOURCE:
non_editable_params = ('username', 'email')
for f in non_editable_params:
if f in data:
return forbidden(
errmsg=_(
"'{0}' is not allowed to modify."
).format(f)
)
try:
new_data = validate_user(data)

View File

@ -34,9 +34,18 @@ def get_storage_directory():
if storage_dir is None:
return None
username = current_user.username.split('@')[0]
if len(username) == 0 or username[0].isdigit():
username = 'pga_user_' + username
def _preprocess_username(un):
ret_un = un
if len(ret_un) == 0 or ret_un[0].isdigit():
ret_un = 'pga_user_' + username
ret_un = ret_un.replace('@', '_')\
.replace('/', 'slash')\
.replace('\\', 'slash')
return ret_un
username = _preprocess_username(current_user.username.split('@')[0])
# Figure out the old-style storage directory name
old_storage_dir = os.path.join(
@ -45,11 +54,13 @@ def get_storage_directory():
username
)
username = _preprocess_username(current_user.username)
# Figure out the new style storage directory name
storage_dir = os.path.join(
storage_dir.decode('utf-8') if hasattr(storage_dir, 'decode')
else storage_dir,
current_user.username.replace('@', '_')
username
)
# Rename an old-style storage directory, if the new style doesn't exist

View File

@ -0,0 +1,26 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2020, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
import re
def validate_email(email):
if email == '' or email is None:
return False
email_filter = re.compile(
"^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9]"
"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]"
"(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
)
if not email_filter.match(email):
return False
return True