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 pipelines #1732

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
67 changes: 34 additions & 33 deletions django_api/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,51 +11,52 @@ django-fixture-magic = "*"
isort = "*"

[packages]
aiohttp = "<=3.7.4.post0"
azure-common = "<=1.1.27"
azure-storage-blob = "<12.0"
aiohttp = "<=3.8.1"
azure-common = "<=1.1.28"
azure-storage-blob = "<=12.12"
azure-storage-common = "<=2.1"
Babel = "<=2.9.1"
boto3 = "<=1.18.24"
Babel = "<=2.10.1"
carto = "<=1.11.3"
cryptography = "<3.4" # issue with image
django = "<=3.2.6"
django-admin-extra-urls = "<=3.5.1"
django = "<4.0"
django-admin-extra-urls = "<=4.1.1"
django-celery-beat = "<=2.2.1"
django-celery-email = "<=3.0"
django-celery-results = "<=2.2"
django-cors-headers = "<=3.8"
django-cron = "<=0.5.1"
django-environ = "<=0.4.5"
django-extensions = "<=3.1.3"
django-filter = "<=2.4"
django-leaflet = "<=0.28.1"
django-model-utils = "<=4.1.1"
django-mptt = "<=0.12"
django-celery-results = "<=2.3.1"
django-cors-headers = "<=3.12"
django-cron = "<=0.6"
django-environ = "<=0.8.1"
django-extensions = "<=3.1.5"
django-filter = "<=21.1"
django-leaflet = "<=0.28.2"
django-model-utils = "<=4.2"
django-mptt = "<=0.13.4"
django-paintstore = "<=0.2"
django-redis-cache = "<=3.0"
django-redis-cache = "<=3.0.1"
django-rest-swagger = "<=2.2"
django-storages = "<=1.11.1"
djangorestframework = "<=3.12.4"
djangorestframework-gis = "<=0.17"
djangorestframework-simplejwt = "<=4.8"
drfpasswordless = "<=1.5.7"
greenlet = "<=1.1.1"
newrelic = "<=6.8.0.163"
openpyxl = "<=3.0.7"
psycopg2-binary = "<=2.9.1"
pycountry = "<=20.7.3"
django-storages = "<=1.12.3"
djangorestframework = "<=3.13.1"
djangorestframework-gis = "<=1.0"
djangorestframework-simplejwt = "<=5.2"
drfpasswordless = "<=1.5.8"
greenlet = "<=1.1.2"
newrelic = "*"
openpyxl = "<=3.0.9"
psycopg2-binary = "<=2.9.3"
pycountry = "<=22.3.5"
python-json-logger = "<=2.0.2"
python-social-auth = "<=0.3.6"
pyrestcli = "<=0.6.11"
requests = "<=2.26"
sentry-sdk = "<=1.3.1"
pyrestcli = "<=0.6.12"
requests = "<=2.27.1"
sentry-sdk = "<=1.5.12"
social-auth-app-django = "<=5.0"
social-auth-core = "<=5.0"
unicef-djangolib = "<=0.6"
unicef-notification = "<=1.1"
unicef-locations = "<=4.0"
uWSGI = "<=2.0.19.1"
weasyprint = "<=53.0"
unicef-security = "<=1.1"
unicef-locations = "<=4.0.1"
uWSGI = "<=2.0.20"
weasyprint = "<=55"

[requires]
python_version = "3.9"
968 changes: 553 additions & 415 deletions django_api/Pipfile.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions django_api/etools_prp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from etools_prp.config.celery import app as celery_app
from etools_prp.config.celery import app as celery_app # noqa

NAME = 'etools_prp'
VERSION = '9.13'

__all__ = ['celery_app', ]
84 changes: 1 addition & 83 deletions django_api/etools_prp/apps/core/mixins.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,16 @@
from datetime import datetime, timedelta
from urllib.parse import quote

from django.conf import settings
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.utils.deconstruct import deconstructible

from social_core.backends.azuread_b2c import AzureADB2COAuth2
from social_core.pipeline import social_auth, user as social_core_user
from social_django.middleware import SocialAuthExceptionMiddleware
from storages.backends.azure_storage import AzureStorage
from storages.utils import setting


def social_details(backend, details, response, *args, **kwargs):
r = social_auth.social_details(backend, details, response, *args, **kwargs)

