--- a/pvl/login/server.py Mon Jan 13 02:46:18 2014 +0200
+++ b/pvl/login/server.py Mon Jan 13 03:20:04 2014 +0200
@@ -28,6 +28,10 @@
def redirect (self, *url, **params) :
return pvl.web.response.redirect(self.url(*url, **params))
+ pubtkt = None
+ cookie_error = None
+ verify_error = None
+
def process_cookie (self) :
"""
Reverse the urlencoding used for the cookie...
@@ -37,27 +41,34 @@
cookie = self.request.cookies.get(self.app.cookie_name)
+ if not cookie :
+ return
+
log.debug("cookie %s=%s", self.app.cookie_name, cookie)
- if cookie :
- cookie = werkzeug.urls.url_unquote(cookie)
+ cookie = werkzeug.urls.url_unquote(cookie)
log.debug("cookie decoded: %s", cookie)
- if cookie :
- return self.app.load(cookie)
+ if not cookie :
+ return
+
+ try :
+ self.pubtkt = self.app.load(cookie)
+
+ except pubtkt.ParseError as ex :
+ self.cookie_error = ex
+
+ except pubtkt.VerifyError as ex :
+ self.pubtkt = ex.pubtkt
+ self.verify_error = ex
+
class Index (Handler) :
TITLE = u"Päivölä Network Login"
- pubtkt = None
- cookie_error = None
-
def process (self) :
- try :
- self.pubtkt = self.process_cookie()
- except pubtkt.Error as ex :
- self.cookie_error = ex
+ self.process_cookie()
if not self.pubtkt :
return self.redirect(Login)
@@ -70,46 +81,79 @@
return "%2d:%02d:%02d" % (hours, minutes, seconds)
+ def render_status (self, pubtkt) :
+ valid = pubtkt.valid()
+ grace = pubtkt.grace()
+
+ if valid and grace :
+ return 'success'
+ elif valid and grace is False :
+ return 'warning'
+ elif valid :
+ return 'success'
+ else :
+ return 'danger'
+
def render_pubtkt_fields (self, pubtkt) :
"""
Yield (glyphicon, text) to render as fields for ticket.
"""
- yield 'user', "User account", pubtkt.uid
-
- valid = self.render_valid(pubtkt.valid())
+ yield 'user', None, "User account", pubtkt.uid
- if pubtkt.graceperiod :
- valid = "{valid} ({grace})".format(valid=valid, grace=self.render_valid(pubtkt.grace()))
+ valid = pubtkt.valid()
+ grace = pubtkt.grace()
- yield 'time', "Remaining validity", valid
+ if valid and grace :
+ valid = "{valid} ({grace})".format(valid=self.render_valid(valid), grace=self.render_valid(grace))
+ valid_status = 'success'
+ elif valid and grace is False :
+ valid = "Renewable ({grace})".format(valid=self.render_valid(valid), grace=self.render_valid(grace))
+ valid_status = 'warning'
+ elif valid :
+ valid = "{valid}".format(valid=self.render_valid(valid))
+ valid_status = 'success'
+ else :
+ valid = "Expired"
+ valid_status = 'danger'
+
+ yield 'time', valid_status, "Remaining validity", valid
if pubtkt.cip :
- yield 'cloud', "Network address", pubtkt.cip
+ yield 'cloud', None, "Network address", pubtkt.cip
if pubtkt.udata :
- yield 'comment', "Associated data", pubtkt.udata
+ yield 'comment', None, "Associated data", pubtkt.udata
for token in pubtkt.tokens :
- yield 'flag', "Access token", token
+ yield 'flag', None, "Access token", token
if pubtkt.bauth :
- yield 'keys', "Authentication token", pubtkt.bauth
+ yield 'keys', None, "Authentication token", pubtkt.bauth
def render_pubtkt (self, pubtkt) :
- return html.div(class_='panel panel-info')(
+ status = self.render_status(pubtkt)
+
+ return html.div(class_='panel panel-{status}'.format(status=status))(
html.div(class_='panel-heading')("Login: {pubtkt.uid}".format(pubtkt=self.pubtkt)),
- html.div(class_='panel-body')(
- "This is a valid login ticket.",
- ),
html.ul(class_='list-group')(
- html.li(class_='list-group-item', title=title)(
+ html.li(class_='list-group-item {status}'.format(status=('alert-'+status if status else '')), title=title)(
html.span(class_='glyphicon glyphicon-{glyphicon}'.format(glyphicon=icon)) if icon else None,
info,
- ) for icon, title, info in self.render_pubtkt_fields(pubtkt)
+ ) for icon, status, title, info in self.render_pubtkt_fields(pubtkt)
),
html.div(class_='panel-footer')(
- html.form(action='/logout', method='post')(
+ (
+ html.form(action=self.url(Login), method='post')(
+ html.button(type='submit', class_='btn btn-success')("Renew"),
+ )
+ ) if pubtkt.valid() else (
+ html.form(action=self.url(Login), method='get')(
+ html.button(type='submit', class_='btn btn-info')("Login"),
+ ),
+ ),
+
+ html.form(action=self.url(Logout), method='post')(
html.button(type='submit', class_='btn btn-warning')("Logout"),
),
),
@@ -142,10 +186,9 @@
"""
+ def process (self) :
+ self.process_cookie()
- auth_error = None
-
- def process (self) :
if self.request.method == 'POST' :
back = self.app.login_server
username = self.request.form.get('username')
@@ -156,28 +199,39 @@
username = username.strip().lower()
try :
- pt = self.app.auth(username, password)
+ self.pubtkt = self.app.auth(username, password)
except pubtkt.Error as ex :
self.auth_errors = ex
-
- else :
- # browsers seem to be very particular about quoting ;'s in cookie values...
- # this follows PHP's setcookie() encoding...
- cookie = werkzeug.urls.url_quote(self.app.sign(pt))
+
+ elif self.pubtkt and self.pubtkt.valid() :
+ # renew
+ self.app.renew(self.pubtkt)
- # redirect with cookie
- response = pvl.web.response.redirect(back)
+ else :
+ return
- response.set_cookie(self.app.cookie_name, cookie,
- domain = self.app.cookie_domain,
- secure = self.app.cookie_secure,
- httponly = self.app.cookie_httponly,
- )
+ # browsers seem to be very particular about quoting ;'s in cookie values...
+ # this follows PHP's setcookie() encoding...
+ cookie = werkzeug.urls.url_quote(self.app.sign(self.pubtkt))
- return response
+ # redirect with cookie
+ response = pvl.web.response.redirect(back)
+
+ response.set_cookie(self.app.cookie_name, cookie,
+ domain = self.app.cookie_domain,
+ secure = self.app.cookie_secure,
+ httponly = self.app.cookie_httponly,
+ )
+
+ return response
def render (self) :
+ if self.pubtkt :
+ username = self.pubtkt.uid
+ else :
+ username = None
+
domain = self.app.login_domain
return html.div(class_='container')(
@@ -188,7 +242,7 @@
html.div(class_='form-group')(
html.div(class_='input-group')(
html.label(for_='username', class_='sr-only')("Username"),
- html.input(name='username', type='text', class_='form-control', placeholder="username", required=True, autofocus=True),
+ html.input(name='username', type='text', class_='form-control', placeholder="username", required=True, autofocus=True, value=username),
html.span(class_='input-group-addon')("@{domain}".format(domain=domain)),
),
@@ -205,11 +259,7 @@
TITLE = "Logout"
def process (self) :
- try :
- self.pubtkt = self.process_cookie()
- except Error as ex :
- self.pubtkt_error = ex
- self.pubtkt = ex.pubtkt
+ self.process_cookie()
if not self.pubtkt :
return self.redirect(Index)
@@ -251,7 +301,7 @@
login_domain = 'test.paivola.fi'
login_server = 'https://login.test.paivola.fi/'
- login_expire = datetime.timedelta(hours=1)
+ login_expire = datetime.timedelta(seconds=60)
cookie_name = 'auth_pubtkt'
cookie_domain = 'test.paivola.fi'
@@ -289,3 +339,9 @@
return pubtkt.sign(self.server_keys.private)
+ def renew (self, pubtkt) :
+ """
+ Renew and re-sign the given pubtkt.
+ """
+
+ pubtkt.renew(self.login_expire)