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">×</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]