user = kwargs.get('user', None)
if user:
# here we are preventing messing up between current us and social user
return HttpResponseRedirect(f"/unauthorized/?eu={user.email}&msgc=alreadyauthenticated")

r['details']['idp'] = response.get('idp')

if not r['details'].get('email'):
if not response.get('email'):
r['details']['email'] = response["signInNames.emailAddress"]
else:
r['details']['email'] = response.get('email')

email = r['details'].get('email')
if isinstance(email, str):
r['details']['email'] = email.lower().strip()
return r


def get_username(strategy, details, backend, user=None, *args, **kwargs):
"""allow to login only existing/already created users """
username = details.get('email')

try:
Expand All @@ -48,63 +23,6 @@ def get_username(strategy, details, backend, user=None, *args, **kwargs):
return {'username': details.get('email')}


def user_details(strategy, details, backend, user=None, *args, **kwargs):
# # This is where we update the user
# # see what the property to map by is here
# updates_available = False

if user:
# user_groups = [group.name for group in user.groups.all()]
# business_area_code = details.get("business_area_code", 'defaultBA1235')

# Update username with email and unusable password
user.username = user.email
user.first_name = details['first_name']
user.last_name = details['last_name']
user.set_unusable_password()
user.save()

return social_core_user.user_details(strategy, details, backend, user, *args, **kwargs)


class CustomAzureADBBCOAuth2(AzureADB2COAuth2):
BASE_URL = 'https://{tenant_id}.b2clogin.com/{tenant_id}.onmicrosoft.com'

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.redirect_uri = settings.FRONTEND_HOST + '/social/complete/azuread-b2c-oauth2/'


class CustomSocialAuthExceptionMiddleware(SocialAuthExceptionMiddleware):

def get_redirect_uri(self, request, exception):
error = request.GET.get('error', None)

# This is what we should expect:
# ['AADB2C90118: The user has forgotten their password.\r\n
# Correlation ID: 7e8c3cf9-2fa7-47c7-8924-a1ea91137ba9\r\n
# Timestamp: 2018-11-13 11:37:56Z\r\n']
error_description = request.GET.get('error_description', None)
if error == "access_denied" and error_description is not None:
if 'AADB2C90118' in error_description:
auth_class = CustomAzureADBBCOAuth2()
redirect_home = auth_class.get_redirect_uri()
redirect_url = auth_class.base_url + '/oauth2/v2.0/' + \
'authorize?p=' + settings.SOCIAL_PASSWORD_RESET_POLICY + \
'&client_id=' + settings.KEY + \
'&nonce=defaultNonce&redirect_uri=' + redirect_home + \
'&scope=openid+email&response_type=code'
return redirect_url

# TODO: In case of password reset the state can't be verified figure out a way to log the user in after reset
if error is None:
return "/landing"

strategy = getattr(request, 'social_strategy', None)
redirect_url = strategy.setting('LOGIN_ERROR_URL') + "?msgc=loginerror"
return redirect_url


@deconstructible
class EToolsAzureStorage(AzureStorage):
account_name = setting("AZURE_ACCOUNT_NAME")
Expand Down
9 changes: 0 additions & 9 deletions django_api/etools_prp/apps/core/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import importlib

from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
from django.http import HttpResponseRedirect
Expand Down Expand Up @@ -274,11 +273,3 @@ def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['unicef_user'] = self.request.user.is_authenticated and self.request.user.email.endswith('@unicef.org')
return context


# TODO import from unicef-security
class SocialLogoutView(RedirectView):

def get_redirect_url(self, *args, **kwargs):
return f'https://{settings.TENANT_B2C_URL}/{settings.TENANT_ID}.onmicrosoft.com/{settings.POLICY}/oauth2/' \
f'v2.0/logout?post_logout_redirect_uri={settings.FRONTEND_HOST}{settings.LOGOUT_URL}'
26 changes: 16 additions & 10 deletions django_api/etools_prp/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.django import DjangoIntegration

import etools_prp

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
env = environ.Env()

Expand All @@ -36,10 +38,10 @@
os.path.join(BASE_DIR, 'static'),
]

DOMAIN_NAME = env('DOMAIN_NAME', default='127.0.0.1:8081') # 'www.partnerreportingportal.org'
DOMAIN_NAME = env('DOMAIN_NAME', default='localhost:8081') # 'www.partnerreportingportal.org'
WWW_ROOT = 'http://%s/' % DOMAIN_NAME
ALLOWED_HOSTS = env('ALLOWED_HOSTS', default='localhost').split(",")

