Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of github.com:hackerdojo/hd-captiveportal

  • Loading branch information...
commit d8a756b964974b511df69f4a8f69e8c08d528095 2 parents ffa2cf5 + 738d091
@progrium progrium authored
View
6 index.yaml
@@ -9,3 +9,9 @@ indexes:
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.
+
+- kind: MacAddressMapping
+ properties:
+ - name: username
+ - name: created
+ direction: desc
View
44 main.py
@@ -9,6 +9,7 @@
import base64
import urllib
import time
+import string
DOMAIN = 'hackerdojo.com'
MEMBER_DOWNLOAD = 0
@@ -56,6 +57,14 @@ def get_stat(name, resolution=60):
else:
return 0
+class Login(db.Model):
+ """ A non log of logins. """
+
+ address = db.StringProperty()
+ username = db.StringProperty()
+ created = db.DateTimeProperty(auto_now_add=True)
+
+
class MacAddressMapping(db.Model):
""" Member MAC address mapping
@@ -69,10 +78,31 @@ class MacAddressMapping(db.Model):
created = db.DateTimeProperty(auto_now_add=True)
@classmethod
+ def register_new_device(cls, address, username):
+ total_devices = 2
+ devices = cls.all().filter('username =', username).order("-created").fetch(100)
+ for d in devices[total_devices-1:]:
+ d.delete()
+ m = cls(address=address, username=username)
+ m.put()
+ return m
+
+
+ @classmethod
def get_by_mac(cls, address):
return cls.all().filter('address =', address).get()
+class LogHandler(webapp.RequestHandler):
+ """ Show log """
+
+ def get(self):
+ log = Login.all()
+ self.response.out.write(template.render('templates/log.html', {
+ 'log': log
+ }))
+
+
class EntryHandler(webapp.RequestHandler):
""" Entry point for the wifi app
@@ -99,17 +129,18 @@ class MemberHandler(webapp.RequestHandler):
def post(self):
client = AppsService(domain=DOMAIN)
- username = self.request.get('username')
+ username = string.split(self.request.get('username'),"@")[0].strip()
mac = self.request.get('mac')
redirect = self.request.get('redirect')
try:
- client.ClientLogin('%s@%s' % (username, DOMAIN), self.request.get('password'))
+ client.ClientLogin('%s@%s' % (username, DOMAIN), self.request.get('password').strip())
+ login = Login(username=username, address = mac)
+ login.put()
existing = MacAddressMapping.get_by_mac(mac)
if existing and not is_suspended(username):
self.redirect(redirect or DEFAULT_REDIRECT)
elif not is_suspended(username):
- m = MacAddressMapping(address=mac, username=username)
- m.put()
+ MacAddressMapping.register_new_device(mac,username)
self.redirect(redirect or DEFAULT_REDIRECT)
else:
raise Exception("Invalid account")
@@ -119,7 +150,7 @@ def post(self):
class GuestHandler(webapp.RequestHandler):
""" Form handler when connecting as a guest """
- def post(self):
+ def get(self):
memcache.set(self.request.get('mac'), GUEST_NAME, time=GUEST_TIMEOUT)
self.redirect(self.request.get('redirect') or DEFAULT_REDIRECT)
@@ -139,7 +170,7 @@ def post(self):
class DonateHandler(webapp.RequestHandler):
""" Form handler when donating for a day pass """
- def post(self):
+ def get(self):
mac = self.request.get('mac')
redirect = self.request.get('redirect') or DEFAULT_REDIRECT
callback = "%s/donate/%s" % (self.request.host_url, base64.b64encode(','.join([mac, redirect])))
@@ -215,6 +246,7 @@ def post(self):
def main():
application = webapp.WSGIApplication([
('/dev', DevHandler),
+ ('/log', LogHandler),
('/api/mac/(.+)', MacHandler),
('/api/stat/(.+)', StatHandler),
('/guest', GuestHandler),
View
3  static/.gitignore
@@ -0,0 +1,3 @@
+*.pyc
+*/*.pyc
+*/*/.pyc
View
338 static/960gs.css
@@ -0,0 +1,338 @@
+/*
+ Variable Grid System.
+ Learn more ~ http://www.spry-soft.com/grids/
+ Based on 960 Grid System - http://960.gs/
+
+ Licensed under GPL and MIT.
+*/
+
+
+/* Containers
+----------------------------------------------------------------------------------------------------*/
+.container_12 {
+ margin-left: auto;
+ margin-right: auto;
+ width: 960px;
+}
+
+/* Grid >> Global
+----------------------------------------------------------------------------------------------------*/
+
+.grid_1,
+.grid_2,
+.grid_3,
+.grid_4,
+.grid_5,
+.grid_6,
+.grid_7,
+.grid_8,
+.grid_9,
+.grid_10,
+.grid_11,
+.grid_12 {
+ display:inline;
+ float: left;
+ position: relative;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+/* Grid >> Children (Alpha ~ First, Omega ~ Last)
+----------------------------------------------------------------------------------------------------*/
+
+.alpha {
+ margin-left: 0;
+}
+
+.omega {
+ margin-right: 0;
+}
+
+/* Grid >> 12 Columns
+----------------------------------------------------------------------------------------------------*/
+
+.container_12 .grid_1 {
+ width:60px;
+}
+
+.container_12 .grid_2 {
+ width:140px;
+}
+
+.container_12 .grid_3 {
+ width:220px;
+}
+
+.container_12 .grid_4 {
+ width:300px;
+}
+
+.container_12 .grid_5 {
+ width:380px;
+}
+
+.container_12 .grid_6 {
+ width:460px;
+}
+
+.container_12 .grid_7 {
+ width:540px;
+}
+
+.container_12 .grid_8 {
+ width:620px;
+}
+
+.container_12 .grid_9 {
+ width:700px;
+}
+
+.container_12 .grid_10 {
+ width:780px;
+}
+
+.container_12 .grid_11 {
+ width:860px;
+}
+
+.container_12 .grid_12 {
+ width:940px;
+}
+
+
+
+/* Prefix Extra Space >> 12 Columns
+----------------------------------------------------------------------------------------------------*/
+
+.container_12 .prefix_1 {
+ padding-left:80px;
+}
+
+.container_12 .prefix_2 {
+ padding-left:160px;
+}
+
+.container_12 .prefix_3 {
+ padding-left:240px;
+}
+
+.container_12 .prefix_4 {
+ padding-left:320px;
+}
+
+.container_12 .prefix_5 {
+ padding-left:400px;
+}
+
+.container_12 .prefix_6 {
+ padding-left:480px;
+}
+
+.container_12 .prefix_7 {
+ padding-left:560px;
+}
+
+.container_12 .prefix_8 {
+ padding-left:640px;
+}
+
+.container_12 .prefix_9 {
+ padding-left:720px;
+}
+
+.container_12 .prefix_10 {
+ padding-left:800px;
+}
+
+.container_12 .prefix_11 {
+ padding-left:880px;
+}
+
+
+
+/* Suffix Extra Space >> 12 Columns
+----------------------------------------------------------------------------------------------------*/
+
+.container_12 .suffix_1 {
+ padding-right:80px;
+}
+
+.container_12 .suffix_2 {
+ padding-right:160px;
+}
+
+.container_12 .suffix_3 {
+ padding-right:240px;
+}
+
+.container_12 .suffix_4 {
+ padding-right:320px;
+}
+
+.container_12 .suffix_5 {
+ padding-right:400px;
+}
+
+.container_12 .suffix_6 {
+ padding-right:480px;
+}
+
+.container_12 .suffix_7 {
+ padding-right:560px;
+}
+
+.container_12 .suffix_8 {
+ padding-right:640px;
+}
+
+.container_12 .suffix_9 {
+ padding-right:720px;
+}
+
+.container_12 .suffix_10 {
+ padding-right:800px;
+}
+
+.container_12 .suffix_11 {
+ padding-right:880px;
+}
+
+
+
+/* Push Space >> 12 Columns
+----------------------------------------------------------------------------------------------------*/
+
+.container_12 .push_1 {
+ left:80px;
+}
+
+.container_12 .push_2 {
+ left:160px;
+}
+
+.container_12 .push_3 {
+ left:240px;
+}
+
+.container_12 .push_4 {
+ left:320px;
+}
+
+.container_12 .push_5 {
+ left:400px;
+}
+
+.container_12 .push_6 {
+ left:480px;
+}
+
+.container_12 .push_7 {
+ left:560px;
+}
+
+.container_12 .push_8 {
+ left:640px;
+}
+
+.container_12 .push_9 {
+ left:720px;
+}
+
+.container_12 .push_10 {
+ left:800px;
+}
+
+.container_12 .push_11 {
+ left:880px;
+}
+
+
+
+/* Pull Space >> 12 Columns
+----------------------------------------------------------------------------------------------------*/
+
+.container_12 .pull_1 {
+ left:-80px;
+}
+
+.container_12 .pull_2 {
+ left:-160px;
+}
+
+.container_12 .pull_3 {
+ left:-240px;
+}
+
+.container_12 .pull_4 {
+ left:-320px;
+}
+
+.container_12 .pull_5 {
+ left:-400px;
+}
+
+.container_12 .pull_6 {
+ left:-480px;
+}
+
+.container_12 .pull_7 {
+ left:-560px;
+}
+
+.container_12 .pull_8 {
+ left:-640px;
+}
+
+.container_12 .pull_9 {
+ left:-720px;
+}
+
+.container_12 .pull_10 {
+ left:-800px;
+}
+
+.container_12 .pull_11 {
+ left:-880px;
+}
+
+
+
+
+/* Clear Floated Elements
+----------------------------------------------------------------------------------------------------*/
+
+/* http://sonspring.com/journal/clearing-floats */
+
+.clear {
+ clear: both;
+ display: block;
+ overflow: hidden;
+ visibility: hidden;
+ width: 0;
+ height: 0;
+}
+
+/* http://perishablepress.com/press/2008/02/05/lessons-learned-concerning-the-clearfix-css-hack */
+
+.clearfix:after {
+ clear: both;
+ content: ' ';
+ display: block;
+ font-size: 0;
+ line-height: 0;
+ visibility: hidden;
+ width: 0;
+ height: 0;
+}
+
+.clearfix {
+ display: inline-block;
+}
+
+* html .clearfix {
+ height: 1%;
+}
+
+.clearfix {
+ display: block;
+}
View
BIN  static/Cabin-Regular.woff
Binary file not shown
View
BIN  static/dojo400.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  static/speed4.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
85 static/style.css
@@ -1,29 +1,56 @@
-body { font-family: Verdana,Arial,sans-serif; }
-#wrapper { margin-left: auto; margin-right: auto; width: 700px; }
-
-.note { font-size: x-small; color: ##444;}
-
-#header { margin-left: auto; margin-right: auto; width: 500px; height: 125px;}
-#header img { margin-right: 10px;}
-#header h1 { font-size: 42px; margin-top: 20px; padding-top: 10px; margin-bottom: 0px; padding-bottom: 0px;}
-#header h2 { font-size: x-large; margin: 0px; }
-
-.step span { color: white; background-color: #b10026; padding: 1px; padding-left: 4px; padding-right: 4px;}
-.step.inactive span { background-color: gray;}
-.step.inactive { color: gray; }
-
-h4 { margin-bottom: 0px; padding-left: 50px;}
-
-
-table .label { text-align: right; font-size: smaller;}
-
-form div { margin-top: 10px; }
-
-input.textbox { width: 100%; }
-
-h3 { margin-top: 0px;}
-
-.notice { background-color: lightyellow; border: 1px solid yellow; padding: 10px; font-size: smaller;}
-
-#member { width: 30%; float: right; background-color: #ddf8cc; border: 1px solid #80C65A; padding: 10px; margin-top: 10px;}
-#guest { width: 65%;}
+body, html {height:100%}
+body, td {font-family: Verdana,sans-serif; font-size: 15px; }
+body { background: #ddd; background: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#fff)) no-repeat; }
+.content { background: #fff; -webkit-box-shadow: 4px 4px 32px #666; margin-top:1em; -webkit-border-radius: 12px; -moz-border-radius: 12px; border-radius: 12px; }
+
+p {margin-top:.5em}
+
+h2 { font-family: arial, sans-serif; font-weight:normal; font-size:22px; width:550px; margin:.5em auto; text-align:center }
+h3 {margin-bottom:.5em; margin-top:1.5em}
+
+td,body,p,h2 {
+ font-family: 'Cabin', arial, serif;
+}
+
+@font-face {
+ font-family: 'Cabin';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Cabin Regular'), local('Cabin-Regular'), url('/static/Cabin-Regular.woff') format('woff');
+}
+
+.homeinput {
+ font: 13px "Lucida Grande",Arial,Sans-serif;
+ border-top-left-radius: 4px 4px;
+ border-top-right-radius: 4px 4px;
+ border-bottom-right-radius: 4px 4px;
+ border-bottom-left-radius: 4px 4px;
+ background: white;
+ padding: 5px;
+ width:90%;
+ border: 1px solid #bbb ;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ margin-left:4px;
+}
+
+
+.memberlogin {
+ background: #fff3f3;
+ border:2px solid #ffb5b5;
+ -webkit-border-radius: 12px;
+ -moz-border-radius: 12px;
+ border-radius: 12px;
+ width:300px;
+ padding:8px;
+}
+
+
+.note {
+ margin-top:1em;
+ font-size:11px;
+ width:300px;
+}
+
+a {color:#b61e44}
View
32 templates/base.html
@@ -1,19 +1,17 @@
-<html>
- <head>
- <title>Hacker Dojo Internet Access</title>
- <link href="/static/style.css" type="text/css" rel="stylesheet" />
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <link href='/static/960gs.css' rel='stylesheet' type='text/css'/>
+ <link href='/static/style.css' rel='stylesheet' type='text/css'/>
+ <link href='http://fonts.googleapis.com/css?family=Cabin' rel='stylesheet' type='text/css'>
+
+ <title>Hacker Dojo Internet</title>
{% block header %}{% endblock %}
- </head>
- <body>
- <div id="wrapper">
- <div id="header">
- <img src="/static/dojo_icon.png" style="float: left; " />
- <h1>Hacker Dojo</h1>
- <h2>Internet Access</h2>
- </div>
- <div id="content">
- {% block content %}{% endblock %}
- </div>
- </div>
- </body>
+ </head>
+<body>
+
+{% block content %}{% endblock %}
+
+</body>
</html>
View
24 templates/daypass.html
@@ -4,10 +4,24 @@
{% endblock %}
{% block content %}
- <div>
- <h2>Thanks for donating!</h2>
- <p>You now have member quality internet for the next {{hours}} hours. Enjoy! :)</p>
- <p>Redirecting to <a href="{{redirect}}">{{redirect}}</a> in the next five seconds...</p>
- </div>
+
+ <div class="container_12 content">
+ <div class="grid_12 alpha omega">
+
+ <img border=0 src="/static/dojo400.png" style="margin:2em" width="400" height="141" />
+
+
+ <h2 style="margin-top:2em; font-weight:strong">Thanks for donating!</h2>
+ <div style="margin:2em; text-align:center; font-size:18px">
+ <p>You now have member quality internet for the next {{hours}} hours.</p>
+ <p>Redirecting to <a href="{{redirect}}">{{redirect}}</a> in 5 seconds.</p>
+ </div>
+
+ </div>
+
+ <div class="clearfix" style="padding-bottom:6em">&nbsp;</div>
+
+
+ </div>
{% endblock %}
View
31 templates/log.html
@@ -0,0 +1,31 @@
+{% extends 'base.html' %}
+{% block content %}
+
+ <div class="container_12 content">
+ <div class="grid_12 alpha omega">
+
+ <img border=0 src="/static/dojo400.png" style="margin:2em" width="400" height="141" />
+
+ </div>
+
+ <br>
+
+ <div class="grid_12 alpha omega">
+
+ <div style="margin:2em">
+ <table width=100%>
+ {% for l in log %}
+ <tr><td>{{l.created}}</td><td>{{l.username}}</td><td>{{l.address}}</td></tr>
+ {% endfor %}
+ </table>
+ </div>
+
+ </div>
+
+
+
+ <div class="clearfix">&nbsp;</div>
+
+ </div>
+
+{% endblock %}
View
94 templates/main.html
@@ -1,36 +1,66 @@
{% extends 'base.html' %}
{% block content %}
- <div id="member">
- <h3>Member Access</h3>
- {% if error %}<span style="color: red; font-size: smaller;">{{error}}</span>{% endif %}
- <form method="post" action="/member">
- <table>
- <tr><td class="label">Username:</td><td width="100%"><input class="textbox" name="username" type="text" /></td></tr>
- <tr><td class="label"> </td>
- <td class="note" style="text-align:right;">@hackerdojo.com</td></tr>
- <tr><td class="label">Password:</td><td width="100%"><input class="textbox" name="password" type="password" /></td></tr>
- </table>
- <input type="hidden" name="redirect" value="{{redirect}}" />
- <input type="hidden" name="mac" value="{{mac}}" />
- <div style="text-align: center; margin-bottom: 10px;"><input name="accept" type="submit" value="Continue as Member &rarr;" /></div>
- </form>
- <div class="note">We'll remember your MAC address, so you shouldn't see this screen again.</div>
- </div>
-
- <div id="guest">
- <h2>Welcome to Hacker Dojo!</h2>
- <p class="notice">You're using <strong>HackerDojo-gwifi</strong>, which is currently running a beta of our new captive portal that will be on our new fiber connection coming in early 2011. It will allow us to easily provide unlimited access to members, throttle access to guests, and perhaps even eliminate the sign-in kiosk.<br /><br />
- Email <a href="mailto:internet@hackerdojo.com">internet@hackerdojo.com</a> for questions or feedback.</p>
- <form method="post" action="/guest" style="text-align: center;">
- <input type="hidden" name="redirect" value="{{redirect}}" />
- <input type="hidden" name="mac" value="{{mac}}" />
- <input name="accept" type="submit" value="Continue as Guest &rarr;" />
- </form>
- <form method="post" action="/donate" style="text-align: center;">
- <input type="hidden" name="redirect" value="{{redirect}}" />
- <input type="hidden" name="mac" value="{{mac}}" />
- <input name="accept" type="submit" value="Donate $10 for Day Pass &rarr;" />
- </form>
- </div>
+ <div class="container_12 content">
+ <div class="grid_12 alpha omega">
+
+ <img border=0 src="/static/dojo400.png" style="margin:1.5em" width="400" height="141" />
+ <h2><b>FIBER Internet has arrived!</b> Members, login below to gain full access to your new connection. Guests may have unlimited free usage of our slower connection.</h2>
+
+ </div>
+
+ <br>
+
+ <div class="grid_6 alpha ">
+
+ <div style="margin:4em">
+ <center>
+ <img border=0 src="/static/speed4.png" width="350" height="249"/>
+ <p style="font-size:12px"><b>Fig. 1.</b> Members get full <b>100Mbps</b> fiber Internet.</p>
+ </center>
+ </div>
+
+ </div>
+
+ <div class="grid_5 omega">
+
+
+ <div style="margin-top:1.5em">
+ <h3>Members</h3>
+ <form method="post" action="/member" class="memberlogin">
+
+ {% if error %}<p style="color: red; font-size: smaller; font-weight:bold">{{error|escape}}</p>{% endif %}
+ <table cellpadding=0 cellspacing=1 border="0" width="100%">
+ <tr><td class="label">Username:</td><td width="100%"><input class="textbox homeinput" name="username" type="text" placeholder="ex: joe.smith" /></td></tr>
+ <tr><td class="label">Password:</td><td width="100%"><input class="textbox homeinput" name="password" type="password" /></td></tr>
+ </table>
+ <input type="hidden" name="redirect" value="{{redirect}}" />
+ <input type="hidden" name="mac" value="{{mac}}" />
+ <div style="text-align: center; margin-top: 8px;"><input name="accept" type="submit" value="Login" /></div>
+ </form>
+ </div>
+
+ <p class="note"> Members: We'll remember your MAC address, so you shouldn't see this screen again.</p>
+
+ <h3>Day Pass</h3>
+ <p>Guests may <a href="/donate?mac={{mac|urlencode}}&redirect={{redirect|urlencode}}">donate $10</a> for a day pass.</p>
+
+ <h3>Guests</h3>
+ <p>Guests are also welcome to our <a href="/guest?mac={{mac|urlencode}}&redirect={{redirect|urlencode}}">slower free connection</a>.</p>
+
+ <br/>
+
+
+ </div>
+
+ <div class="clearfix">&nbsp;</div>
+ <div class="grid_12">
+
+
+
+ </div>
+
+ <div class="clearfix">&nbsp;</div>
+ </div>
+
{% endblock %}
Please sign in to comment.
Something went wrong with that request. Please try again.