forked from JuliaCloud/JuliaBox
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add email_whitelist post-auth plugin
Issue JuliaCloud#339
- Loading branch information
Showing
7 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from impl_email_whitelist import EmailWhitelistHandler | ||
from email_verify_tbl import EmailVerifyDB | ||
from email_verify import EmailVerifyHandler | ||
__author__ = 'barche' |
72 changes: 72 additions & 0 deletions
72
engine/src/juliabox/plugins/email_whitelist/email_verify.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import os | ||
from juliabox.jbox_util import unquote, JBoxCfg | ||
from juliabox.handlers import JBPluginHandler | ||
from juliabox.db import JBoxUserV2, JBoxDBItemNotFound | ||
from email_verify_tbl import EmailVerifyDB | ||
from impl_email_whitelist import EmailWhitelistHandler | ||
import urllib | ||
from juliabox.cloud import JBPluginCloud | ||
|
||
__author__ = 'barche' | ||
|
||
|
||
class EmailVerifyHandler(JBPluginHandler): | ||
provides = [JBPluginHandler.JBP_HANDLER] | ||
|
||
CONFIGURED = False | ||
EMAIL_PLUGIN = None | ||
EMAIL_SENDER = "" | ||
|
||
@staticmethod | ||
def register(app): | ||
app.add_handlers(".*$", [(r"/jboxauth/email_verify/", EmailVerifyHandler)]) | ||
|
||
@staticmethod | ||
def configure(): | ||
if not EmailVerifyHandler.CONFIGURED: | ||
plugin = JBPluginCloud.jbox_get_plugin(JBPluginCloud.JBP_SENDMAIL) | ||
if plugin is None: | ||
EmailVerifyHandler.log_error("No plugin found for sending mails. Cannot send verification mail.") | ||
EmailVerifyHandler.EMAIL_PLUGIN = plugin | ||
EmailVerifyHandler.EMAIL_SENDER = JBoxCfg.get('user_activation')['sender'] | ||
|
||
EmailVerifyHandler.CONFIGURED = True | ||
|
||
|
||
|
||
def get(self): | ||
EmailVerifyHandler.configure() | ||
|
||
email = unquote(self.get_argument("email", None)) | ||
user_id = unquote(self.get_argument("user_id", None)) | ||
verification_code = unquote(self.get_argument("verification_code", None)) | ||
if user_id == None or email == None: | ||
EmailVerifyHandler.log_error("Bad request to email handler") | ||
return | ||
|
||
EmailVerifyHandler.log_info("Request to verify email %s with user_id %s", email, user_id) | ||
|
||
if not EmailWhitelistHandler.is_whitelisted(email): | ||
self.render(os.path.join(EmailWhitelistHandler.TEMPLATE_PATH, "email_whitelist.tpl"), cfg=JBoxCfg.nv, user_id=user_id, message="ERROR: entered email is not whitelisted, please try again:") | ||
return | ||
|
||
if verification_code == None: | ||
record = EmailVerifyDB(user_id, "pending_email_form_response", create=False) | ||
record.set_email(email) | ||
|
||
base_uri = self.request.protocol + "://" + self.request.host + self.request.uri.split('?')[0] | ||
mail_body = base_uri + '?' + urllib.urlencode({ | ||
"user_id": user_id, | ||
"email": email, | ||
"verification_code": record.get_code() | ||
}) | ||
EmailVerifyHandler.EMAIL_PLUGIN.send_email(email, EmailVerifyHandler.EMAIL_SENDER, 'JuliaBox account activation', mail_body) | ||
|
||
self.render(os.path.join(EmailWhitelistHandler.TEMPLATE_PATH, "message.tpl"), cfg=JBoxCfg.nv, message="Email sent. Please click the link in the mail.") | ||
else: | ||
record = EmailVerifyDB(user_id, email, create=False) | ||
if record.verify(verification_code): | ||
s = dict(error="", success="Verification OK, please log in again", info="", pending_activation=False, user_id="") | ||
self.rendertpl("index.tpl", cfg=JBoxCfg.nv, state=s) | ||
else: | ||
self.render(os.path.join(EmailWhitelistHandler.TEMPLATE_PATH, "message.tpl"), cfg=JBoxCfg.nv, message="Verification failed.") |
65 changes: 65 additions & 0 deletions
65
engine/src/juliabox/plugins/email_whitelist/email_verify_tbl.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from juliabox.jbox_util import gen_random_secret | ||
from juliabox.db import JBPluginDB, JBoxDBItemNotFound | ||
|
||
__author__ = 'barche' | ||
|
||
|
||
class EmailVerifyDB(JBPluginDB): | ||
provides = [JBPluginDB.JBP_TABLE_RDBMS] | ||
|
||
NAME = 'jbox_email_verify' | ||
|
||
TABLE = None | ||
|
||
KEYS = ['user_id'] | ||
ATTRIBUTES = ['email', 'verification_code', 'is_verified'] | ||
SQL_INDEXES = None | ||
KEYS_TYPES = [JBPluginDB.VCHAR] | ||
TYPES = [JBPluginDB.VCHAR, JBPluginDB.VCHAR, JBPluginDB.INT] | ||
|
||
def __init__(self, user_id, email, create=False): | ||
count = self.query_count(user_id__eq=user_id, email__eq=email) | ||
if count > 0 and create: | ||
raise RuntimeError("Email verify record exists, but create was requested") | ||
if count == 0 and (not create): | ||
raise RuntimeError("Email verify record does not exist") | ||
|
||
if create: | ||
data = { | ||
'user_id': user_id, | ||
'email': email, | ||
'verification_code': gen_random_secret(), | ||
'is_verified': 0 | ||
} | ||
self.create(data) | ||
|
||
self.item = self.fetch(user_id=user_id, email=email) | ||
self.is_new = create | ||
|
||
@classmethod | ||
def get_verified_emails(cls, user_id): | ||
records = cls.query(user_id__eq=user_id, is_verified__eq=1) | ||
verified_email_list = [] | ||
for rec in records: | ||
verified_email_list.append(rec['email']) | ||
return verified_email_list | ||
|
||
|
||
def set_email(self, email): | ||
self.set_attrib('email', email) | ||
self.save() | ||
|
||
def verify(self, verification_code): | ||
if self.get_attrib('verification_code') == verification_code: | ||
self.set_attrib('is_verified', 1) | ||
self.save() | ||
return True | ||
return False | ||
|
||
def get_code(self): | ||
return self.get_attrib('verification_code') | ||
|
||
def is_verified(self): | ||
if self.get_attrib('is_verified') == 1: | ||
return True | ||
return False |
61 changes: 61 additions & 0 deletions
61
engine/src/juliabox/plugins/email_whitelist/email_whitelist.tpl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<title>JuliaBox</title> | ||
|
||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> | ||
<link rel="stylesheet" href="/assets/css/icons.css" /> | ||
{% if cfg["env_type"] == "dev" %} | ||
<link rel="stylesheet/less" type="text/css" href="/assets/css/base.less" /> | ||
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/1.7.3/less.min.js"></script> | ||
{% else %} | ||
<link rel="stylesheet" type="text/css" href="/assets/css/base.css" /> | ||
{% end %} | ||
|
||
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script> | ||
|
||
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script> | ||
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> | ||
<script src="//cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.3.0/bootbox.min.js"></script> | ||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script> | ||
<script src="//apis.google.com/js/client.js"></script> | ||
<script src="/assets/js/jquery-gdrive.js"></script> | ||
<script src="/assets/js/juliabox.js"></script> | ||
<script type="text/javascript" src="//use.typekit.net/cpz5ogz.js"></script> | ||
<script type="text/javascript">try{Typekit.load();}catch(e){}</script> | ||
{% block head %} | ||
{% end %} | ||
</head> | ||
<body> | ||
<div class="header-wrap"> | ||
<div class="container"> | ||
<div class="row header-row"> | ||
<div class="logo-and-name"> | ||
<img class="brand-logo" src="/assets/img/juliacloudlogo.png"/> | ||
<div class="brand-title hidden-xs hidden-sm">JuliaBox<sup> beta</sup></div> | ||
</div> | ||
{% block tabs %} | ||
{% end %} | ||
</div><!-- row --> | ||
<div style="clear:both;"></div> | ||
</div> | ||
</div> | ||
|
||
<div class="container"> | ||
<table width="100%" height="100%" align="center" valign="middle"> | ||
<tr width="100%" height="100%" align="center" valign="middle"> | ||
<td width="100%" height="100%" align="center" valign="middle"> | ||
<div> | ||
<div>{{message}}</div> | ||
<form action="/jboxauth/email_verify/" method="get"> | ||
<input type="text" placeholder="Email whitelist check. Enter a whitelisted email and hit ⏎" class="form-control email-box" name="email" id="email" required autofocus> | ||
<input type="hidden" name="user_id" value={{user_id}}> | ||
<input style="display:none" type="submit" value="Launch"> | ||
</form> | ||
</div> | ||
</td> | ||
</tr> | ||
</table> | ||
</div> | ||
</body> | ||
</html> |
69 changes: 69 additions & 0 deletions
69
engine/src/juliabox/plugins/email_whitelist/impl_email_whitelist.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import os | ||
from juliabox.jbox_util import unquote, JBoxCfg | ||
from juliabox.handlers import JBPluginHandler | ||
from juliabox.db import JBoxUserV2, JBoxDBItemNotFound | ||
from email_verify_tbl import EmailVerifyDB | ||
|
||
__author__ = 'barche' | ||
|
||
|
||
class EmailWhitelistHandler(JBPluginHandler): | ||
provides = [JBPluginHandler.JBP_HANDLER, | ||
JBPluginHandler.JBP_HANDLER_POST_AUTH] | ||
|
||
WHITELIST = [] | ||
CONFIGURED = False | ||
TEMPLATE_PATH = os.path.dirname(__file__) | ||
|
||
@staticmethod | ||
def register(app): | ||
app.add_handlers(".*$", [(r"/jboxauth/email_whitelist/", EmailWhitelistHandler)]) | ||
|
||
def get(self): | ||
#EmailWhitelistHandler.log_info("State arg: %s", self.get_argument("state")) | ||
email = unquote(self.get_argument("email")) | ||
EmailWhitelistHandler.log_info("Obtained email %s", email) | ||
|
||
@staticmethod | ||
def configure(): | ||
if not EmailWhitelistHandler.CONFIGURED: | ||
data = JBoxCfg.get('email_whitelist') | ||
if data == None: | ||
EmailWhitelistHandler.log_error("No email_whitelist config entry") | ||
return | ||
EmailWhitelistHandler.WHITELIST = data.get('allowed_addresses') | ||
|
||
if len(EmailWhitelistHandler.WHITELIST) == 0: | ||
EmailWhitelistHandler.log_error("No allowed_addresses config entry for email_whitelist") | ||
|
||
EmailWhitelistHandler.CONFIGURED = True | ||
|
||
@staticmethod | ||
def is_whitelisted(email): | ||
for allowed_mail in EmailWhitelistHandler.WHITELIST: | ||
if email.lower().endswith(allowed_mail.lower()): | ||
return True | ||
return False | ||
|
||
|
||
@staticmethod | ||
def process_user_id(handler, user_id): | ||
EmailWhitelistHandler.configure() | ||
|
||
# Check if the user_id matches | ||
if EmailWhitelistHandler.is_whitelisted(user_id): | ||
return True | ||
|
||
# Check if any of the users verified email addresses match | ||
verified_emails = EmailVerifyDB.get_verified_emails(user_id) | ||
for allowed_mail in EmailWhitelistHandler.WHITELIST: | ||
for verified_email in verified_emails: | ||
if EmailWhitelistHandler.is_whitelisted(verified_email): | ||
return True | ||
|
||
# No match, create a pending email verify request | ||
EmailVerifyDB(user_id, "pending_email_form_response", create=True) | ||
|
||
handler.render(os.path.join(EmailWhitelistHandler.TEMPLATE_PATH, "email_whitelist.tpl"), cfg=JBoxCfg.nv, user_id=user_id, message="Please enter white-listed email as per tutor instructions:") | ||
|
||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<title>JuliaBox</title> | ||
|
||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> | ||
<link rel="stylesheet" href="/assets/css/icons.css" /> | ||
{% if cfg["env_type"] == "dev" %} | ||
<link rel="stylesheet/less" type="text/css" href="/assets/css/base.less" /> | ||
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/1.7.3/less.min.js"></script> | ||
{% else %} | ||
<link rel="stylesheet" type="text/css" href="/assets/css/base.css" /> | ||
{% end %} | ||
</head> | ||
<body> | ||
<div class="header-wrap"> | ||
<div class="container"> | ||
<div class="row header-row"> | ||
<div class="logo-and-name"> | ||
<img class="brand-logo" src="/assets/img/juliacloudlogo.png"/> | ||
<div class="brand-title hidden-xs hidden-sm">JuliaBox<sup> beta</sup></div> | ||
</div> | ||
{% block tabs %} | ||
{% end %} | ||
</div><!-- row --> | ||
<div style="clear:both;"></div> | ||
</div> | ||
</div> | ||
|
||
<div class="container"> | ||
<table width="100%" height="100%" align="center" valign="middle"> | ||
<tr width="100%" height="100%" align="center" valign="middle"> | ||
<td width="100%" height="100%" align="center" valign="middle"> | ||
<div> | ||
<div>{{message}}</div> | ||
</div> | ||
</td> | ||
</tr> | ||
</table> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters