Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update django 4.2 #343

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ GITHUB_SECRET="<insert>"
OAUTH_PROVIDERS="github"
SECRET_KEY="<insert>"
NAMESPACE="default"
stdnfsPvc="stdnfs"
stdnfsPvc="stdnfs"
CSRF_DOMAINS="https://*.renci.org"
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ RUN adduser --disabled-login --home $HOME --shell /bin/bash --uid $UID $USER &&

RUN set -x && apt-get update && \
chown -R $UID:$UID $APP_HOME && \
apt-get install -y build-essential git xmlsec1
apt-get install -y build-essential git xmlsec1 libpq5 gcc

# Removing but leaving commented in case Tycho needs this for swagger.
# Version 3.3.1 currently, if not complaints v3.3.3 this can be
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ clean:
${MANAGE} flush
${PYTHON} -m pip uninstall -y -r requirements.txt

#install: Install application along with required development packages
install:
${PYTHON} -m pip install --upgrade pip
${PYTHON} -m pip install -r requirements.txt

#test: Run all tests
test:
Expand Down
3 changes: 1 addition & 2 deletions appstore/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from django.conf.urls import re_path
from django.urls import include
from django.urls import include, re_path

from .v1.router import v1_urlpatterns

Expand Down
5 changes: 3 additions & 2 deletions appstore/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,10 +684,11 @@ def _get_social_providers(self, request, settings):
"allauth.account.auth_backends.AuthenticationBackend"
in settings.AUTHENTICATION_BACKENDS
):
for provider in socialaccount.providers.registry.get_list():
for provider in socialaccount.providers.registry.get_class_list():
inst = provider(request, "allauth.socialaccount")
provider_data.append(
asdict(
LoginProvider(provider.name, provider.get_login_url(request))
LoginProvider(inst.name, inst.get_login_url(request))
)
)

Expand Down
36 changes: 28 additions & 8 deletions appstore/appstore/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
if DEBUG_STRING.lower() == "false":
DEBUG_STRING = ""
DEBUG = bool(DEBUG_STRING)

# stub, local, dev, val, prod.
DEV_PHASE = os.environ.get("DEV_PHASE", "local")
TYCHO_MODE = os.environ.get("TYCHO_MODE", "null" if DEV_PHASE == "stub" else "live")
Expand Down Expand Up @@ -80,6 +81,7 @@
"django.contrib.auth",
"django.contrib.messages",
"django.contrib.sites",
"django_saml2_auth",
]

THIRD_PARTY_APPS = [
Expand Down Expand Up @@ -122,9 +124,10 @@
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django.contrib.auth.middleware.RemoteUserMiddleware",
"django.contrib.auth.middleware.PersistentRemoteUserMiddleware",
"middleware.filter_whitelist_middleware.AllowWhiteListedUserOnly",
"middleware.session_idle_timeout.SessionIdleTimeout",
"allauth.account.middleware.AccountMiddleware"
]

SESSION_IDLE_TIMEOUT = int(os.environ.get("DJANGO_SESSION_IDLE_TIMEOUT", 300))
Expand All @@ -143,20 +146,22 @@
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_VERIFICATION = "none"
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 3
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400 # 1 day in seconds
ACCOUNT_RATE_LIMITS= {'login_failed':10}
#deprecated ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400 # 1 day in seconds
ACCOUNT_LOGOUT_REDIRECT_URL = "/helx"
LOGIN_REDIRECT_URL = "/helx/workspaces/login/success"
LOGIN_URL = "/accounts/login"
LOGIN_WHITELIST_URL = "/login_whitelist/"
OIDC_SESSION_MANAGEMENT_ENABLE = True
SAML_URL = "/accounts/saml"
SAML_ACS_URL = "/saml2_auth/acs/"
#SAML_ACS_URL = "/sso/acs/"
SOCIALACCOUNT_QUERY_EMAIL = ACCOUNT_EMAIL_REQUIRED
SOCIALACCOUNT_STORE_TOKENS = True
SOCIALACCOUNT_PROVIDERS = {
"google": {"SCOPE": ["profile", "email"], "AUTH_PARAMS": {"access_type": "offline"}}
}
SECURE_CROSS_ORIGIN_OPENER_POLICY = None

TEMPLATES = [
{
Expand Down Expand Up @@ -339,6 +344,9 @@
},
}

csrf_strings = os.environ.get("CSRF_DOMAINS", "")
CSRF_TRUSTED_ORIGINS = [] if len(csrf_strings) == 0 else csrf_strings.split(',')

# All debug settings
if DEBUG and DEV_PHASE in ("local", "stub", "dev"):
INSTALLED_APPS += [
Expand All @@ -349,6 +357,13 @@
"127.0.0.1",
]

CSRF_TRUSTED_ORIGINS += [
"https://localhost",
hina-shah marked this conversation as resolved.
Show resolved Hide resolved
"https://127.0.0.1",
hina-shah marked this conversation as resolved.
Show resolved Hide resolved
"http://localhost",
"http://127.0.0.1",
]

