Author: adc
Date: Sun Sep 15 20:20:02 2013
New Revision: 1523498

URL: http://svn.apache.org/r1523498
Log:
Added login/logout capabilities

Added:
    labs/panopticon/src/asf/panopticon/templates/error.html
    labs/panopticon/src/asf/panopticon/templates/forbidden.html
    labs/panopticon/src/asf/panopticon/templates/not_found.html
Modified:
    labs/panopticon/requirements.txt
    labs/panopticon/src/asf/panopticon/__init__.py
    labs/panopticon/src/asf/panopticon/static/css/panopticon.css
    labs/panopticon/src/asf/panopticon/templates/index.html
    labs/panopticon/src/asf/panopticon/templates/layout.html

Modified: labs/panopticon/requirements.txt
URL: 
http://svn.apache.org/viewvc/labs/panopticon/requirements.txt?rev=1523498&r1=1523497&r2=1523498&view=diff
==============================================================================
--- labs/panopticon/requirements.txt (original)
+++ labs/panopticon/requirements.txt Sun Sep 15 20:20:02 2013
@@ -1,6 +1,7 @@
 argparse
 brownie
 Flask
+Flask-Principal
 keyring==1.6.1
 mock
 nose

Modified: labs/panopticon/src/asf/panopticon/__init__.py
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/__init__.py?rev=1523498&r1=1523497&r2=1523498&view=diff
==============================================================================
--- labs/panopticon/src/asf/panopticon/__init__.py (original)
+++ labs/panopticon/src/asf/panopticon/__init__.py Sun Sep 15 20:20:02 2013
@@ -16,28 +16,112 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+from logging import getLogger
 
-from flask import Flask, render_template, abort, request
+from flask import Flask, render_template, request, redirect, flash, 
current_app, g, abort, session
+from flask.ext.principal import identity_changed, Identity, Principal, 
identity_loaded
+from flask.ext import principal
+
+from asf.data import ldap
+from asf.person import Person
 
 
 app = Flask(__name__)
+app.secret_key = 'DhMHc1FZ/veGr+R/VOdzOmMWd'
+
+log = getLogger(__name__)
+
 
 @app.route('/')
 def hello_world():
     return render_template('index.html')
 
+
[email protected]_request
+def before_request():
+    g.login_allowed = current_app.debug or request.scheme == 'https'
+
+
 @app.route('/login', methods=['POST'])
 def login():
     if not g.login_allowed:
         abort(403)
+
     username = request.form.get('username')
     password = request.form.get('password')
     if ldap.check_user_password(username, password):
-        identity_changed.send(tools_base, identity=Identity(username))
+        identity_changed.send(app, identity=Identity(username))
         flash(u'Signed in as ' + username, 'success')
     else:
-        flash(u'Invalid username or password', 'error')
+        flash(u'Invalid username or password', 'danger')
     return redirect(request.referrer)
 
+
[email protected]('/logout')
+def logout():
+    identity_changed.send(app, identity=None)
+    flash(u'You have been signed out', 'success')
+    return redirect(request.referrer)
+
+
+is_authenticated = principal.Permission(principal.RoleNeed('authenticated'))
+login_required = is_authenticated.require(401)
+
+# workaround some bugs with the default session identities
+
+def session_identity_loader():
+    if 'identity.name' in session and 'identity.auth_type' in session:
+        identity = Identity(session['identity.name'],
+                            session['identity.auth_type'])
+        return identity
+    else:
+        return principal.AnonymousIdentity()
+
+
+def session_identity_saver(identity):
+    if identity is None or not identity.is_authenticated:
+        session.pop('identity.name', None)
+        session.pop('identity.auth_type', None)
+    else:
+        session['identity.name'] = identity.name
+        session['identity.auth_type'] = identity.auth_type
+    session.modified = True
+
+
+principals = Principal(app, use_sessions=False)
+principals.identity_loader(session_identity_loader)
+principals.identity_saver(session_identity_saver)
+
+
+@identity_loaded.connect
+def on_identity_loaded(sender, identity):
+    if identity is None:
+        return
+
+    identity.is_authenticated = not isinstance(identity, 
principal.AnonymousIdentity)
+    if identity.is_authenticated:
+        person = Person(identity.name)
+        identity.person = person
+        identity.provides.add(principal.RoleNeed('authenticated'))
+    else:
+        identity.person = None
+
+
[email protected](404)
+def not_found_handler(error):
+    return render_template('not_found.html'), 404
+
+
[email protected](500)
+def error_handler(error):
+    return render_template('error.html'), 500
+
+
[email protected](401)
[email protected](403)
+def forbidden_handler(error):
+    return render_template('forbidden.html'), 403
+
+
 if __name__ == '__main__':
