Skip to content

Commit

Permalink
parameterizing various values specific to hacker dojo into constants.…
Browse files Browse the repository at this point in the history
… eventually to be put into a config
  • Loading branch information
progrium committed Apr 30, 2011
1 parent 2d89ec0 commit 21e8506
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 72 deletions.
159 changes: 94 additions & 65 deletions main.py
Expand Up @@ -13,9 +13,19 @@
import base64 import base64
import sys import sys


ORG_NAME = 'Hacker Dojo'
APP_NAME = 'hd-signup' APP_NAME = 'hd-signup'
EMAIL_FROM = "Dojo Signup <no-reply@%s.appspotmail.com>" % APP_NAME EMAIL_FROM = "Dojo Signup <no-reply@%s.appspotmail.com>" % APP_NAME
DAYS_FOR_KEY = 30 DAYS_FOR_KEY = 30
INTERNAL_DEV_EMAIL = "Internal Dev <internal-dev@hackerdojo.com>"
DOMAIN_HOST = 'domain.hackerdojo.com'
DOMAIN_USER = 'api@hackerdojo.com'
SUCCESS_HTML_URL = 'http://hackerdojo.pbworks.com/api_v2/op/GetPage/page/SubscriptionSuccess/_type/html'
PAYPAL_EMAIL = 'PayPal <paypal@hackerdojo.com>'
APPS_DOMAIN = 'hackerdojo.com'
SIGNUP_HELP_EMAIL = 'signupops@hackerdojo.com'
TREASURER_EMAIL = 'treasurer@hackerdojo.com'
GOOGLE_ANALYTICS_ID = 'UA-11332872-2'


try: try:
is_dev = os.environ['SERVER_SOFTWARE'].startswith('Dev') is_dev = os.environ['SERVER_SOFTWARE'].startswith('Dev')
Expand All @@ -38,13 +48,25 @@ def fetch_usernames(use_cache=True):
if usernames and use_cache: if usernames and use_cache:
return usernames return usernames
else: else:
resp = urlfetch.fetch('http://domain.hackerdojo.com/users', deadline=10) resp = urlfetch.fetch('http://%s/users' % DOMAIN_HOST, deadline=10)
if resp.status_code == 200: if resp.status_code == 200:
usernames = [m.lower() for m in simplejson.loads(resp.content)] usernames = [m.lower() for m in simplejson.loads(resp.content)]
if not memcache.set('usernames', usernames, 3600*24): if not memcache.set('usernames', usernames, 3600*24):
logging.error("Memcache set failed.") logging.error("Memcache set failed.")
return usernames return usernames


def render(path, local_vars):
template_vars = {'is_prod': is_prod, 'org_name': ORG_NAME, 'analytics_id': GOOGLE_ANALYTICS_ID, 'domain': APPS_DOMAIN}
template_vars.update(local_vars)
return template.render(path, template_vars)


class BadgeChange(db.Model):
created = db.DateTimeProperty(auto_now_add=True)
rfid_tag = db.StringProperty()
username = db.StringProperty()
description = db.StringProperty()

class Membership(db.Model): class Membership(db.Model):
hash = db.StringProperty() hash = db.StringProperty()
first_name = db.StringProperty(required=True) first_name = db.StringProperty(required=True)
Expand Down Expand Up @@ -78,8 +100,7 @@ def get_by_hash(cls, hash):


class MainHandler(webapp.RequestHandler): class MainHandler(webapp.RequestHandler):
def get(self): def get(self):
self.response.out.write(template.render('templates/main.html', { self.response.out.write(render('templates/main.html', {
'is_prod': is_prod,
'plan': self.request.get('plan', 'full'), 'plan': self.request.get('plan', 'full'),
'paypal': self.request.get('paypal')})) 'paypal': self.request.get('paypal')}))


Expand All @@ -90,8 +111,8 @@ def post(self):
plan = self.request.get('plan', 'full') plan = self.request.get('plan', 'full')