CORS_ALLOWED_ORIGINS = [
hina-shah marked this conversation as resolved.
Show resolved Hide resolved
"https://localhost:3000",
"https://127.0.0.1:3000",
Expand All @@ -359,11 +374,6 @@
# We don't want to create security vulnerabilities through CORS policy. Only allow on dev deployments where the UI may be running on another origin.
CORS_ALLOW_CREDENTIALS = True

CSRF_TRUSTED_ORIGINS = [
"localhost",
"127.0.0.1",
]

DEBUG_MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"debug_toolbar.middleware.DebugToolbarMiddleware",
Expand All @@ -389,10 +399,18 @@
"first_name": "givenName",
"last_name": "sn",
},
"TRIGGER": {
"CREATE_USER": "core.models.update_user",
},
"ASSERTION_URL": os.environ.get("SAML2_AUTH_ASSERTION_URL"),
"ENTITY_ID": os.environ.get(
"SAML2_AUTH_ENTITY_ID"
), # Populates the Issuer element in authn request
"USE_JWT": False,
'WANT_ASSERTIONS_SIGNED': True,
'AUTHN_REQUESTS_SIGNED': False,
'WANT_RESPONSE_SIGNED': False,
'TOKEN_REQUIRED': False,
}

# Metadata is required, either remote url or local file path, check the environment
Expand All @@ -407,3 +425,5 @@
SAML2_AUTH["METADATA_AUTO_CONF_URL"] = metadata_source
else: SAML2_AUTH["METADATA_LOCAL_FILE_PATH"] = metadata_source
else: SAML2_AUTH["METADATA_LOCAL_FILE_PATH"] = metadata_source

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
2 changes: 1 addition & 1 deletion appstore/appstore/settings/heal_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
title="NIH HEAL Initiative",
logo_url="/static/images/heal/logo.png",
color_scheme=ProductColorScheme("#8a5a91", "#505057"),
links=None,
links=[],
)
2 changes: 1 addition & 1 deletion appstore/appstore/settings/helx_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
title="HeLx",
logo_url="/static/images/helx/logo.png",
color_scheme=ProductColorScheme("#8a5a91", "#505057"),
links=None,
links=[],
)
12 changes: 12 additions & 0 deletions appstore/core/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
from django.db import models
from django.contrib.auth import get_user_model
from django_saml2_auth.user import get_user

def update_user(user):
# as of Django_saml2_auth v3.12.0 does not add email address by default
# to the created use entry in django db according to:
# https://github.com/grafana/django-saml2-auth/blob/11b97beaa2a431209e2c54103cb49c033c42ff54/django_saml2_auth/user.py#L93
# https://github.com/grafana/django-saml2-auth/blob/11b97beaa2a431209e2c54103cb49c033c42ff54/django_saml2_auth/user.py#L165
# This trigger gets and set the email field in the django user db
_user = get_user(user)
_user.email = user['email']
_user.save()
return _user

class AuthorizedUser(models.Model):
email = models.EmailField(max_length=254)
Expand Down
19 changes: 18 additions & 1 deletion appstore/middleware/filter_whitelist_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@


class AllowWhiteListedUserOnly(MiddlewareMixin):
def __init__(self, get_response=None):
if get_response is not None:
self.get_response = get_response
else:
self.get_response = self._get_response

def process_request(self, request):
user = request.user
logger.debug(f"testing user: {user}")

if user.is_authenticated and not user.is_superuser:
if not any(
[
Expand All @@ -34,7 +41,6 @@ def process_request(self, request):
request.path.startswith("/api/v1/providers"),
]
):

if self.is_authorized(user):
logger.debug(f"Adding user {user} to whitelist")
whitelist_group = Group.objects.get(name="whitelisted")
Expand All @@ -56,6 +62,17 @@ def process_request(self, request):
logger.info(f"accepting user {user}")
return None

def _get_response(self, request):
"""
Call the next middleware in the chain to get a response.
"""
# Call the next middleware in the chain to get a response
if hasattr(self, 'process_response'):
return self.process_response(request)
else:
# If there's no process_response method, return None
return None

@staticmethod
def is_whitelisted(user):
if user.groups.filter(name="whitelisted").exists():
Expand Down
3 changes: 2 additions & 1 deletion appstore/middleware/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ def _create_user_and_login(
return user

def test_login_whitelisted_user(self):
print("---- TESTING FOR WHITELISTED USER (steve_whitelist) ----- ")
user = self._create_user_and_login(
username="Steve_whitelist", email="[email protected]", password="admin"
)
AuthorizedUser.objects.create(email=user.email)
self.request.user = user
self.request.session = self.client.session
response = self.middleware.process_request(self.request)
self.assertTrue(isinstance(response, HttpResponseRedirect))
self.assertFalse(isinstance(response, HttpResponseRedirect))
self.assertEqual(
list(self.request.user.groups.values_list("name", flat=True))[0],
self.groups.name,
Expand Down
32 changes: 16 additions & 16 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
Django==3.2.23
django-allauth==0.54.0
django-cors-headers==3.7.0
django-crispy-forms==1.11.2
django-debug-toolbar==3.2
django-extensions==3.1.1
django-saml2-auth==2.2.1
djangorestframework==3.12.2
drf-spectacular==0.15.1
Django==4.2
django-allauth==0.61.1
django-cors-headers==4.3.1
django-crispy-forms==2.1
django-debug-toolbar==4.3.0
django-extensions==3.2.3
grafana-django-saml2-auth==3.12.0
djangorestframework==3.14.0
drf-spectacular==0.27.1
flake8==3.9.0
gunicorn==20.1.0
mock==4.0.2
pysaml2
python3-openid==3.1.0
pysaml2==7.4.2
python3-openid==3.2.0
requests==2.31.0
requests-oauthlib
requests-oauthlib==1.4.0
selenium==3.141.0
tycho-api>=1.17
webdriver-manager==3.2.1
sqlparse==0.4.2
asgiref==3.4.1
psycopg2-binary
python-irodsclient==1.1.5
sqlparse==0.4.4
asgiref==3.7.2
psycopg[binary]
python-irodsclient==1.1.5
Loading