-    app.run()
+    app.run(debug=False)

Modified: labs/panopticon/src/asf/panopticon/static/css/panopticon.css
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/static/css/panopticon.css?rev=1523498&r1=1523497&r2=1523498&view=diff
==============================================================================
--- labs/panopticon/src/asf/panopticon/static/css/panopticon.css (original)
+++ labs/panopticon/src/asf/panopticon/static/css/panopticon.css Sun Sep 15 
20:20:02 2013
@@ -1,6 +1,3 @@
-/* Sticky footer styles
--------------------------------------------------- */
-
 html,
 body {
     height: 100%;
@@ -24,7 +21,6 @@ body {
     background-color: #f5f5f5;
 }
 
-
 /* Custom page CSS
 -------------------------------------------------- */
 /* Not required for template or sticky footer method. */
@@ -32,6 +28,7 @@ body {
 #wrap > .container {
     padding: 60px 15px 0;
 }
+
 .container .credit {
     margin: 20px 0;
 }
@@ -44,3 +41,7 @@ body {
 code {
     font-size: 80%;
 }
+
+p.text-warning.navbar-text {
+    color: #c09853;
+}

Added: labs/panopticon/src/asf/panopticon/templates/error.html
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/templates/error.html?rev=1523498&view=auto
==============================================================================
--- labs/panopticon/src/asf/panopticon/templates/error.html (added)
+++ labs/panopticon/src/asf/panopticon/templates/error.html Sun Sep 15 20:20:02 
2013
@@ -0,0 +1,12 @@
+{% extends 'layout.html' %}
+
+{% block content %}
+<div class="alert alert-block alert-error">
+    <h1 class="alert-heading">500 Internal Server Error</h1>
+    <p>
+        The server encountered an internal error and was unable to complete 
your
+        request. Either the server is overloaded or there is an error in the
+        application.
+    </p>
+</div>
+{% endblock %}

Added: labs/panopticon/src/asf/panopticon/templates/forbidden.html
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/templates/forbidden.html?rev=1523498&view=auto
==============================================================================
--- labs/panopticon/src/asf/panopticon/templates/forbidden.html (added)
+++ labs/panopticon/src/asf/panopticon/templates/forbidden.html Sun Sep 15 
20:20:02 2013
@@ -0,0 +1,28 @@
+{% extends "layout.html" %}
+
+
+{% block content %}
+{% if g.identity.is_authenticated %}
+<div class="alert alert-block alert-error">
+    <p><strong>You do not have permission to access this page</strong></p>
+    <p>You can <a href="{{ url_for('logout') }}">sign out</a> to log in as a 
different user.</p>
+</div>
+{% elif g.login_allowed %}
+<p class="alert alert-warning">
+    <strong>Please sign in to access this page</strong>
+</p>
+
+<form action="{{ url_for('login') }}" method="POST">
+    <p>
+        <input name="username" class="span3" type="text" 
placeholder="Username">
+        <input  name="password" class="span3" type="password" 
placeholder="Password">
+        <button class="btn" type="submit">Sign in</button>
+    </p>
+</form>
+{% else %}
+<div class="alert alert-block alert-error">
+    <p><strong>Login disabled over insecure connection</strong></p>
+    <p>For security reasons, login is only enabled over HTTPS.</p>
+</div>
+{% endif %}
+{% endblock %}

Modified: labs/panopticon/src/asf/panopticon/templates/index.html
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/templates/index.html?rev=1523498&r1=1523497&r2=1523498&view=diff
==============================================================================
--- labs/panopticon/src/asf/panopticon/templates/index.html (original)
+++ labs/panopticon/src/asf/panopticon/templates/index.html Sun Sep 15 20:20:02 
2013
@@ -1 +1,5 @@
 {% extends "layout.html" %}
+
+{% block content %}
+
+{% endblock %}

Modified: labs/panopticon/src/asf/panopticon/templates/layout.html
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/templates/layout.html?rev=1523498&r1=1523497&r2=1523498&view=diff
==============================================================================
--- labs/panopticon/src/asf/panopticon/templates/layout.html (original)
+++ labs/panopticon/src/asf/panopticon/templates/layout.html Sun Sep 15 
20:20:02 2013
@@ -23,6 +23,20 @@
 </head>
 
 <body data-spy="scroll" data-target=".topbar" data-offset="90">
+{% macro flash_messages() %}
+<ul class="flashes list-unstyled">
+    {% with messages = get_flashed_messages(with_categories=true) %}
+    {% if messages %}
+    {% for category, message in messages %}
+    <li class="alert alert-{{ category }} alert-dismissable">
+        {{ message }}
+        <button type="button" class="close" data-dismiss="alert" 
aria-hidden="true">&times;</button>
+    </li>
+    {% endfor %}
+    {% endif %}
+    {% endwith %}
+</ul>
+{% endmacro %}
 
 <!-- Begin page content -->
 <!-- Wrap all page content here -->
@@ -57,27 +71,36 @@
                         </ul>
                     </li>
                 </ul>
-                <form class="navbar-form navbar-right">
+                {% if g.identity.is_authenticated %}
+                <p class="navbar-text pull-right">
+                    Logged in as
+                    <a href="#" rel="user"
+                       data-username="{{ g.identity.id }}"
+                            >{{ g.identity.name }}</a>  |
+                    <a href="{{ url_for('logout') }}">Sign out</a>
+                </p>
+                {% elif g.login_allowed%}
+                <form action="{{ url_for('login') }}" method="POST" 
class="login navbar-right navbar-form form-group">
                     <div class="form-group">
-                        <input type="text" placeholder="Apache Id" 
class="form-control">
+                        <input name="username" type="text" placeholder="Apache 
Id" class="form-control">
                     </div>
                     <div class="form-group">
-                        <input type="password" placeholder="Password" 
class="form-control">
+                        <input name="password" type="password" 
placeholder="Password" class="form-control">
                     </div>
                     <button type="submit" class="btn btn-success">Sign 
in</button>
                 </form>
+                {% else %}
+                <p class="pull-right text-warning navbar-text">Login disabled 
over insecure connection</p>
+                {% endif %}
             </div>
             <!--/.nav-collapse -->
         </div>
     </div>
 
     <div class="container">
-        <div class="page-header">
-            <h1>Sticky footer with fixed navbar</h1>
-        </div>
-        <p class="lead">Pin a fixed-height footer to the bottom of the 
viewport in desktop browsers with this custom HTML and CSS. A fixed navbar has 
been added within <code>#wrap</code> with <code>padding-top: 60px;</code> on 
the <code>.container</code>.</p>
+        {{ flash_messages() }}
 
-        <p>Back to <a href="../sticky-footer">the default sticky footer</a> 
minus the navbar.</p>
+        {{ self.content() }}
     </div>
 </div>
 

Added: labs/panopticon/src/asf/panopticon/templates/not_found.html
URL: 
http://svn.apache.org/viewvc/labs/panopticon/src/asf/panopticon/templates/not_found.html?rev=1523498&view=auto
==============================================================================
--- labs/panopticon/src/asf/panopticon/templates/not_found.html (added)
+++ labs/panopticon/src/asf/panopticon/templates/not_found.html Sun Sep 15 
20:20:02 2013
@@ -0,0 +1,9 @@
+{% extends 'layout.html' %}
+
+{% block content %}
+<div class="alert alert-block alert-error">
+    <h1 class="alert-heading">404 Not Found</h1>
+    <p>The requested URL was not found on the server.</p>
+    <p>If you entered the URL manually please check your spelling and try 
again.</p>
+</div>
+{% endblock %}



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to