if not first_name or not last_name or not email: if not first_name or not last_name or not email:
self.response.out.write(template.render('templates/main.html', { self.response.out.write(render('templates/main.html', {
'is_prod': is_prod, 'plan': plan, 'message': "Sorry, we need all three fields."})) 'plan': plan, 'message': "Sorry, we need all three fields."}))
else: else:
existing_member = Membership.get_by_email(email) existing_member = Membership.get_by_email(email)
if existing_member and existing_member.status in [None, 'paypal']: if existing_member and existing_member.status in [None, 'paypal']:
Expand Down Expand Up @@ -121,7 +142,7 @@ def get(self, hash):
if self.request.get('u'): if self.request.get('u'):
pick_username = True pick_username = True
message = self.request.get('message') message = self.request.get('message')
self.response.out.write(template.render('templates/account.html', locals())) self.response.out.write(render('templates/account.html', locals()))


def post(self, hash): def post(self, hash):
username = self.request.get('username') username = self.request.get('username')
Expand Down Expand Up @@ -163,8 +184,8 @@ class CreateUserTask(webapp.RequestHandler):
def post(self): def post(self):
def fail(what, details): def fail(what, details):
mail.send_mail(sender=EMAIL_FROM, mail.send_mail(sender=EMAIL_FROM,
to="Internal Dev <internal-dev@hackerdojo.com>", to=INTERNAL_DEV_EMAIL,
subject="[hd-signup] CreateUserTask failure", subject="[%s] CreateUserTask failure" % APP_NAME,
body=details) body=details)
def retry(countdown=None): def retry(countdown=None):
retries = int(self.request.get('retries', 0)) + 1 retries = int(self.request.get('retries', 0)) + 1
Expand All @@ -186,12 +207,12 @@ def retry(countdown=None):
return fail("Account information expired") return fail("Account information expired")


try: try:
resp = urlfetch.fetch('http://domain.hackerdojo.com/users', method='POST', payload=urllib.urlencode({ resp = urlfetch.fetch('http://%s/users' % DOMAIN_HOST, method='POST', payload=urllib.urlencode({
'username': username, 'username': username,
'password': password, 'password': password,
'first_name': membership.first_name, 'first_name': membership.first_name,
'last_name': membership.last_name, 'last_name': membership.last_name,
'secret': keymaster.get('api@hackerdojo.com'), 'secret': keymaster.get(DOMAIN_USER),
}), deadline=10) }), deadline=10)
except urlfetch.DownloadError, e: except urlfetch.DownloadError, e:
return retry() return retry()
Expand All @@ -207,25 +228,25 @@ def retry(countdown=None):


class SuccessHandler(webapp.RequestHandler): class SuccessHandler(webapp.RequestHandler):
def get(self, hash): def get(self, hash):
member = Membership.all().filter('hash =', hash).get() member = Membership.get_by_hash(hash)
if member: if member:
if self.request.query_string == 'email': if self.request.query_string == 'email':
spreedly_url = member.spreedly_url() spreedly_url = member.spreedly_url()
mail.send_mail(sender=EMAIL_FROM, mail.send_mail(sender=EMAIL_FROM,
to="%s <%s>" % (member.full_name(), member.email), to="%s <%s>" % (member.full_name(), member.email),
subject="Welcome to Hacker Dojo, %s!" % member.first_name, subject="Welcome to Hacker Dojo, %s!" % member.first_name,
body=template.render('templates/welcome.txt', locals())) body=render('templates/welcome.txt', locals()))
self.redirect(self.request.path) self.redirect(self.request.path)
else: else:
success_html = urlfetch.fetch("http://hackerdojo.pbworks.com/api_v2/op/GetPage/page/SubscriptionSuccess/_type/html").content success_html = urlfetch.fetch(SUCCESS_HTML_URL).content
success_html = success_html.replace('joining!', 'joining, %s!' % member.first_name) success_html = success_html.replace('joining!', 'joining, %s!' % member.first_name)
is_prod = not is_dev is_prod = not is_dev
self.response.out.write(template.render('templates/success.html', locals())) self.response.out.write(render('templates/success.html', locals()))


class NeedAccountHandler(webapp.RequestHandler): class NeedAccountHandler(webapp.RequestHandler):
def get(self): def get(self):
message = self.request.get('message') message = self.request.get('message')
self.response.out.write(template.render('templates/needaccount.html', locals())) self.response.out.write(render('templates/needaccount.html', locals()))


