You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sm...@apache.org on 2020/04/14 18:07:10 UTC
[airavata-custos-portal] 10/14: Added emails for forgot password
and reset password
This is an automated email from the ASF dual-hosted git repository.
smarru pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit 415ecde41b586351fa9d0cfdd07cc87ca96424b3
Author: Shivam Rastogi <sh...@yahoo.com>
AuthorDate: Tue Mar 31 15:31:39 2020 -0400
Added emails for forgot password and reset password
---
custos_portal/custos_portal/apps/auth/backends.py | 1 -
.../auth/migrations/0003_password_reset_request.py | 64 ++++
.../auth/migrations/0004_auto_20200331_1859.py | 18 ++
custos_portal/custos_portal/apps/auth/urls.py | 11 +-
custos_portal/custos_portal/apps/auth/utils.py | 29 ++
custos_portal/custos_portal/apps/auth/views.py | 357 +++++++++++++++------
custos_portal/custos_portal/context_processors.py | 6 -
custos_portal/custos_portal/settings.py | 2 +-
custos_portal/custos_portal/settings_local.py | 4 +-
.../templates/custos_portal/home.html | 5 +-
.../custos_portal_auth/forgot_password.html | 2 +-
.../login_username_password.html | 2 +-
.../partials/username_password_login_form.html | 2 +-
.../custos_portal_auth/reset_password.html | 2 +-
.../templates/custos_portal_auth/verify_email.html | 2 +-
15 files changed, 393 insertions(+), 114 deletions(-)
diff --git a/custos_portal/custos_portal/apps/auth/backends.py b/custos_portal/custos_portal/apps/auth/backends.py
index 2db7af3..33b4c4b 100644
--- a/custos_portal/custos_portal/apps/auth/backends.py
+++ b/custos_portal/custos_portal/apps/auth/backends.py
@@ -21,7 +21,6 @@ class CustosAuthBackend(ModelBackend):
@sensitive_variables('password')
def authenticate(self, request=None, username=None, password=None, refresh_token=None):
try:
- userinfo = None
if username and password:
token = self._get_token_and_userinfo_password_flow(username, password)
request.session["ACCESS_TOKEN"] = token
diff --git a/custos_portal/custos_portal/apps/auth/migrations/0003_password_reset_request.py b/custos_portal/custos_portal/apps/auth/migrations/0003_password_reset_request.py
new file mode 100644
index 0000000..b1f0242
--- /dev/null
+++ b/custos_portal/custos_portal/apps/auth/migrations/0003_password_reset_request.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-05-07 15:49
+from __future__ import unicode_literals
+
+import uuid
+
+from django.db import migrations, models
+
+from custos_portal.apps.auth.models import PASSWORD_RESET_EMAIL_TEMPLATE
+
+
+def default_templates(apps, schema_editor):
+
+ EmailTemplate = apps.get_model("custos_portal_auth", "EmailTemplate")
+ verify_email_template = EmailTemplate(
+ template_type=PASSWORD_RESET_EMAIL_TEMPLATE,
+ subject="{{first_name}} {{last_name}} ({{username}}), "
+ "Reset your password in {{portal_title}}",
+ body="""
+ <p>
+ Dear {{first_name}} {{last_name}},
+ </p>
+
+ <p>
+ Please click the link below to reset your password. This link is
+ valid for 24 hours.
+ </p>
+
+ <p><a href="{{url}}">{{url}}</a></p>
+
+ <p>If you didn't request to reset your password, just ignore this message.</p>
+ """.strip())
+ verify_email_template.save()
+
+
+def delete_default_templates(apps, schema_editor):
+ EmailTemplate = apps.get_model("custos_portal_auth", "EmailTemplate")
+ EmailTemplate.objects.filter(
+ template_type=PASSWORD_RESET_EMAIL_TEMPLATE).delete()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('custos_portal_auth', '0002_default_email_template'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='PasswordResetRequest',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('username', models.CharField(max_length=64)),
+ ('reset_code', models.CharField(default=uuid.uuid4, max_length=36, unique=True)),
+ ('created_date', models.DateTimeField(auto_now_add=True)),
+ ],
+ ),
+ migrations.AlterField(
+ model_name='emailtemplate',
+ name='template_type',
+ field=models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template'), (3, 'Password Reset Email Template')], primary_key=True, serialize=False),
+ ),
+ migrations.RunPython(default_templates, reverse_code=delete_default_templates)
+ ]
diff --git a/custos_portal/custos_portal/apps/auth/migrations/0004_auto_20200331_1859.py b/custos_portal/custos_portal/apps/auth/migrations/0004_auto_20200331_1859.py
new file mode 100644
index 0000000..2bf309b
--- /dev/null
+++ b/custos_portal/custos_portal/apps/auth/migrations/0004_auto_20200331_1859.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.4 on 2020-03-31 18:59
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('custos_portal_auth', '0003_password_reset_request'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='emailtemplate',
+ name='template_type',
+ field=models.IntegerField(choices=[(1, 'Verify Email Template'), (2, 'New User Email Template'), (3, 'Password Reset Email Template'), (4, 'User Added to Group Template')], primary_key=True, serialize=False),
+ ),
+ ]
diff --git a/custos_portal/custos_portal/apps/auth/urls.py b/custos_portal/custos_portal/apps/auth/urls.py
index 623799e..47c1d12 100644
--- a/custos_portal/custos_portal/apps/auth/urls.py
+++ b/custos_portal/custos_portal/apps/auth/urls.py
@@ -6,15 +6,16 @@ from . import views
app_name = 'custos_portal_auth'
urlpatterns = [
path('login/', views.start_login, name='login'),
+ url(r'^login-password$', views.start_username_password_login, name='login_with_password'),
url(r'^redirect_login/(\w+)/$', views.redirect_login, name='redirect_login'),
url(r'^create-account$', views.create_account, name='create_account'),
url(r'^redirect_login/(\w+)/$', views.redirect_login, name='redirect_login'),
url(r'^callback/$', views.callback, name='callback'),
- url(r'^callback-error/(?P<idp_alias>\w+)/$', views.callback_error,
- name='callback-error'),
+ url(r'^callback-error/(?P<idp_alias>\w+)/$', views.callback_error, name='callback-error'),
url(r'handle-login', views.handle_login, name="handle_login"),
url(r'^logout$', views.start_logout, name='logout'),
- url(r'^verify-email/(?P<code>[\w-]+)/$', views.verify_email,
- name="verify_email"),
-
+ url(r'^verify-email/(?P<code>[\w-]+)/$', views.verify_email, name="verify_email"),
+ url(r'^resend-email-link/', views.resend_email_link, name="resend_email_link"),
+ url(r'^forgot-password/$', views.forgot_password, name="forgot_password"),
+ url(r'^reset-password/(?P<code>[\w-]+)/$', views.reset_password, name="reset_password"),
]
diff --git a/custos_portal/custos_portal/apps/auth/utils.py b/custos_portal/custos_portal/apps/auth/utils.py
index a1f5598..df68deb 100644
--- a/custos_portal/custos_portal/apps/auth/utils.py
+++ b/custos_portal/custos_portal/apps/auth/utils.py
@@ -1,5 +1,6 @@
from django.conf import settings
from django.core.mail import EmailMessage
+from django.http.request import split_domain_port
from . import models
from django.template import Context, Template
@@ -23,3 +24,31 @@ def send_email_to_user(template_id, context):
)
msg.content_subtype = 'html'
msg.send()
+
+
+def send_new_user_email(request, username, email, first_name, last_name):
+ """Send new user email notification to portal admins."""
+ new_user_email_template = models.EmailTemplate.objects.get(
+ pk=models.NEW_USER_EMAIL_TEMPLATE)
+ domain, port = split_domain_port(request.get_host())
+ context = Context({
+ "username": username,
+ "email": email,
+ "first_name": first_name,
+ "last_name": last_name,
+ "portal_title": settings.PORTAL_TITLE,
+ "gateway_id": settings.GATEWAY_ID,
+ "http_host": domain,
+ })
+ subject = Template(new_user_email_template.subject).render(context)
+ body = Template(new_user_email_template.body).render(context)
+ msg = EmailMessage(subject=subject,
+ body=body,
+ from_email="{} <{}>".format(
+ settings.PORTAL_TITLE,
+ settings.SERVER_EMAIL),
+ to=[a[1] for a in getattr(settings,
+ 'PORTAL_ADMINS',
+ settings.ADMINS)])
+ msg.content_subtype = 'html'
+ msg.send()
diff --git a/custos_portal/custos_portal/apps/auth/views.py b/custos_portal/custos_portal/apps/auth/views.py
index c806245..ddf0f55 100644
--- a/custos_portal/custos_portal/apps/auth/views.py
+++ b/custos_portal/custos_portal/apps/auth/views.py
@@ -1,18 +1,22 @@
import logging
import json
+from time import timezone
from urllib.parse import quote
+from datetime import datetime, timedelta, timezone
+
-from clients.identity_management_client import IdentityManagementClient
-from clients.user_management_client import UserManagementClient
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
-from django.core.exceptions import ValidationError
+from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.forms import formset_factory, models
+from django.http import HttpResponseBadRequest
from django.shortcuts import render, redirect, resolve_url
from django.template import Context
from django.urls import reverse
from django.utils.http import urlencode
+from django.views.decorators.debug import sensitive_variables
+from google.protobuf.json_format import MessageToDict
from requests_oauthlib import OAuth2Session
from . import utils
@@ -24,48 +28,6 @@ from ... import user_management_client
logger = logging.getLogger(__name__)
-def start_login(request):
- return render(request, 'custos_portal_auth/login.html', {
- 'next': request.GET.get('next', None),
- 'options': settings.AUTHENTICATION_OPTIONS,
- })
-
-
-def redirect_login(request, idp_alias):
- _validate_idp_alias(idp_alias)
-
- client_id = settings.KEYCLOAK_CLIENT_ID
-
- auth_base_url = identity_management_client.get_oidc_configuration(settings.CUSTOS_TOKEN, client_id)
- # auth_base_url = json.loads(auth_base_url.)
- # print(auth_base_url)
- base_authorize_url = settings.KEYCLOAK_AUTHORIZE_URL
-
- redirect_uri = request.build_absolute_uri(
- reverse('custos_portal_auth:callback'))
-
- oauth2_session = OAuth2Session(
- client_id, scope='openid', redirect_uri=redirect_uri)
- authorization_url, state = oauth2_session.authorization_url(
- base_authorize_url)
- authorization_url += '&kc_idp_hint=' + quote("oidc")
-
- # Store state in session for later validation (see backends.py)
- request.session['OAUTH2_STATE'] = state
- request.session['OAUTH2_REDIRECT_URI'] = redirect_uri
-
- logger.debug('Redirect URI: {}'.format(redirect_uri))
- logger.debug('Authorization URL for OpenID: {}'.format(authorization_url))
- return redirect(authorization_url)
-
-
-def _validate_idp_alias(idp_alias):
- external_auth_options = settings.AUTHENTICATION_OPTIONS['external']
- valid_idp_aliases = [ext['idp_alias'] for ext in external_auth_options]
- if idp_alias not in valid_idp_aliases:
- raise Exception("idp_alias is not valid: {}".format(idp_alias))
-
-
def callback(request):
try:
user = authenticate(request=request)
@@ -96,6 +58,110 @@ def callback_error(request, idp_alias):
})
+def create_account(request):
+ if request.method == 'POST':
+ form = forms.CreateAccountForm(request.POST)
+ if form.is_valid():
+ try:
+ username = form.cleaned_data['username']
+ email = form.cleaned_data['email']
+ first_name = form.cleaned_data['first_name']
+ last_name = form.cleaned_data['last_name']
+ password = form.cleaned_data['password']
+ is_temp_password = False
+ result = user_management_client.register_user(settings.CUSTOS_TOKEN, username, first_name, last_name,
+ password, email, is_temp_password)
+ if result.is_registered:
+ logger.debug("User account successfully created for : {}".format(username))
+ _create_and_send_email_verification_link(request, username, email, first_name, last_name,
+ settings.LOGIN_URL)
+ messages.success(
+ request,
+ "Account request processed successfully. Before you "
+ "can login you need to confirm your email address. "
+ "We've sent you an email with a link that you should "
+ "click on to complete the account creation process.")
+ else:
+ form.add_error(None, ValidationError("Failed to register the user with IAM service"))
+ except TypeError as e:
+ logger.exception(
+ "Failed to create account for user", exc_info=e)
+ form.add_error(None, ValidationError(e))
+ return render(request, 'custos_portal_auth/create_account.html', {
+ 'options': settings.AUTHENTICATION_OPTIONS,
+ 'form': form
+ })
+ else:
+ form = forms.CreateAccountForm()
+ return render(request, 'custos_portal_auth/create_account.html', {
+ 'options': settings.AUTHENTICATION_OPTIONS,
+ 'form': form
+ })
+
+
+def forgot_password(request):
+ if request.method == 'POST':
+ form = forms.ForgotPasswordForm(request.POST)
+ if form.is_valid():
+ try:
+ username = form.cleaned_data['username']
+ if not user_management_client.is_username_available(settings.CUSTOS_TOKEN, username).is_exist:
+ if not user_management_client.is_user_enabled(settings.CUSTOS_TOKEN, username).is_exist:
+ messages.error(
+ request,
+ "Please finish creating your account before "
+ "resetting your password. Provide your username "
+ "below and we will send you another email "
+ "verification link.")
+ return redirect(
+ reverse('custos_portal_auth:resend_email_link'))
+ _create_and_send_password_reset_request_link(request, username)
+ # Always display this message even if you doesn't exist. Don't
+ # reveal whether a user with that username exists.
+ messages.success(
+ request,
+ "Reset password request processed successfully. We've "
+ "sent an email with a password reset link to the email "
+ "address associated with the username you provided. You "
+ "can use that link within the next 24 hours to set a new "
+ "password.")
+ return redirect(
+ reverse('custos_portal_auth:forgot_password'))
+ except Exception as e:
+ logger.exception(
+ "Failed to generate password reset request for user",
+ exc_info=e)
+ form.add_error(None, ValidationError(str(e)))
+ else:
+ form = forms.ForgotPasswordForm()
+ return render(request, 'custos_portal_auth/forgot_password.html', {
+ 'form': form
+ })
+
+
+def _create_and_send_password_reset_request_link(request, username):
+ password_reset_request = models.PasswordResetRequest(username=username)
+ password_reset_request.save()
+
+ verification_uri = request.build_absolute_uri(
+ reverse(
+ 'custos_portal_auth:reset_password', kwargs={
+ 'code': password_reset_request.reset_code}))
+ logger.debug(
+ "password reset verification_uri={}".format(verification_uri))
+
+ user = user_management_client.get_user(settings.CUSTOS_TOKEN, username)
+ context = Context({
+ "username": username,
+ "email": user.email,
+ "first_name": user.first_name,
+ "last_name": user.last_name,
+ "portal_title": settings.PORTAL_TITLE,
+ "url": verification_uri,
+ })
+ utils.send_email_to_user(models.PASSWORD_RESET_EMAIL_TEMPLATE, context)
+
+
def handle_login(request):
username = request.POST['username']
password = request.POST['password']
@@ -122,61 +188,153 @@ def handle_login(request):
})
-def _handle_login_redirect(request):
- if request.is_gateway_admin:
- return redirect(reverse('custos_portal_admin:list_requests'))
- else:
- return redirect(reverse('custos_portal_workspace:list_requests'))
+def redirect_login(request, idp_alias):
+ _validate_idp_alias(idp_alias)
+ client_id = settings.KEYCLOAK_CLIENT_ID
-def start_logout(request):
- logout(request)
- redirect_url = request.build_absolute_uri(resolve_url(settings.LOGOUT_REDIRECT_URL))
- return redirect(settings.KEYCLOAK_LOGOUT_URL + "?redirect_uri=" + quote(redirect_url))
+ auth_base_url = identity_management_client.get_oidc_configuration(settings.CUSTOS_TOKEN, client_id)
+ # auth_base_url = json.loads(auth_base_url.)
+ # print(auth_base_url)
+ base_authorize_url = settings.KEYCLOAK_AUTHORIZE_URL
+ redirect_uri = request.build_absolute_uri(
+ reverse('custos_portal_auth:callback'))
-def create_account(request):
+ oauth2_session = OAuth2Session(
+ client_id, scope='openid', redirect_uri=redirect_uri)
+ authorization_url, state = oauth2_session.authorization_url(
+ base_authorize_url)
+ authorization_url += '&kc_idp_hint=' + quote("oidc")
+
+ # Store state in session for later validation (see backends.py)
+ request.session['OAUTH2_STATE'] = state
+ request.session['OAUTH2_REDIRECT_URI'] = redirect_uri
+
+ logger.debug('Redirect URI: {}'.format(redirect_uri))
+ logger.debug('Authorization URL for OpenID: {}'.format(authorization_url))
+ return redirect(authorization_url)
+
+
+def resend_email_link(request):
if request.method == 'POST':
- form = forms.CreateAccountForm(request.POST)
+ form = forms.ResendEmailVerificationLinkForm(request.POST)
if form.is_valid():
try:
username = form.cleaned_data['username']
- email = form.cleaned_data['email']
- first_name = form.cleaned_data['first_name']
- last_name = form.cleaned_data['last_name']
- password = form.cleaned_data['password']
- is_temp_password = True
- result = user_management_client.register_user(settings.CUSTOS_TOKEN, username, first_name, last_name,
- password, email, is_temp_password)
- if result.is_registered:
- logger.debug("User account successfully created for : {}".format(username))
- _create_and_send_email_verification_link(request, username, email, first_name, last_name, next)
+ if not user_management_client.is_username_available(settings.CUSTOS_TOKEN, username).is_exist:
+ user_profile = user_management_client.get_user(settings.CUSTOS_TOKEN, username)
+ print(user_profile)
+ _create_and_send_email_verification_link(
+ request,
+ username,
+ user_profile.email,
+ user_profile.first_name,
+ user_profile.last_name,
+ settings.LOGIN_URL)
messages.success(
request,
- "Account request processed successfully. Before you "
- "can login you need to confirm your email address. "
- "We've sent you an email with a link that you should "
- "click on to complete the account creation process.")
+ "Email verification link sent successfully. Please "
+ "click on the link in the email that we sent "
+ "to your email address.")
else:
- form.add_error(None, ValidationError("Failed to register the user with IAM service"))
- except TypeError as e:
+ messages.error(
+ request,
+ "Unable to resend email verification link. Please "
+ "contact the website administrator for further "
+ "assistance.")
+ return redirect(
+ reverse('custos_portal_auth:resend_email_link'))
+ except Exception as e:
logger.exception(
- "Failed to create account for user", exc_info=e)
- form.add_error(None, ValidationError(e))
- return render(request, 'custos_portal_auth/create_account.html', {
- 'options': settings.AUTHENTICATION_OPTIONS,
- 'form': form
- })
+ "Failed to resend email verification link", exc_info=e)
+ form.add_error(None, ValidationError(str(e)))
else:
- form = forms.CreateAccountForm()
- return render(request, 'custos_portal_auth/create_account.html', {
- 'options': settings.AUTHENTICATION_OPTIONS,
+ form = forms.ResendEmailVerificationLinkForm()
+ return render(request, 'custos_portal_auth/verify_email.html', {
'form': form
})
-def verify_email(request, code):
+@sensitive_variables('password')
+def reset_password(request, code):
+ try:
+ password_reset_request = models.PasswordResetRequest.objects.get(
+ reset_code=code)
+ except ObjectDoesNotExist as e:
+ messages.error(
+ request,
+ "Reset password link is invalid. Please try again.")
+ return redirect(reverse('custos_portal_auth:forgot_password'))
+
+ now = datetime.now(timezone.utc)
+ if now - password_reset_request.created_date > timedelta(days=1):
+ password_reset_request.delete()
+ messages.error(
+ request,
+ "Reset password link has expired. Please try again.")
+ return redirect(reverse('custos_portal_auth:forgot_password'))
+
+ if request.method == "POST":
+ form = forms.ResetPasswordForm(request.POST)
+ if form.is_valid():
+ try:
+ password = form.cleaned_data['password']
+ # TODO Password is not updating properly
+ success = user_management_client.reset_password(settings.CUSTOS_TOKEN, password_reset_request.username,
+ password)
+ logger.debug("Password reset result: {}".format(success))
+ if not success:
+ messages.error(
+ request, "Failed to reset password. Please try again.")
+ return redirect(
+ reverse('custos_portal_auth:forgot_password'))
+ else:
+ password_reset_request.delete()
+ messages.success(
+ request,
+ "You may now log in with your new password.")
+ return redirect(
+ reverse('custos_portal_auth:login_with_password'))
+ except Exception as e:
+ logger.exception(
+ "Failed to reset password for user", exc_info=e)
+ form.add_error(None, ValidationError(str(e)))
+ else:
+ form = forms.ResetPasswordForm()
+ return render(request, 'custos_portal_auth/reset_password.html', {
+ 'form': form,
+ 'code': code
+ })
+
+
+def start_login(request):
+ return render(request, 'custos_portal_auth/login.html', {
+ 'next': request.GET.get('next', None),
+ 'options': settings.AUTHENTICATION_OPTIONS,
+ })
+
+def start_logout(request):
+ logout(request)
+ redirect_url = request.build_absolute_uri(resolve_url(settings.LOGOUT_REDIRECT_URL))
+ return redirect(settings.KEYCLOAK_LOGOUT_URL + "?redirect_uri=" + quote(redirect_url))
+
+
+def start_username_password_login(request):
+ # return bad request if password isn't a configured option
+ if 'password' not in settings.AUTHENTICATION_OPTIONS:
+ return HttpResponseBadRequest("Username/password login is not enabled")
+ return render(request,
+ 'custos_portal_auth/login_username_password.html',
+ {
+ 'next': request.GET.get('next', None),
+ 'options': settings.AUTHENTICATION_OPTIONS,
+ 'login_type': 'password'
+ })
+
+
+def verify_email(request, code):
try:
email_verification = models.EmailVerification.objects.get(verification_code=code)
email_verification.verified = True
@@ -187,7 +345,9 @@ def verify_email(request, code):
login_url = reverse('custos_portal_auth:login')
if email_verification.next:
login_url += "?" + urlencode({'next': email_verification.next})
- if iam_admin_client.is_user_enabled(username):
+
+ print(user_management_client.is_user_enabled(settings.CUSTOS_TOKEN, "shivam_testing_3"))
+ if user_management_client.is_user_enabled(settings.CUSTOS_TOKEN, username).is_exist:
logger.debug("User {} is already enabled".format(username))
messages.success(
request,
@@ -197,11 +357,11 @@ def verify_email(request, code):
else:
logger.debug("Enabling user {}".format(username))
# enable user and inform admins
- iam_admin_client.enable_user(username)
- user_profile = iam_admin_client.get_user(username)
- email_address = user_profile.emails[0]
- first_name = user_profile.firstName
- last_name = user_profile.lastName
+ user_profile = MessageToDict(user_management_client.enable_user(settings.CUSTOS_TOKEN, username))
+ logger.debug(user_profile)
+ email_address = user_profile["email"]
+ first_name = user_profile["firstName"]
+ last_name = user_profile["lastName"]
utils.send_new_user_email(request,
username,
email_address,
@@ -221,18 +381,17 @@ def verify_email(request, code):
request,
"Email verification failed. Please enter your username and we "
"will send you another email verification link.")
- return redirect(reverse('django_airavata_auth:resend_email_link'))
+ return redirect(reverse('custos_portal_auth:resend_email_link'))
except Exception as e:
logger.exception("Email verification processing failed!")
messages.error(
request,
"Email verification failed. Please try clicking the email "
"verification link again later.")
- return redirect(reverse('django_airavata_auth:create_account'))
-
+ return redirect(reverse('custos_portal_auth:create_account'))
-def _create_and_send_email_verification_link(request, username, email, first_name, last_name, next_url):
+def _create_and_send_email_verification_link(request, username, email, first_name, last_name, next_url=None):
email_verification = models.EmailVerification(username=username, next=next_url)
email_verification.save()
@@ -250,3 +409,17 @@ def _create_and_send_email_verification_link(request, username, email, first_nam
"url": verification_uri,
})
utils.send_email_to_user(models.VERIFY_EMAIL_TEMPLATE, context)
+
+
+def _validate_idp_alias(idp_alias):
+ external_auth_options = settings.AUTHENTICATION_OPTIONS['external']
+ valid_idp_aliases = [ext['idp_alias'] for ext in external_auth_options]
+ if idp_alias not in valid_idp_aliases:
+ raise Exception("idp_alias is not valid: {}".format(idp_alias))
+
+
+def _handle_login_redirect(request):
+ if request.is_gateway_admin:
+ return redirect(reverse('custos_portal_admin:list_requests'))
+ else:
+ return redirect(reverse('custos_portal_workspace:list_requests'))
diff --git a/custos_portal/custos_portal/context_processors.py b/custos_portal/custos_portal/context_processors.py
index e9e48ae..d1f4fd4 100644
--- a/custos_portal/custos_portal/context_processors.py
+++ b/custos_portal/custos_portal/context_processors.py
@@ -31,12 +31,6 @@ def airavata_app_registry(request):
if isinstance(app, CustosAppConfig) and
(app.app_enabled(request)
)]
- for app in apps.get_app_configs():
- if isinstance(app, CustosAppConfig):
- print(app.url_app_name)
- print(getattr(app, 'enabled', None))
- print(app.app_enabled(request))
- print("Custos apps", airavata_apps)
# Sort by app_order then by verbose_name (case-insensitive)
airavata_apps.sort(
key=lambda app: "{:09}-{}".format(app.app_order,
diff --git a/custos_portal/custos_portal/settings.py b/custos_portal/custos_portal/settings.py
index 188b2b4..960825b 100644
--- a/custos_portal/custos_portal/settings.py
+++ b/custos_portal/custos_portal/settings.py
@@ -126,7 +126,7 @@ STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "custos_portal", "static")]
LOGIN_URL = 'custos_portal_auth:login'
-LOGIN_REDIRECT_URL = 'django_airavata_workspace:dashboard'
+LOGIN_REDIRECT_URL = 'custos_portal_auth:dashboard'
LOGOUT_REDIRECT_URL = '/'
AUTHENTICATION_OPTIONS = {
diff --git a/custos_portal/custos_portal/settings_local.py b/custos_portal/custos_portal/settings_local.py
index 383a3d5..81b94ae 100644
--- a/custos_portal/custos_portal/settings_local.py
+++ b/custos_portal/custos_portal/settings_local.py
@@ -18,10 +18,9 @@ KEYCLOAK_AUTHORIZE_URL = 'https://keycloak.custos.scigap.org:31000/auth/realms/1
KEYCLOAK_TOKEN_URL = 'https://airavata.host:8443/auth/realms/default/protocol/openid-connect/token'
KEYCLOAK_LOGOUT_URL = 'https://keycloak.custos.scigap.org:31000/auth/realms/10000101/protocol/openid-connect/logout'
# Optional: specify if using self-signed certificate or certificate from unrecognized CA
-#KEYCLOAK_CA_CERTFILE = os.path.join(BASE_DIR, "django_airavata", "resources", "incommon_rsa_server_ca.pem")
+# KEYCLOAK_CA_CERTFILE = os.path.join(BASE_DIR, "django_airavata", "resources", "incommon_rsa_server_ca.pem")
KEYCLOAK_VERIFY_SSL = False
-
SESSION_COOKIE_SECURE = False
# Default email backend (for local development)
@@ -42,3 +41,4 @@ ADMINS = [('Admin Name', 'admin@example.com')]
# Portal settings
PORTAL_TITLE = 'Custos Admin Portal'
+GATEWAY_ID = 'Custos Portal'
diff --git a/custos_portal/custos_portal/templates/custos_portal/home.html b/custos_portal/custos_portal/templates/custos_portal/home.html
index d413ceb..a22b3d8 100644
--- a/custos_portal/custos_portal/templates/custos_portal/home.html
+++ b/custos_portal/custos_portal/templates/custos_portal/home.html
@@ -6,10 +6,11 @@
<div class="container">
<div class="jumbotron">
<h1>Welcome!</h1>
- <p>This is the Django based web portal for Custos Admin.</p>
+ <p>This is the Django based web portal for Custos.</p>
+ {% if not user.is_authenticated %}
<p><a class="btn btn-primary btn-lg" href="{% url 'custos_portal_auth:login' %}" role="button">Login ยป</a></p>
<p><a class="btn btn-primary btn-lg" href="{% url 'custos_portal_auth:create_account' %}" role="button">Register</a></p>
-
+ {% endif %}
</div>
{% if user.is_authenticated %}
<div class="row">
diff --git a/custos_portal/custos_portal/templates/custos_portal_auth/forgot_password.html b/custos_portal/custos_portal/templates/custos_portal_auth/forgot_password.html
index 30524ab..d40d14f 100644
--- a/custos_portal/custos_portal/templates/custos_portal_auth/forgot_password.html
+++ b/custos_portal/custos_portal/templates/custos_portal_auth/forgot_password.html
@@ -12,7 +12,7 @@
<h5 class="card-title">Forgot Password?</h5>
<p class="card-text">If you forgot your password you can reset it. Just enter the username for your account and click Email Reset Link.</p>
{% include "./partials/messages.html" %}
- {% url 'django_airavata_auth:forgot_password' as form_url %}
+ {% url 'custos_portal_auth:forgot_password' as form_url %}
{% include "./partials/form.html" with form=form url=form_url submit_text="Email Reset Link" %}
</div>
</div>
diff --git a/custos_portal/custos_portal/templates/custos_portal_auth/login_username_password.html b/custos_portal/custos_portal/templates/custos_portal_auth/login_username_password.html
index 84d2b5f..b948768 100644
--- a/custos_portal/custos_portal/templates/custos_portal_auth/login_username_password.html
+++ b/custos_portal/custos_portal/templates/custos_portal_auth/login_username_password.html
@@ -9,7 +9,7 @@
<div class="row">
<div class="col">
<p>
- <small>See <a href="{% url 'django_airavata_auth:login' %}" class="text-muted">all login options</small>
+ <small>See <a href="{% url 'custos_portal_auth:login' %}" class="text-muted">all login options</small>
</p>
</div>
</div>
diff --git a/custos_portal/custos_portal/templates/custos_portal_auth/partials/username_password_login_form.html b/custos_portal/custos_portal/templates/custos_portal_auth/partials/username_password_login_form.html
index e2ca5b3..9b4ceef 100644
--- a/custos_portal/custos_portal/templates/custos_portal_auth/partials/username_password_login_form.html
+++ b/custos_portal/custos_portal/templates/custos_portal_auth/partials/username_password_login_form.html
@@ -13,7 +13,7 @@
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password" required>
- <small class="form-text text-muted"><a href="#}" class="text-reset">Forgot your password?</a></small>
+ <small class="form-text text-muted"><a href="{% url 'custos_portal_auth:forgot_password' %}" class="text-reset">Forgot your password?</a></small>
</div>
{% if next %}
<input type="hidden" name="next" value="{{ next }}"/>
diff --git a/custos_portal/custos_portal/templates/custos_portal_auth/reset_password.html b/custos_portal/custos_portal/templates/custos_portal_auth/reset_password.html
index 4227153..196ea0f 100644
--- a/custos_portal/custos_portal/templates/custos_portal_auth/reset_password.html
+++ b/custos_portal/custos_portal/templates/custos_portal_auth/reset_password.html
@@ -11,7 +11,7 @@
<div class="card-body">
<h5 class="card-title">Reset Password</h5>
{% include "./partials/messages.html" %}
- {% url 'django_airavata_auth:reset_password' code as form_url %}
+ {% url 'custos_portal_auth:reset_password' code as form_url %}
{% include "./partials/form.html" with form=form url=form_url submit_text="Reset Password" %}
</div>
</div>
diff --git a/custos_portal/custos_portal/templates/custos_portal_auth/verify_email.html b/custos_portal/custos_portal/templates/custos_portal_auth/verify_email.html
index 537d970..32e9753 100644
--- a/custos_portal/custos_portal/templates/custos_portal_auth/verify_email.html
+++ b/custos_portal/custos_portal/templates/custos_portal_auth/verify_email.html
@@ -10,7 +10,7 @@
<div class="card-body">
<h5 class="card-title">Resend Email Verification Link</h5>
{% include "./partials/messages.html" %}
- {% url 'django_airavata_auth:resend_email_link' code as form_url %}
+ {% url 'custos_portal_auth:resend_email_link' code as form_url %}
{% include "./partials/form.html" with form=form url=form_url submit_text="Resend" %}
</div>
</div>