diff --git a/controllers/admin.py b/controllers/admin.py
new file mode 100644
index 0000000..5de5268
--- /dev/null
+++ b/controllers/admin.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
+
+from decorators import WSGISimpleAuth # decoratore ( singleton )
+auth = WSGISimpleAuth()
+
+@auth.require( 'admin superadmin hyperadmin' )
+def application( environ, start_response ):
+ storage = environ['auth.storage']
+
+ start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
+
+ return [
+ "
GOSH BATMAN! HOW DID SHE DO THE IMPOSSIBLE?
",
+ "index"
+ ]
diff --git a/controllers/demo/due.py b/controllers/demo/due.py
index 7628023..82cda5b 100644
--- a/controllers/demo/due.py
+++ b/controllers/demo/due.py
@@ -18,4 +18,4 @@ def application( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
- return [ html, '
', '', pformat( environ, width=132 ), '
' ] # TODO: pformat..... ---> trasformarlo in un decoratore
+ return [ html, '
', '', pformat( environ, width=132 ), '
' ]
diff --git a/controllers/forbidden.py b/controllers/forbidden.py
new file mode 100644
index 0000000..b00bbd4
--- /dev/null
+++ b/controllers/forbidden.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
+
+from decorators import WSGISimpleAuth # decoratore ( singleton )
+auth = WSGISimpleAuth()
+
+def application( environ, start_response ):
+ start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
+
+ return [
+ "",
+ "FORBIDDEN
",
+ "
",
+ "
",
+ "Maybe you should go back to index",
+ ""
+ ]
diff --git a/controllers/login.py b/controllers/login.py
new file mode 100644
index 0000000..ff84c46
--- /dev/null
+++ b/controllers/login.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
+
+from decorators import WSGISimpleAuth # decoratore ( singleton )
+auth = WSGISimpleAuth()
+
+@auth.require()
+def application( environ, start_response ):
+ storage = environ['auth.storage']
+
+ import cgi
+ post_environ = environ.copy()
+ post_environ['QUERY_STRING'] = ''
+ post = cgi.FieldStorage(
+ fp=environ['wsgi.input'],
+ environ=post_environ,
+ keep_blank_values=True
+ )
+
+ if 'password' in post:
+ password = post['password'].value
+ storage['permissions'] = [ 'auth' ]
+ html = [
+ "You are logged in, now you can see the Secret page.",
+ ]
+
+ else:
+ storage['timeout'] = -1
+ html = [
+ "",
+ ]
+
+ start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
+
+ return html
+
+
diff --git a/controllers/logout.py b/controllers/logout.py
new file mode 100644
index 0000000..f9f1c1d
--- /dev/null
+++ b/controllers/logout.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
+
+from decorators import WSGISimpleAuth # decoratore ( singleton )
+auth = WSGISimpleAuth()
+
+@auth.require()
+def application( environ, start_response ):
+ storage = environ['auth.storage']
+
+ storage['timeout'] = -1
+
+ start_response( '200 OK', [('content-type', 'text/html; charset=utf-8')] )
+
+ return [
+ "Now you are logged out
",
+ "index"
+ ]
+
diff --git a/controllers/secret.py b/controllers/secret.py
index d558f78..0b338f3 100644
--- a/controllers/secret.py
+++ b/controllers/secret.py
@@ -4,7 +4,7 @@
from decorators import WSGISimpleAuth # decoratore ( singleton )
auth = WSGISimpleAuth()
-@auth.require()
+@auth.require( 'auth' )
def application( environ, start_response ):
storage = environ['auth.storage']
@@ -14,4 +14,5 @@ def application( environ, start_response ):
"The secret code is:
",
"''keep calm and carry on''
"
"uuid:%s
" % environ['auth.uuid'],
+ "index"
]
diff --git a/decorators.py b/decorators.py
index d7cccce..be9c8cd 100644
--- a/decorators.py
+++ b/decorators.py
@@ -158,7 +158,7 @@ class WSGISimpleAuth( object ):
"""Generate a unique session ID"""
return hashlib.sha256(
str(os.getpid())
- + str(time())
+ + str(time.time())
+ str(random.random())
).hexdigest()
@@ -169,7 +169,7 @@ class WSGISimpleAuth( object ):
self._lock.release()
- def require( self, permission='', group='', p_g_mode='AND', p_mode='OR', g_mode='OR' ):
+ def require( self, permissions=[], groups=[], p_g_mode='AND', p_mode='OR', g_mode='OR' ):
def real_decorator( wsgi_application ):
def wrapper( environ, start_response ):
#--------------------------------------------------------------
@@ -185,6 +185,8 @@ class WSGISimpleAuth( object ):
#
# salva le informazioni legate al cookie
#
+ timeout = storage.get( 'timeout', self.__timeout )
+ storage['epoch_timeout'] = time.time() + timeout
storage['epoch_write'] = time.time()
self.acquire_lock() ## LOCK
@@ -203,6 +205,7 @@ class WSGISimpleAuth( object ):
start_response( status, response_headers );
#--------------------------------------------------------------
+
#
# recupera UUID dal cookie
#
@@ -218,24 +221,56 @@ class WSGISimpleAuth( object ):
self.acquire_lock() ## LOCK
- f = open( path, 'r' )
-
try:
+ f = open( path, 'r' )
storage = cPickle.load( f )
+ f.close()
+
+ if storage['epoch_timeout'] < time.time():
+ # dati scaduti rimuove il file dei permessi..
+ os.unlink( path )
+
+ # ... e finge di non everlo mai trovato
+ raise Exception
+
+ logged_in = True
+
except:
# UUID assente, crea una nuova struttura dati
storage = {
'epoch_created': time.time(),
'permissions': [],
'groups': [],
+ 'timeout': self.__timeout
}
- f.close()
+ logged_in = False
self.release_lock() ## RELEASE
storage['epoch_read'] = time.time()
+ if permissions:
+ if isinstance( permissions, str ):
+ p = permissions.split()
+ else:
+ p = permissions
+
+ if not logged_in:
+ # non autenticato -> redirect to 'login_url'
+ start_response( '302 Found', [('Location', '/login'),] )
+ yield 'Please login first.' % '/login'
+ return
+
+ for perm in p:
+ if perm in storage['permissions']:
+ break
+ else:
+ # permessi insufficienti -> redirect to 'forbidden_url'
+ start_response( '302 Found', [('Location', '/forbidden'),] )
+ yield 'This page is not for your eyes.'
+ return
+
#
# popola environ
#
@@ -258,7 +293,7 @@ class WSGISimpleAuth( object ):
"""
{
uuid: jkfghkjgdhfgkjlsk,
- permission=[],
+ permissions=[],
groups=[],
timeout=3600
}
@@ -267,7 +302,7 @@ class WSGISimpleAuth( object ):
{
uuid: jkfghkjgdhfgkjlsk,
- permission=[],
+ permissions=[],
groups=[],
timeout=3600
}
diff --git a/dispatch_wsgi.py b/dispatch_wsgi.py
index 0367835..ec6716e 100755
--- a/dispatch_wsgi.py
+++ b/dispatch_wsgi.py
@@ -52,7 +52,7 @@ from router import WSGIRouter, WSGISmartRouter
#
def index( environ, start_response ):
start_response( '200 OK', [('content-type', 'text/html')] )
- return [ 'Index was here' ]
+ return [ 'Index was here' ]
#
# hello: esempio minimo di applicazione WSGI
diff --git a/router.py b/router.py
index 4263180..503ea9a 100644
--- a/router.py
+++ b/router.py
@@ -78,8 +78,7 @@ class WSGISmartRouter(object):
tokens = [ token for token in environ['SCRIPT_URL'].split('/') if token ]
#for idx in range( 1, len( tokens ) + 1 ): # from shortest path to longest one
- # from longest path to shortest one
- for idx in range( len( tokens ) , 0, -1 ):
+ for idx in range( len( tokens ) , 0, -1 ): # from longest path to shortest one
module = os.path.normpath( self.cont_dir + '/'.join( tokens[:idx] ) + '.py' )
args = tokens[idx:]
@@ -88,8 +87,6 @@ class WSGISmartRouter(object):
environ['router.args'] = args
if environ['REQUEST_METHOD'] == 'GET' and hasattr( handler, 'get' ):
- # FIXME: forse รจ meglio eseguire QUI la start_response
- # e compilare il template (solo per GET e POST)
return handler.get( environ, start_response )
elif environ['REQUEST_METHOD'] == 'POST' and hasattr( handler, 'post' ):
diff --git a/static/attack_dog.jpg b/static/attack_dog.jpg
new file mode 100644
index 0000000..0fdd63a
Binary files /dev/null and b/static/attack_dog.jpg differ
diff --git a/static/index.html b/static/index.html
index 84e1ecd..0362da4 100644
--- a/static/index.html
+++ b/static/index.html
@@ -12,7 +12,10 @@
test autorouting
test autorouting (longest path possible)
test sql access
- test authenticated
+ login
+ secret page
+ admin page (you have no permissions)
+ logout