HOST = DOMAIN_NAME

FRONTEND_HOST = env(
'PRP_FRONTEND_HOST',
Expand Down Expand Up @@ -100,9 +102,9 @@
'leaflet',
'django_cron',
'social_django',

'unicef_djangolib',
'unicef_locations',

'unicef_security',
'etools_prp.apps.account',
'etools_prp.apps.cluster',
'etools_prp.apps.core',
Expand All @@ -122,7 +124,7 @@
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'etools_prp.apps.core.mixins.CustomSocialAuthExceptionMiddleware',
'unicef_security.middleware.UNICEFSocialAuthExceptionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
Expand Down Expand Up @@ -423,8 +425,9 @@
SOCIAL_PASSWORD_RESET_POLICY = env('AZURE_B2C_PASS_RESET_POLICY', default="B2C_1_PasswordResetPolicy")
POLICY = env('AZURE_B2C_POLICY_NAME', default="b2c_1A_UNICEF_PARTNERS_signup_signin")

TENANT_ID = env('AZURE_B2C_TENANT', default='unicefpartners')
TENANT_B2C_URL = f'{TENANT_ID}.b2clogin.com'
TENANT_NAME = env('TENANT_NAME', default='unicefpartners')
TENANT_ID = f'{TENANT_NAME}.onmicrosoft.com'
TENANT_B2C_URL = f'{TENANT_NAME}.b2clogin.com'


SCOPE = ['openid', 'email']
Expand All @@ -443,7 +446,7 @@

SOCIAL_AUTH_PIPELINE = (
# 'social_core.pipeline.social_auth.social_details',
'etools_prp.apps.core.mixins.social_details',
'unicef_security.pipeline.social_details',
'social_core.pipeline.social_auth.social_uid',
# allows based on emails being listed in 'WHITELISTED_EMAILS' or 'WHITELISTED_DOMAINS'
'social_core.pipeline.social_auth.auth_allowed',
Expand All @@ -455,7 +458,7 @@
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
# 'social_core.pipeline.user.user_details',
'etools_prp.apps.core.mixins.user_details',
'unicef_security.pipeline.user_details',
)


Expand Down Expand Up @@ -517,7 +520,7 @@
})

AUTHENTICATION_BACKENDS = (
'etools_prp.apps.core.mixins.CustomAzureADBBCOAuth2',
'unicef_security.backends.UNICEFAzureADB2COAuth2',
'django.contrib.auth.backends.ModelBackend',
)

Expand All @@ -543,3 +546,6 @@
DOCS_URL = 'api/docs/'

UNICEF_LOCATIONS_MODEL = 'core.Location'

PROJECT_NAME = etools_prp.NAME
PROJECT_VERSION = etools_prp.VERSION
4 changes: 2 additions & 2 deletions django_api/etools_prp/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from rest_framework_swagger.views import get_swagger_view

from etools_prp.apps.core.views import HomeView, RedirectAppView, SocialLogoutView, UnauthorizedView
from etools_prp.apps.core.views import HomeView, RedirectAppView, UnauthorizedView

schema_view = get_swagger_view(title='eTools PRP API')

Expand All @@ -41,7 +41,7 @@
re_path(r'^api/id-management/', include('etools_prp.apps.id_management.urls')),

# Social auth urls
re_path(r'^social/unicef-logout/', SocialLogoutView.as_view()),
re_path(r'^security/', include('unicef_security.urls')),
re_path(r'^social/', include('social_django.urls', namespace='social')),
re_path(r'^unauthorized/$', UnauthorizedView.as_view(), name="unauthorized"),
]
Expand Down
2 changes: 1 addition & 1 deletion frontend_cluster/src_ts/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const Endpoints = {
},

login() {
return '/social/login/azuread-b2c-oauth2/';
return '/social/login/unicef-azuread-b2c-oauth2/';
},

config() {
Expand Down
2 changes: 1 addition & 1 deletion frontend_ip/src_ts/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const Endpoints = {
},

login() {
return '/social/login/azuread-b2c-oauth2/';
return '/social/login/unicef-azuread-b2c-oauth2/';
},

interventions() {
Expand Down