Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

new version of keymaster, added some api endpoints, no more keys.py

  • Loading branch information...
commit fbdf629bd143bc54a40e222459b77f3890610cf3 1 parent bda34f9
@progrium progrium authored
Showing with 99 additions and 79 deletions.
  1. +3 −0  app.yaml
  2. +57 −40 keymaster.py
  3. +39 −39 main.py
View
3  app.yaml
@@ -14,5 +14,8 @@ handlers:
static_dir: static
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
+- url: /_km/.*
+ script: keymaster.py
+ login: admin
- url: .*
script: main.py
View
97 keymaster.py
@@ -1,44 +1,61 @@
-from google.appengine.api import urlfetch, memcache
-from google.appengine.ext import webapp
-import urllib
+from google.appengine.api import urlfetch, memcache, users
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import util
+import os
+try:
+ from Crypto.Cipher import ARC4
+except ImportError:
+ # Just pass through in dev mode
+ class ARC4:
+ new = classmethod(lambda k,x: ARC4)
+ encrypt = classmethod(lambda k,x: x)
+ decrypt = classmethod(lambda k,x: x)
-## Example usage
-#
-# def needs_key():
-# key = keymaster.get('my-key')
-# if key:
-# # Do something with key
-# else:
-# keymaster.request('my-key')
-#
-# def main():
-# application = webapp.WSGIApplication([
-# ('/key/(.+)', keymaster.Handler({
-# 'my-key': ('6f7e21711e29e6d4b4e64daceb2a7348', '2isy046g', needs_key),
-# 'another-key': ('keymaster-hash', 'keymaster-secret', optional_key_arrival_callback),
-# })),
-# ], debug=True)
-
-_keys = {}
-
-def get(keyname):
- return memcache.get(keyname, namespace='keymaster')
+class Keymaster(db.Model):
+ secret = db.BlobProperty(required=True)
-def request(keyname):
- urlfetch.fetch('http://www.thekeymaster.org/%s' % _keys[keyname][0], method='POST', payload=urllib.urlencode({'secret': _keys[keyname][1]}), deadline=10)
+ @classmethod
+ def encrypt(cls, key_name, secret):
+ secret = ARC4.new(os.environ['APPLICATION_ID']).encrypt(secret)
+ k = cls.get_by_key_name(key_name)
+ if k:
+ k.secret = str(secret)
+ else:
+ k = cls(key_name=str(key_name), secret=str(secret))
+ return k.put()
-class _Handler(webapp.RequestHandler):
- def get(self, keyname):
- request(keyname)
-
- def post(self, keyname):
- key = self.request.get('key')
- if key:
- memcache.set(keyname, key, namespace='keymaster')
- if len(_keys[keyname]) > 2:
- _keys[keyname][2]()
+ @classmethod
+ def decrypt(cls, key_name):
+ k = cls.get_by_key_name(str(key_name))
+ if not k:
+ raise Exception("Keymaster has no secret for %s" % key_name)
+ return ARC4.new(os.environ['APPLICATION_ID']).encrypt(k.secret)
+
+def get(key):
+ return Keymaster.decrypt(key)
+
+class KeymasterHandler(webapp.RequestHandler):
+ @util.login_required
+ def get(self):
+ if users.is_current_user_admin():
+ self.response.out.write("""<html><body><form method="post">
+ <input type="text" name="key" /><input type="text" name="secret" /><input type="submit" /></form></body></html>""")
+ else:
+ self.redirect('/')
+
+ def post(self):
+ if users.is_current_user_admin():
+ Keymaster.encrypt(self.request.get('key'), self.request.get('secret'))
+ self.response.out.write("Saved: %s" % Keymaster.decrypt(self.request.get('key')))
+ else:
+ self.redirect('/')
+
+def main():
+ application = webapp.WSGIApplication([
+ ('/_km/key', KeymasterHandler),
+ ],debug=True)
+ util.run_wsgi_app(application)
+
+if __name__ == '__main__':
+ main()
-def Handler(keys):
- global _keys
- _keys = keys
- return _Handler
View
78 main.py
@@ -17,14 +17,13 @@
except:
is_dev = False
-import keys
if is_dev:
SPREEDLY_ACCOUNT = 'hackerdojotest'
- SPREEDLY_APIKEY = keys.hackerdojotest
+ SPREEDLY_APIKEY = keymaster.get('spreedly:hackerdojotest')
PLAN_IDS = {'full': '1957'}
else:
SPREEDLY_ACCOUNT = 'hackerdojo'
- SPREEDLY_APIKEY = keys.hackerdojo
+ SPREEDLY_APIKEY = keymaster.get('spreedly:hackerdojo')
PLAN_IDS = {'full': '1987', 'hardship': '2537', 'supporter': '1988', 'family': '3659', 'minor': '3660'}
is_prod = not is_dev
@@ -35,7 +34,7 @@ def fetch_usernames(use_cache=True):
if usernames and use_cache:
return usernames
else:
- resp = urlfetch.fetch('http://hackerdojo-domain.appspot.com/users', deadline=10)
+ resp = urlfetch.fetch('http://domain.hackerdojo.com/users', deadline=10)
if resp.status_code == 200:
usernames = [m.lower() for m in simplejson.loads(resp.content)]
if not memcache.set('usernames', usernames, 3600*24):
@@ -117,8 +116,6 @@ def get(self, hash):
m.put()
self.redirect(users.create_logout_url('/success/%s' % hash))
else:
- if not keymaster.get('api-secret'):
- keymaster.request('api-secret')
message = self.request.get('message')
p = re.compile(r'[^\w]')
username = '.'.join([p.sub('', m.first_name), p.sub('', m.last_name)]).lower()
@@ -139,37 +136,32 @@ def post(self, hash):
elif len(password) < 6:
self.redirect(self.request.path + "?message=Password must be 6 characters or longer")
else:
- if not keymaster.get('api-secret'):
- self.redirect(self.request.path + "?message=There was a caching error, please try again.")
+ m = Membership.all().filter('hash =', hash).get()
+
+ if m and m.spreedly_token:
+ try:
+ resp = urlfetch.fetch('http://domain.hackerdojo.com/users', method='POST', payload=urllib.urlencode({
+ 'username': username,
+ 'password': password,
+ 'first_name': m.first_name,
+ 'last_name': m.last_name,
+ 'secret': keymaster.get('api@hackerdojo.com'),
+ }), deadline=10)
+ out = resp.content
+ except urlfetch.DownloadError, e:
+ out = str(e)
+
+ usernames = fetch_usernames(False)
+ if username in usernames:
+ m.username = username
+ m.put()
+ self.redirect('/success/%s?email' % hash)
else:
- m = Membership.all().filter('hash =', hash).get()
-
- if m.spreedly_token:
- try:
- resp = urlfetch.fetch('http://hackerdojo-domain.appspot.com/users', method='POST', payload=urllib.urlencode({
- 'username': username,
- 'password': password,
- 'first_name': m.first_name,
- 'last_name': m.last_name,
- 'secret': keymaster.get('api-secret'),
- }), deadline=10)
- if 'try again' in resp.content:
- self.redirect(self.request.path + "?message=There was a caching error, please try again.")
- return
- except urlfetch.DownloadError:
- pass
-
- usernames = fetch_usernames(False)
- if username in usernames:
- m.username = username
- m.put()
- self.redirect('/success/%s?email' % hash)
- else:
- mail.send_mail(sender=EMAIL_FROM,
- to="Jeff Lindsay <progrium@gmail.com>",
- subject="Error creating account",
- body=resp.content if m.spreedly_token else "Attempt to make user without paying: " + self.request.remote_addr)
- self.redirect(self.request.path + "?message=There was a problem creating your account. Please contact an admin.")
+ mail.send_mail(sender=EMAIL_FROM,
+ to="Jeff Lindsay <progrium@gmail.com>",
+ subject="Error creating account for %s" % username,
+ body=out if m.spreedly_token else "Attempt to make user without paying: " + self.request.remote_addr)
+ self.redirect(self.request.path + "?message=There was a problem creating your account. Please contact an admin.")
class SuccessHandler(webapp.RequestHandler):
@@ -231,6 +223,14 @@ def post(self, ids=None):
member.put()
self.response.out.write("ok")
+class LinkedHandler(webapp.RequestHandler):
+ def get(self):
+ self.response.out.write(simplejson.dumps([m.username for m in Membership.all().filter('username !=', None)]))
+
+class SuspendedHandler(webapp.RequestHandler):
+ def get(self):
+ self.response.out.write(simplejson.dumps([[m.fullname(), m.username] for m in Membership.all().filter('status =', 'suspended')]))
+
class CleanupHandler(webapp.RequestHandler):
def get(self):
self.post()
@@ -250,14 +250,14 @@ def post(self):
def main():
application = webapp.WSGIApplication([
('/', MainHandler),
+ ('/api/linked', LinkedHandler),
+ ('/api/suspended', SuspendedHandler),
('/cleanup', CleanupHandler),
('/account/(.+)', AccountHandler),
('/upgrade/needaccount', NeedAccountHandler),
('/success/(.+)', SuccessHandler),
('/update', UpdateHandler),
- ('/key/(.+)', keymaster.Handler({
- 'api-secret': ('c94d981ca589581cd270439854f08679', '1w5q7v3h'),
- })),], debug=True)
+ ], debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
Please sign in to comment.
Something went wrong with that request. Please try again.