def post(self): def post(self):
email = self.request.get('email') email = self.request.get('email')
Expand All @@ -241,7 +262,7 @@ def post(self):
subject="Create your Hacker Dojo account", subject="Create your Hacker Dojo account",
body="""Hello,\n\nHere's a link to create your Hacker Dojo account:\n\nhttp://%s/account/%s""" % (self.request.host, member.hash)) body="""Hello,\n\nHere's a link to create your Hacker Dojo account:\n\nhttp://%s/account/%s""" % (self.request.host, member.hash))
sent = True sent = True
self.response.out.write(template.render('templates/needaccount.html', locals())) self.response.out.write(render('templates/needaccount.html', locals()))


class UpdateHandler(webapp.RequestHandler): class UpdateHandler(webapp.RequestHandler):
def get(self): def get(self):
Expand All @@ -256,7 +277,7 @@ def post(self, ids=None):
if member: if member:
if member.status == 'paypal': if member.status == 'paypal':
mail.send_mail(sender=EMAIL_FROM, mail.send_mail(sender=EMAIL_FROM,
to="PayPal <paypal@hackerdojo.com>", to=PAYPAL_EMAIL,
subject="Please cancel PayPal subscription for %s" % member.full_name(), subject="Please cancel PayPal subscription for %s" % member.full_name(),
body=member.email) body=member.email)
member.status = 'active' if subscriber['active'] == 'true' else 'suspended' member.status = 'active' if subscriber['active'] == 'true' else 'suspended'
Expand All @@ -283,7 +304,7 @@ def get(self):
if not user: if not user:
self.redirect(users.create_login_url('/memberlist')) self.redirect(users.create_login_url('/memberlist'))
signup_users = Membership.all().order("last_name").fetch(1000); signup_users = Membership.all().order("last_name").fetch(1000);
self.response.out.write(template.render('templates/memberlist.html', locals())) self.response.out.write(render('templates/memberlist.html', locals()))


class AllHandler(webapp.RequestHandler): class AllHandler(webapp.RequestHandler):
def get(self): def get(self):
Expand All @@ -298,7 +319,7 @@ def get(self):
signup_usernames = [m.lower() for m in signup_usernames] signup_usernames = [m.lower() for m in signup_usernames]
users_not_on_domain = set(signup_usernames) - set(domain_usernames) users_not_on_domain = set(signup_usernames) - set(domain_usernames)
users_not_on_signup = set(domain_usernames) - set(signup_usernames) users_not_on_signup = set(domain_usernames) - set(signup_usernames)
self.response.out.write(template.render('templates/users.html', locals())) self.response.out.write(render('templates/users.html', locals()))
else: else:
self.response.out.write("Need admin access") self.response.out.write("Need admin access")


Expand Down Expand Up @@ -326,9 +347,9 @@ def get(self):
return return
else: else:
account = Membership.all().filter('username =', user.nickname()).get() account = Membership.all().filter('username =', user.nickname()).get()
email = account.username + "@hackerdojo.com" email = '%s@%s' % (account.username, APPS_DOMAIN)
gravatar_url = "http://www.gravatar.com/avatar/" + hashlib.md5(email.lower()).hexdigest() gravatar_url = "http://www.gravatar.com/avatar/" + hashlib.md5(email.lower()).hexdigest()
self.response.out.write(template.render('templates/profile.html', locals())) self.response.out.write(render('templates/profile.html', locals()))


class PrefHandler(webapp.RequestHandler): class PrefHandler(webapp.RequestHandler):
def get(self): def get(self):
Expand All @@ -345,10 +366,10 @@ def get(self):
error += "<pre>Account: "+str(account) error += "<pre>Account: "+str(account)
if account: if account:
error += "<pre>Token: "+str(account.spreedly_token) error += "<pre>Token: "+str(account.spreedly_token)
self.response.out.write(template.render('templates/error.html', locals())) self.response.out.write(render('templates/error.html', locals()))
return return
auto_signin = account.auto_signin auto_signin = account.auto_signin
self.response.out.write(template.render('templates/pref.html', locals())) self.response.out.write(render('templates/pref.html', locals()))


