You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2018/10/31 17:48:20 UTC
[airavata-django-portal] 06/09: AIRAVATA-2888 Resend email
verification link form
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit e1c22616d7ead16f5f45db10f8947038b2b1672c
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Fri Oct 26 17:03:45 2018 -0400
AIRAVATA-2888 Resend email verification link form
---
.../iam/admin/services/cpi/IamAdminServices-remote | 14 +
.../iam/admin/services/cpi/IamAdminServices.py | 467 +++++++++++++++++++++
django_airavata/apps/auth/forms.py | 10 +
django_airavata/apps/auth/iam_admin_client.py | 12 +
.../django_airavata_auth/verify_email.html | 51 +++
django_airavata/apps/auth/urls.py | 2 +
django_airavata/apps/auth/views.py | 78 +++-
django_airavata/utils.py | 10 +-
8 files changed, 623 insertions(+), 21 deletions(-)
diff --git a/airavata/service/profile/iam/admin/services/cpi/IamAdminServices-remote b/airavata/service/profile/iam/admin/services/cpi/IamAdminServices-remote
index 683c411..c164ce1 100755
--- a/airavata/service/profile/iam/admin/services/cpi/IamAdminServices-remote
+++ b/airavata/service/profile/iam/admin/services/cpi/IamAdminServices-remote
@@ -30,6 +30,8 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print(' bool registerUser(AuthzToken authzToken, string username, string emailAddress, string firstName, string lastName, string newPassword)')
print(' bool enableUser(AuthzToken authzToken, string username)')
print(' bool isUserEnabled(AuthzToken authzToken, string username)')
+ print(' bool isUserExist(AuthzToken authzToken, string username)')
+ print(' UserProfile getUser(AuthzToken authzToken, string username)')
print(' bool resetUserPassword(AuthzToken authzToken, string username, string newPassword)')
print(' findUsers(AuthzToken authzToken, string email, string userId)')
print(' void updateUserProfile(AuthzToken authzToken, UserProfile userDetails)')
@@ -151,6 +153,18 @@ elif cmd == 'isUserEnabled':
sys.exit(1)
pp.pprint(client.isUserEnabled(eval(args[0]), args[1],))
+elif cmd == 'isUserExist':
+ if len(args) != 2:
+ print('isUserExist requires 2 args')
+ sys.exit(1)
+ pp.pprint(client.isUserExist(eval(args[0]), args[1],))
+
+elif cmd == 'getUser':
+ if len(args) != 2:
+ print('getUser requires 2 args')
+ sys.exit(1)
+ pp.pprint(client.getUser(eval(args[0]), args[1],))
+
elif cmd == 'resetUserPassword':
if len(args) != 3:
print('resetUserPassword requires 3 args')
diff --git a/airavata/service/profile/iam/admin/services/cpi/IamAdminServices.py b/airavata/service/profile/iam/admin/services/cpi/IamAdminServices.py
index 58b46fe..dae59b5 100644
--- a/airavata/service/profile/iam/admin/services/cpi/IamAdminServices.py
+++ b/airavata/service/profile/iam/admin/services/cpi/IamAdminServices.py
@@ -67,6 +67,22 @@ class Iface(object):
"""
pass
+ def isUserExist(self, authzToken, username):
+ """
+ Parameters:
+ - authzToken
+ - username
+ """
+ pass
+
+ def getUser(self, authzToken, username):
+ """
+ Parameters:
+ - authzToken
+ - username
+ """
+ pass
+
def resetUserPassword(self, authzToken, username, newPassword):
"""
Parameters:
@@ -355,6 +371,80 @@ class Client(Iface):
raise result.ae
raise TApplicationException(TApplicationException.MISSING_RESULT, "isUserEnabled failed: unknown result")
+ def isUserExist(self, authzToken, username):
+ """
+ Parameters:
+ - authzToken
+ - username
+ """
+ self.send_isUserExist(authzToken, username)
+ return self.recv_isUserExist()
+
+ def send_isUserExist(self, authzToken, username):
+ self._oprot.writeMessageBegin('isUserExist', TMessageType.CALL, self._seqid)
+ args = isUserExist_args()
+ args.authzToken = authzToken
+ args.username = username
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_isUserExist(self):
+ iprot = self._iprot
+ (fname, mtype, rseqid) = iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(iprot)
+ iprot.readMessageEnd()
+ raise x
+ result = isUserExist_result()
+ result.read(iprot)
+ iprot.readMessageEnd()
+ if result.success is not None:
+ return result.success
+ if result.Idse is not None:
+ raise result.Idse
+ if result.ae is not None:
+ raise result.ae
+ raise TApplicationException(TApplicationException.MISSING_RESULT, "isUserExist failed: unknown result")
+
+ def getUser(self, authzToken, username):
+ """
+ Parameters:
+ - authzToken
+ - username
+ """
+ self.send_getUser(authzToken, username)
+ return self.recv_getUser()
+
+ def send_getUser(self, authzToken, username):
+ self._oprot.writeMessageBegin('getUser', TMessageType.CALL, self._seqid)
+ args = getUser_args()
+ args.authzToken = authzToken
+ args.username = username
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_getUser(self):
+ iprot = self._iprot
+ (fname, mtype, rseqid) = iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(iprot)
+ iprot.readMessageEnd()
+ raise x
+ result = getUser_result()
+ result.read(iprot)
+ iprot.readMessageEnd()
+ if result.success is not None:
+ return result.success
+ if result.Idse is not None:
+ raise result.Idse
+ if result.ae is not None:
+ raise result.ae
+ raise TApplicationException(TApplicationException.MISSING_RESULT, "getUser failed: unknown result")
+
def resetUserPassword(self, authzToken, username, newPassword):
"""
Parameters:
@@ -594,6 +684,8 @@ class Processor(Iface, TProcessor):
self._processMap["registerUser"] = Processor.process_registerUser
self._processMap["enableUser"] = Processor.process_enableUser
self._processMap["isUserEnabled"] = Processor.process_isUserEnabled
+ self._processMap["isUserExist"] = Processor.process_isUserExist
+ self._processMap["getUser"] = Processor.process_getUser
self._processMap["resetUserPassword"] = Processor.process_resetUserPassword
self._processMap["findUsers"] = Processor.process_findUsers
self._processMap["updateUserProfile"] = Processor.process_updateUserProfile
@@ -766,6 +858,56 @@ class Processor(Iface, TProcessor):
oprot.writeMessageEnd()
oprot.trans.flush()
+ def process_isUserExist(self, seqid, iprot, oprot):
+ args = isUserExist_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = isUserExist_result()
+ try:
+ result.success = self._handler.isUserExist(args.authzToken, args.username)
+ msg_type = TMessageType.REPLY
+ except (TTransport.TTransportException, KeyboardInterrupt, SystemExit):
+ raise
+ except airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+ msg_type = TMessageType.REPLY
+ result.Idse = Idse
+ except airavata.api.error.ttypes.AuthorizationException as ae:
+ msg_type = TMessageType.REPLY
+ result.ae = ae
+ except Exception as ex:
+ msg_type = TMessageType.EXCEPTION
+ logging.exception(ex)
+ result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+ oprot.writeMessageBegin("isUserExist", msg_type, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
+ def process_getUser(self, seqid, iprot, oprot):
+ args = getUser_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = getUser_result()
+ try:
+ result.success = self._handler.getUser(args.authzToken, args.username)
+ msg_type = TMessageType.REPLY
+ except (TTransport.TTransportException, KeyboardInterrupt, SystemExit):
+ raise
+ except airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException as Idse:
+ msg_type = TMessageType.REPLY
+ result.Idse = Idse
+ except airavata.api.error.ttypes.AuthorizationException as ae:
+ msg_type = TMessageType.REPLY
+ result.ae = ae
+ except Exception as ex:
+ msg_type = TMessageType.EXCEPTION
+ logging.exception(ex)
+ result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+ oprot.writeMessageBegin("getUser", msg_type, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
def process_resetUserPassword(self, seqid, iprot, oprot):
args = resetUserPassword_args()
args.read(iprot)
@@ -1935,6 +2077,331 @@ class isUserEnabled_result(object):
return not (self == other)
+class isUserExist_args(object):
+ """
+ Attributes:
+ - authzToken
+ - username
+ """
+
+ thrift_spec = (
+ None, # 0
+ (1, TType.STRUCT, 'authzToken', (airavata.model.security.ttypes.AuthzToken, airavata.model.security.ttypes.AuthzToken.thrift_spec), None, ), # 1
+ (2, TType.STRING, 'username', 'UTF8', None, ), # 2
+ )
+
+ def __init__(self, authzToken=None, username=None,):
+ self.authzToken = authzToken
+ self.username = username
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 1:
+ if ftype == TType.STRUCT:
+ self.authzToken = airavata.model.security.ttypes.AuthzToken()
+ self.authzToken.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.STRING:
+ self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
+ return
+ oprot.writeStructBegin('isUserExist_args')
+ if self.authzToken is not None:
+ oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+ self.authzToken.write(oprot)
+ oprot.writeFieldEnd()
+ if self.username is not None:
+ oprot.writeFieldBegin('username', TType.STRING, 2)
+ oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ if self.authzToken is None:
+ raise TProtocolException(message='Required field authzToken is unset!')
+ if self.username is None:
+ raise TProtocolException(message='Required field username is unset!')
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
+
+
+class isUserExist_result(object):
+ """
+ Attributes:
+ - success
+ - Idse
+ - ae
+ """
+
+ thrift_spec = (
+ (0, TType.BOOL, 'success', None, None, ), # 0
+ (1, TType.STRUCT, 'Idse', (airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException.thrift_spec), None, ), # 1
+ (2, TType.STRUCT, 'ae', (airavata.api.error.ttypes.AuthorizationException, airavata.api.error.ttypes.AuthorizationException.thrift_spec), None, ), # 2
+ )
+
+ def __init__(self, success=None, Idse=None, ae=None,):
+ self.success = success
+ self.Idse = Idse
+ self.ae = ae
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 0:
+ if ftype == TType.BOOL:
+ self.success = iprot.readBool()
+ else:
+ iprot.skip(ftype)
+ elif fid == 1:
+ if ftype == TType.STRUCT:
+ self.Idse = airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+ self.Idse.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.STRUCT:
+ self.ae = airavata.api.error.ttypes.AuthorizationException()
+ self.ae.read(iprot)
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
+ return
+ oprot.writeStructBegin('isUserExist_result')
+ if self.success is not None:
+ oprot.writeFieldBegin('success', TType.BOOL, 0)
+ oprot.writeBool(self.success)
+ oprot.writeFieldEnd()
+ if self.Idse is not None:
+ oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+ self.Idse.write(oprot)
+ oprot.writeFieldEnd()
+ if self.ae is not None:
+ oprot.writeFieldBegin('ae', TType.STRUCT, 2)
+ self.ae.write(oprot)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
+
+
+class getUser_args(object):
+ """
+ Attributes:
+ - authzToken
+ - username
+ """
+
+ thrift_spec = (
+ None, # 0
+ (1, TType.STRUCT, 'authzToken', (airavata.model.security.ttypes.AuthzToken, airavata.model.security.ttypes.AuthzToken.thrift_spec), None, ), # 1
+ (2, TType.STRING, 'username', 'UTF8', None, ), # 2
+ )
+
+ def __init__(self, authzToken=None, username=None,):
+ self.authzToken = authzToken
+ self.username = username
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 1:
+ if ftype == TType.STRUCT:
+ self.authzToken = airavata.model.security.ttypes.AuthzToken()
+ self.authzToken.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.STRING:
+ self.username = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
+ return
+ oprot.writeStructBegin('getUser_args')
+ if self.authzToken is not None:
+ oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+ self.authzToken.write(oprot)
+ oprot.writeFieldEnd()
+ if self.username is not None:
+ oprot.writeFieldBegin('username', TType.STRING, 2)
+ oprot.writeString(self.username.encode('utf-8') if sys.version_info[0] == 2 else self.username)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ if self.authzToken is None:
+ raise TProtocolException(message='Required field authzToken is unset!')
+ if self.username is None:
+ raise TProtocolException(message='Required field username is unset!')
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
+
+
+class getUser_result(object):
+ """
+ Attributes:
+ - success
+ - Idse
+ - ae
+ """
+
+ thrift_spec = (
+ (0, TType.STRUCT, 'success', (airavata.model.user.ttypes.UserProfile, airavata.model.user.ttypes.UserProfile.thrift_spec), None, ), # 0
+ (1, TType.STRUCT, 'Idse', (airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException, airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException.thrift_spec), None, ), # 1
+ (2, TType.STRUCT, 'ae', (airavata.api.error.ttypes.AuthorizationException, airavata.api.error.ttypes.AuthorizationException.thrift_spec), None, ), # 2
+ )
+
+ def __init__(self, success=None, Idse=None, ae=None,):
+ self.success = success
+ self.Idse = Idse
+ self.ae = ae
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 0:
+ if ftype == TType.STRUCT:
+ self.success = airavata.model.user.ttypes.UserProfile()
+ self.success.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 1:
+ if ftype == TType.STRUCT:
+ self.Idse = airavata.service.profile.iam.admin.services.cpi.error.ttypes.IamAdminServicesException()
+ self.Idse.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.STRUCT:
+ self.ae = airavata.api.error.ttypes.AuthorizationException()
+ self.ae.read(iprot)
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
+ return
+ oprot.writeStructBegin('getUser_result')
+ if self.success is not None:
+ oprot.writeFieldBegin('success', TType.STRUCT, 0)
+ self.success.write(oprot)
+ oprot.writeFieldEnd()
+ if self.Idse is not None:
+ oprot.writeFieldBegin('Idse', TType.STRUCT, 1)
+ self.Idse.write(oprot)
+ oprot.writeFieldEnd()
+ if self.ae is not None:
+ oprot.writeFieldBegin('ae', TType.STRUCT, 2)
+ self.ae.write(oprot)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
+
+
class resetUserPassword_args(object):
"""
Attributes:
diff --git a/django_airavata/apps/auth/forms.py b/django_airavata/apps/auth/forms.py
index 1077e58..9569af3 100644
--- a/django_airavata/apps/auth/forms.py
+++ b/django_airavata/apps/auth/forms.py
@@ -87,3 +87,13 @@ class CreateAccountForm(forms.Form):
)
return cleaned_data
+
+
+class ResendEmailVerificationLinkForm(forms.Form):
+ error_css_class = "is-invalid"
+ username = forms.CharField(
+ label='Username',
+ widget=forms.TextInput(attrs={'class': 'form-control',
+ 'placeholder': 'Username'}),
+ min_length=6,
+ validators=[USERNAME_VALIDATOR])
diff --git a/django_airavata/apps/auth/iam_admin_client.py b/django_airavata/apps/auth/iam_admin_client.py
index 7c0aec1..6877d8a 100644
--- a/django_airavata/apps/auth/iam_admin_client.py
+++ b/django_airavata/apps/auth/iam_admin_client.py
@@ -39,3 +39,15 @@ def enable_user(username):
with get_iam_admin_client() as iam_admin_client:
authz_token = utils.get_service_account_authz_token()
return iam_admin_client.enableUser(authz_token, username)
+
+
+def is_user_exist(username):
+ with get_iam_admin_client() as iam_admin_client:
+ authz_token = utils.get_service_account_authz_token()
+ return iam_admin_client.isUserExist(authz_token, username)
+
+
+def get_user(username):
+ with get_iam_admin_client() as iam_admin_client:
+ authz_token = utils.get_service_account_authz_token()
+ return iam_admin_client.getUser(authz_token, username)
diff --git a/django_airavata/apps/auth/templates/django_airavata_auth/verify_email.html b/django_airavata/apps/auth/templates/django_airavata_auth/verify_email.html
new file mode 100644
index 0000000..d737105
--- /dev/null
+++ b/django_airavata/apps/auth/templates/django_airavata_auth/verify_email.html
@@ -0,0 +1,51 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+<div class="container">
+ <div class="row">
+ <div class="col">
+ <div class="card">
+ <div class="card-body">
+ <h5 class="card-title">Resend Email Verification Link</h5>
+ <form action="{% url 'django_airavata_auth:resend_email_link' %}" method="post">
+ {% for error in form.non_field_errors %}
+ <div class="alert alert-danger" role="alert">
+ {{ error }}
+ </div>
+ {% endfor %}
+ {% csrf_token %}
+
+ {% for field in form %}
+ <div class="form-group">
+ <label for="{{ field.id_for_label }}">{{ field.label }}</label>
+ <input id="{{ field.id_for_label }}" type="{{ field.field.widget.input_type }}"
+ class="form-control{% if field.errors %} is-invalid{% endif %}" name="{{ field.name }}"
+ placeholder="{{ field.field.widget.attrs.placeholder }}"
+ {% if field.value %} value="{{ field.value }}" {% endif %}
+ {% if field.field.required %} required {% endif %} />
+ <div class="invalid-feedback">
+ {% if field.errors|length == 1 %}
+ {{ field.errors|first| escape }}
+ {% else %}
+ <ul>
+ {% for error in field.errors %}
+ <li>{{ error | escape }}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+ </div>
+ {% endfor %}
+
+ <button type="submit" class="btn btn-primary btn-block">
+ Resend
+ </button>
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+{% endblock %}
diff --git a/django_airavata/apps/auth/urls.py b/django_airavata/apps/auth/urls.py
index 5d54b76..66011f0 100644
--- a/django_airavata/apps/auth/urls.py
+++ b/django_airavata/apps/auth/urls.py
@@ -15,4 +15,6 @@ urlpatterns = [
url(r'^create-account$', views.create_account, name='create_account'),
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"),
]
diff --git a/django_airavata/apps/auth/views.py b/django_airavata/apps/auth/views.py
index 9626721..271881b 100644
--- a/django_airavata/apps/auth/views.py
+++ b/django_airavata/apps/auth/views.py
@@ -111,25 +111,8 @@ def create_account(request):
form.add_error(None, ValidationError(
"Failed to register user with IAM service"))
else:
- email_verification = models.EmailVerification(
- username=username)
- email_verification.save()
-
- verification_uri = request.build_absolute_uri(
- reverse(
- 'django_airavata_auth:verify_email', kwargs={
- 'code': email_verification.verification_code}))
- logger.debug(
- "verification_uri={}".format(verification_uri))
-
- # TODO: need a better template, customization
- # TODO: add email settings documentation to settings_local.py
- send_mail(
- 'Please verify your email address',
- "Verification link: {}".format(verification_uri),
- "Django Portal <pg...@gmail.com>",
- ["{} {} <{}>".format(first_name, last_name, email)]
- )
+ _create_and_send_email_verification_link(
+ request, username, email, first_name, last_name)
# TODO: success message
return redirect(
reverse('django_airavata_auth:create_account'))
@@ -174,4 +157,59 @@ def verify_email(request, code):
except ObjectDoesNotExist as e:
# TODO: if doesn't exist, give user a form where they can enter their
# username to resend verification code
- pass
+ return redirect(reverse('django_airavata_auth:resend_email_link'))
+
+
+def resend_email_link(request):
+
+ # TODO: if the user is already verified their email, then redirect to login page with message
+ if request.method == 'POST':
+ form = forms.ResendEmailVerificationLinkForm(request.POST)
+ if form.is_valid():
+ try:
+ username = form.cleaned_data['username']
+ if iam_admin_client.is_user_exist(username):
+ user_profile = iam_admin_client.get_user(username)
+ _create_and_send_email_verification_link(
+ request,
+ username,
+ user_profile.emails[0],
+ user_profile.firstName,
+ user_profile.lastName)
+ # TODO: success message
+ return redirect(
+ reverse('django_airavata_auth:resend_email_link'))
+ except Exception as e:
+ logger.exception(
+ "Failed to resend email verification link", exc_info=e)
+ form.add_error(None, ValidationError(str(e)))
+ else:
+ form = forms.ResendEmailVerificationLinkForm()
+ return render(request, 'django_airavata_auth/verify_email.html', {
+ 'form': form
+ })
+
+
+def _create_and_send_email_verification_link(
+ request, username, email, first_name, last_name):
+
+ email_verification = models.EmailVerification(
+ username=username)
+ email_verification.save()
+
+ verification_uri = request.build_absolute_uri(
+ reverse(
+ 'django_airavata_auth:verify_email', kwargs={
+ 'code': email_verification.verification_code}))
+ logger.debug(
+ "verification_uri={}".format(verification_uri))
+
+ # TODO: need a better template, customization
+ # TODO: add email settings documentation to
+ # settings_local.py
+ send_mail(
+ 'Please verify your email address',
+ "Verification link: {}".format(verification_uri),
+ "Django Portal <pg...@gmail.com>",
+ ["{} {} <{}>".format(first_name, last_name, email)]
+ )
diff --git a/django_airavata/utils.py b/django_airavata/utils.py
index 78748c9..e730bd2 100644
--- a/django_airavata/utils.py
+++ b/django_airavata/utils.py
@@ -30,6 +30,10 @@ class ThriftConnectionException(Exception):
pass
+class ThriftClientException(Exception):
+ pass
+
+
def get_unsecure_transport(hostname, port):
# Create a socket to the Airavata Server
transport = TSocket.TSocket(hostname, port)
@@ -165,12 +169,16 @@ def get_thrift_client(host, port, is_secure, client_generator):
yield client
except Exception as e:
log.exception("Thrift client error occurred")
- raise e
+ raise ThriftClientException(
+ "Thrift client error occurred: " + str(e)) from e
finally:
if transport.isOpen():
transport.close()
log.debug("Thrift connection closed to {}:{}, "
"secure={}".format(host, port, is_secure))
+ except ThriftClientException as tce:
+ # Allow thrift client errors to bubble up
+ raise tce
except Exception as e:
msg = "Failed to open thrift connection to {}:{}, secure={}".format(
host, port, is_secure)