def post(self): def post(self):
user = users.get_current_user() user = users.get_current_user()
Expand All @@ -358,45 +379,56 @@ def post(self):
account = Membership.all().filter('username =', user.nickname()).get() account = Membership.all().filter('username =', user.nickname()).get()
if not account: if not account:
error = "<p>Error #1983, which should never happen." error = "<p>Error #1983, which should never happen."
self.response.out.write(template.render('templates/error.html', locals())) self.response.out.write(render('templates/error.html', locals()))
return return
auto_signin = self.request.get('auto').strip() auto_signin = self.request.get('auto').strip()
account.auto_signin = auto_signin account.auto_signin = auto_signin
account.put() account.put()
self.response.out.write(template.render('templates/prefsaved.html', locals())) self.response.out.write(render('templates/prefsaved.html', locals()))






class KeyHandler(webapp.RequestHandler): class KeyHandler(webapp.RequestHandler):
def get(self): def get(self):
user = users.get_current_user() user = users.get_current_user()
if not user: if not user:
self.redirect(users.create_login_url('/key')) self.redirect(users.create_login_url('/key'))
return
else:
account = Membership.all().filter('username =', user.nickname()).get()
if not account or not account.spreedly_token:
error = "<p>It appears that you have an account on @hackerdojo.com, but you do not have a corresponding account in the signup application.</p><p>How to remedy:</p><ol><li>If you <b>are not</b> in the Spreedly system yet, <a href=\"/\">sign up</a> now.</li><li>If you <b>are</b> in Spreedly already, please contact <a href=\"mailto:signupops@hackerdojo.com?Subject=Spreedly+account+not+linked+to+hackerdojo+account\">signupops@hackerdojo.com</a>.</li></ol>"
error += "<pre>Nick: "+str(user.nickname())
error += "<pre>Email: "+str(user.email())
error += "<pre>Account: "+str(account)
if account:
error += "<pre>Token: "+str(account.spreedly_token)

self.response.out.write(template.render('templates/error.html', locals()))
return
if account.status != "active":
url = "https://spreedly.com/"+SPREEDLY_ACCOUNT+"/subscriber_accounts/"+account.spreedly_token
error = "<p>Your Spreedly account status does not appear to me marked as active. This might be a mistake, in which case we apologize. <p>To investigate your account, you may go here: <a href=\""+url+"\">"+url+"</a> <p>If you believe this message is in error, please contact <a href=\"mailto:signupops@hackerdojo.com?Subject=Spreedly+account+not+linked+to+hackerdojo+account\">signupops@hackerdojo.com</a></p>";
self.response.out.write(template.render('templates/error.html', locals()))
return return
delta = datetime.utcnow() - account.created else:
if delta.days < DAYS_FOR_KEY: account = Membership.all().filter('username =', user.nickname()).get()
error = "<p>You have been a member for "+str(delta.days)+" days. After "+str(DAYS_FOR_KEY)+" days you qualify for a key. Check back in "+str(DAYS_FOR_KEY-delta.days)+" days!</p><p>If you believe this message is in error, please contact <a href=\"mailto:signupops@hackerdojo.com?Subject=Membership+create+date+not+correct\">signupops@hackerdojo.com</a>.</p>"; if not account or not account.spreedly_token:
self.response.out.write(template.render('templates/error.html', locals())) error = """<p>It appears that you have an account on @%(domain)s, but you do not have a corresponding account in the signup application.</p>
return <p>How to remedy:</p>
bc = BadgeChange.all().filter('username =', account.username).fetch(100) <ol><li>If you <b>are not</b> in the Spreedly system yet, <a href=\"/\">sign up</a> now.</li>
self.response.out.write(template.render('templates/key.html', locals())) <li>If you <b>are</b> in Spreedly already, please contact <a href=\"mailto:%(signup_email)s?Subject=Spreedly+account+not+linked+to+account\">%(signup_email)s</a>.</li></ol>
<pre>Nick: %(nick)s</pre>
<pre>Email: %(email)s</pre>
<pre>Account: %(account)s</pre>
""" % {'domain': APPS_DOMAIN, 'signup_email': SIGNUP_HELP_EMAIL, 'nick': user.nickname(), 'email': user.email(), 'account': account}
if account:
error += "<pre>Token: %s</pre>" % account.spreedly_token

self.response.out.write(render('templates/error.html', locals()))
return
if account.status != "active":
url = "https://spreedly.com/"+SPREEDLY_ACCOUNT+"/subscriber_accounts/"+account.spreedly_token
error = """<p>Your Spreedly account status does not appear to me marked as active.
This might be a mistake, in which case we apologize. </p>
<p>To investigate your account, you may go here: <a href=\"%(url)s\">%(url)s</a> </p>
<p>If you believe this message is in error, please contact <a href=\"mailto:%(signup_email)s?Subject=Spreedly+account+not+linked+to+account\">%(signup_email)s</a></p>
""" % {'url': url, 'signup_email': SIGNUP_HELP_EMAIL}
self.response.out.write(render('templates/error.html', locals()))
return
delta = datetime.utcnow() - account.created
if delta.days < DAYS_FOR_KEY:
error = """<p>You have been a member for %(days)s days.
After %(days)s days you qualify for a key. Check back in %(delta)s days!</p>
<p>If you believe this message is in error, please contact <a href=\"mailto:%(signup_email)s?Subject=Membership+create+date+not+correct\">%(signup_email)s</a>.</p>
""" % {'days': DAYS_FOR_KEY, 'delta': DAYS_FOR_KEY-delta.days, 'signup_email': SIGNUP_HELP_EMAIL}
self.response.out.write(render('templates/error.html', locals()))
return
bc = BadgeChange.all().filter('username =', account.username).fetch(100)
self.response.out.write(render('templates/key.html', locals()))


def post(self): def post(self):
user = users.get_current_user() user = users.get_current_user()
Expand All @@ -406,28 +438,28 @@ def post(self):
account = Membership.all().filter('username =', user.nickname()).get() account = Membership.all().filter('username =', user.nickname()).get()
if not account or not account.spreedly_token or account.status != "active": if not account or not account.spreedly_token or account.status != "active":
error = "<p>Error #1982, which should never happen." error = "<p>Error #1982, which should never happen."
self.response.out.write(template.render('templates/error.html', locals())) self.response.out.write(render('templates/error.html', locals()))
return return
rfid_tag = self.request.get('rfid_tag').strip() rfid_tag = self.request.get('rfid_tag').strip()
description = self.request.get('description').strip() description = self.request.get('description').strip()
if rfid_tag.isdigit(): if rfid_tag.isdigit():
if Membership.all().filter('rfid_tag =', rfid_tag).get(): if Membership.all().filter('rfid_tag =', rfid_tag).get():
error = "<p>That RFID tag is in use by someone else.</p>" error = "<p>That RFID tag is in use by someone else.</p>"
self.response.out.write(template.render('templates/error.html', locals())) self.response.out.write(render('templates/error.html', locals()))
return return
if not description: if not description:
error = "<p>Please enter a reason why you are associating a replacement RFID key. Please hit BACK and try again.</p>" error = "<p>Please enter a reason why you are associating a replacement RFID key. Please hit BACK and try again.</p>"
self.response.out.write(template.render('templates/error.html', locals())) self.response.out.write(render('templates/error.html', locals()))
return return
account.rfid_tag = rfid_tag account.rfid_tag = rfid_tag
account.put() account.put()
bc = BadgeChange(rfid_tag = rfid_tag, username=account.username, description=description) bc = BadgeChange(rfid_tag = rfid_tag, username=account.username, description=description)
bc.put() bc.put()
self.response.out.write(template.render('templates/key_ok.html', locals())) self.response.out.write(render('templates/key_ok.html', locals()))
return return
else: else:
error = "<p>That RFID ID seemed invalid. Hit back and try again.</p>" error = "<p>That RFID ID seemed invalid. Hit back and try again.</p>"
self.response.out.write(template.render('templates/error.html', locals())) self.response.out.write(render('templates/error.html', locals()))
return return


class RFIDHandler(webapp.RequestHandler): class RFIDHandler(webapp.RequestHandler):
Expand All @@ -437,7 +469,7 @@ def get(self):
if self.request.get('callback'): # jsonp callback support if self.request.get('callback'): # jsonp callback support
self.response.out.write(self.request.get('callback')+"("); self.response.out.write(self.request.get('callback')+"(");
if m: if m:
email = m.username + "@hackerdojo.com" email = '%s@%s' % (m.username, APPS_DOMAIN)
gravatar_url = "http://www.gravatar.com/avatar/" + hashlib.md5(email.lower()).hexdigest() gravatar_url = "http://www.gravatar.com/avatar/" + hashlib.md5(email.lower()).hexdigest()
self.response.out.write(simplejson.dumps({"gravatar": gravatar_url,"auto_signin":m.auto_signin, "status" : m.status, "name" : m.first_name + " " + m.last_name, "rfid_tag" : m.rfid_tag, "username" : m.username })) self.response.out.write(simplejson.dumps({"gravatar": gravatar_url,"auto_signin":m.auto_signin, "status" : m.status, "name" : m.first_name + " " + m.last_name, "rfid_tag" : m.rfid_tag, "username" : m.username }))
else: else:
Expand All @@ -459,17 +491,14 @@ def get(self):
else: else:
account = Membership.all().filter('username =', user.nickname()).get() account = Membership.all().filter('username =', user.nickname()).get()
if not account or not account.spreedly_token: if not account or not account.spreedly_token:
error = "<p>Sorry, your hackerdojo account does not appear to be linked to a Spreedly account. Please contact <a href=\"mailto:treasurer@hackerdojo.com\">treasurer@hackerdojo.com</a> so they can manually update your account." error = """"<p>Sorry, your %(name)s account does not appear to be linked to a Spreedly account.
self.response.out.write(template.render('templates/error.html', locals())) Please contact <a href=\"mailto:%(treasurer)s\">%(treasurer)s</a> so they can manually update your account.
""" % {'treasurer': TREASURER_EMAIL, 'name': ORG_NAME}
self.response.out.write(render('templates/error.html', locals()))
return return
url = "https://spreedly.com/"+SPREEDLY_ACCOUNT+"/subscriber_accounts/"+account.spreedly_token url = "https://spreedly.com/"+SPREEDLY_ACCOUNT+"/subscriber_accounts/"+account.spreedly_token
self.redirect(url) self.redirect(url)


class BadgeChange(db.Model):
created = db.DateTimeProperty(auto_now_add=True)
rfid_tag = db.StringProperty()
username = db.StringProperty()
description = db.StringProperty()


def main(): def main():
application = webapp.WSGIApplication([ application = webapp.WSGIApplication([
Expand Down
2 changes: 1 addition & 1 deletion templates/account.html
Expand Up @@ -10,7 +10,7 @@ <h4>
<form action="{{self.request.path}}" method="post"> <form action="{{self.request.path}}" method="post">
<table> <table>
{% if message %}<tr><td>&nbsp;</td><td style="color: red; font-size: smaller;">{{ message }}</td></tr>{% endif %} {% if message %}<tr><td>&nbsp;</td><td style="color: red; font-size: smaller;">{{ message }}</td></tr>{% endif %}
<tr><td class="label">Username:</td><td>{% if pick_username %}<input type="text" name="username" value="{{username}}" />{% else %}<strong>{{ username }}</strong><input type="hidden" name="username" value="{{username}}" />{% endif %} @hackerdojo.com</td></tr> <tr><td class="label">Username:</td><td>{% if pick_username %}<input type="text" name="username" value="{{username}}" />{% else %}<strong>{{ username }}</strong><input type="hidden" name="username" value="{{username}}" />{% endif %} @{{domain}}</td></tr>
<tr><td class="label">Password:</td><td><input type="password" name="password" /></td></tr> <tr><td class="label">Password:</td><td><input type="password" name="password" /></td></tr>
<tr><td class="label">Confirm:</td><td><input type="password" name="password_confirm" /></td></tr> <tr><td class="label">Confirm:</td><td><input type="password" name="password_confirm" /></td></tr>
</table> </table>
Expand Down

0 comments on commit 21e8506

Please sign in to comment.