diff options
author | Cédric Bonhomme <kimble.mandel@gmail.com> | 2013-10-30 23:44:56 +0100 |
---|---|---|
committer | Cédric Bonhomme <kimble.mandel@gmail.com> | 2013-10-30 23:44:56 +0100 |
commit | 594aec6929519399307c057a7bedfd448e7d26be (patch) | |
tree | 103d93d3210cbb250060cd61f8c95c7bd38d59bd | |
parent | this sort is enough fast (diff) | |
download | newspipe-594aec6929519399307c057a7bedfd448e7d26be.tar.gz newspipe-594aec6929519399307c057a7bedfd448e7d26be.tar.bz2 newspipe-594aec6929519399307c057a7bedfd448e7d26be.zip |
Added authentication with Flask-Login.
-rw-r--r-- | pyaggr3g470r/__init__.py | 9 | ||||
-rw-r--r-- | pyaggr3g470r/forms.py | 18 | ||||
-rw-r--r-- | pyaggr3g470r/models.py | 6 | ||||
-rw-r--r-- | pyaggr3g470r/templates/layout.html | 15 | ||||
-rw-r--r-- | pyaggr3g470r/templates/login.html | 29 | ||||
-rw-r--r-- | pyaggr3g470r/views.py | 75 |
6 files changed, 138 insertions, 14 deletions
diff --git a/pyaggr3g470r/__init__.py b/pyaggr3g470r/__init__.py index 3d63d9de..64b25b96 100644 --- a/pyaggr3g470r/__init__.py +++ b/pyaggr3g470r/__init__.py @@ -5,7 +5,7 @@ import os from flask import Flask, session, g from flask.ext.mongoengine import MongoEngine -#from flask.ext.login import AnonymousUserMixin +from flask.ext.login import LoginManager, AnonymousUserMixin from flask.ext.admin import Admin from flask.ext.admin.contrib.mongoengine import ModelView @@ -13,7 +13,7 @@ from flask.ext.admin.contrib.mongoengine import ModelView import conf from models import * -# Create Flask applicatio +# Create Flask application app = Flask(__name__) app.debug = True @@ -37,6 +37,10 @@ mail.init_app(app) # Administration panel admin = Admin(app, name='pyAggr3g470r') # Add administrative views here +class UserView(ModelView): + column_filters = ['firstname', 'lastname'] + + column_searchable_list = ('firstname', 'lastname') class FeedView(ModelView): column_filters = ['title', 'link'] @@ -47,6 +51,7 @@ class ArticleView(ModelView): column_searchable_list = ('title', 'link') admin.add_view(FeedView(Feed)) admin.add_view(ArticleView(Article)) +admin.add_view(UserView(User)) from pyaggr3g470r import views
\ No newline at end of file diff --git a/pyaggr3g470r/forms.py b/pyaggr3g470r/forms.py index 72bb3909..c7054b85 100644 --- a/pyaggr3g470r/forms.py +++ b/pyaggr3g470r/forms.py @@ -6,3 +6,21 @@ from wtforms import TextField, TextAreaField, PasswordField, SubmitField, valida import models +class SigninForm(Form): + email = TextField("Email", [validators.Required("Please enter your email address."), validators.Email("Please enter your email address.")]) + password = PasswordField('Password', [validators.Required("Please enter a password.")]) + submit = SubmitField("Sign In") + + def __init__(self, *args, **kwargs): + Form.__init__(self, *args, **kwargs) + + def validate(self): + if not Form.validate(self): + return False + + user = models.User.objects(email = self.email.data).first() + if user and user.check_password(self.password.data): + return True + else: + self.email.errors.append("Invalid e-mail or password") + return False
\ No newline at end of file diff --git a/pyaggr3g470r/models.py b/pyaggr3g470r/models.py index dfc40b28..23222909 100644 --- a/pyaggr3g470r/models.py +++ b/pyaggr3g470r/models.py @@ -12,8 +12,12 @@ class User(Document, UserMixin): lastname = StringField(required = True) email = EmailField(required=True, unique=True) pwdhash = StringField(required=True) + #feeds = ListField(DocumentField('Article')) created_at = DateTimeField(required=True, default=datetime.now) + def get_id(self): + return self.email + def set_password(self, password): self.pwdhash = generate_password_hash(password) @@ -22,7 +26,7 @@ class User(Document, UserMixin): #required for administrative interface def __unicode__(self): - return self.nickname + return self.email class Feed(Document): title = StringField(required=True) diff --git a/pyaggr3g470r/templates/layout.html b/pyaggr3g470r/templates/layout.html index c6d26e50..659c573c 100644 --- a/pyaggr3g470r/templates/layout.html +++ b/pyaggr3g470r/templates/layout.html @@ -38,12 +38,15 @@ <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav"> - <li><a href="/fetch">Fetch</a></li> - <li><a href="/management/">Management</a></li> - <li><a href="#services">History</a></li> - <li><a href="/favorites/">Favorites</a></li> - <li><a href="/unread/">Unread</a></li> - <li><a href="/about/">About</a></li> + {% if g.user.is_authenticated() %} + <li><a href="/fetch">Fetch</a></li> + <li><a href="/management/">Management</a></li> + <li><a href="#services">History</a></li> + <li><a href="/favorites/">Favorites</a></li> + <li><a href="/unread/">Unread</a></li> + <li><a href="/about/">About</a></li> + <li><a href="{{ url_for('logout') }}">Logout</a></li> + {% endif %} </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container --> diff --git a/pyaggr3g470r/templates/login.html b/pyaggr3g470r/templates/login.html new file mode 100644 index 00000000..fce29054 --- /dev/null +++ b/pyaggr3g470r/templates/login.html @@ -0,0 +1,29 @@ +{% extends "layout.html" %} + +{% block content %} +<div align="center"> + <h2>Log In</h2> + + {% for message in form.email.errors %} + <div class="flash">{{ message }}</div> + {% endfor %} + + {% for message in form.password.errors %} + <div class="flash">{{ message }}</div> + {% endfor %} + + <form action="{{ url_for('login') }}" method=post> + {{ form.hidden_tag() }} + + {{ form.email.label }} + {{ form.email }} + <br /> + {{ form.password.label }} + {{ form.password }} + + <br /> + {{ form.submit(class_="btn") }} + </form> +</div> + +{% endblock %} diff --git a/pyaggr3g470r/views.py b/pyaggr3g470r/views.py index 1a0408ee..359ae15d 100644 --- a/pyaggr3g470r/views.py +++ b/pyaggr3g470r/views.py @@ -1,47 +1,109 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- -from flask import render_template, request, flash, session, url_for, redirect +from flask import render_template, request, flash, session, url_for, redirect, g from wtforms import TextField, PasswordField, SubmitField, validators from flask.ext.mail import Message, Mail +from flask.ext.login import LoginManager, login_user, logout_user, login_required, current_user, AnonymousUserMixin from collections import defaultdict -#from forms import ContactForm, SignupForm, SigninForm +from forms import SigninForm from pyaggr3g470r import app, db + import feedgetter import models mail = Mail() +login_manager = LoginManager() +login_manager.init_app(app) + +@app.before_request +def before_request(): + g.user = current_user + if g.user.is_authenticated(): + pass + #g.user.last_seen = datetime.utcnow() + #db.session.add(g.user) + #db.session.commit() + +@app.errorhandler(403) +def authentication_failed(e): + flash('Authenticated failed.') + return redirect(url_for('login')) + +@app.errorhandler(401) +def authentication_failed(e): + flash('Authenticated required.') + return redirect(url_for('login')) + +@login_manager.user_loader +def load_user(email): + # Return an instance of the User model + return models.User.objects(email=email).first() + +@app.route('/login/', methods=['GET', 'POST']) +def login(): + g.user = AnonymousUserMixin() + form = SigninForm() + + if form.validate_on_submit(): + user = models.User.objects(email=form.email.data).first() + login_user(user) + g.user = user + flash("Logged in successfully.") + return redirect(url_for('home')) + return render_template('login.html', form=form) + +@app.route('/logout/') +@login_required +def logout(): + """ + Remove the user information from the session. + """ + logout_user() + return redirect(url_for('home')) + + + + + @app.route('/') +@login_required def home(): #feeds = models.Feed.objects().order_by('title').fields(slice__articles=[0,9]) + user = g.user feeds = models.Feed.objects().fields(slice__articles=9) - return render_template('home.html', feeds=feeds) + return render_template('home.html', user=user, feeds=feeds) @app.route('/fetch/', methods=['GET']) +@login_required def fetch(): feed_getter = feedgetter.FeedGetter() feed_getter.retrieve_feed() return redirect(url_for('home')) @app.route('/about/', methods=['GET']) +@login_required def about(): return render_template('about.html') @app.route('/feeds/', methods=['GET']) +@login_required def feeds(): feeds = models.Feed.objects() return render_template('feeds.html', feeds=feeds) @app.route('/feed/<feed_id>', methods=['GET']) +@login_required def feed(feed_id=None): feed = models.Article.objects(id=feed_id).first() return render_template('feed.html', feed=feed) @app.route('/article/<article_id>', methods=['GET']) +@login_required def article(article_id=None): article = models.Article.objects(id=article_id).first() if not article.readed: @@ -50,6 +112,7 @@ def article(article_id=None): return render_template('article.html', article=article) @app.route('/delete/<article_id>', methods=['GET']) +@login_required def delete(article_id=None): article = models.Article.objects(id=article_id).first() article.delete() @@ -57,12 +120,14 @@ def delete(article_id=None): return redirect(url_for('home')) @app.route('/articles/<feed_id>', methods=['GET']) +@login_required def articles(feed_id=None): feed = models.Feed.objects(id=feed_id).first() #feed.articles = sorted(feed.articles, key=lambda t: t.date, reverse=True) return render_template('articles.html', feed=feed) @app.route('/favorites/', methods=['GET']) +@login_required def favorites(): favorites = defaultdict(list) for feed in models.Feed.objects(): @@ -73,15 +138,15 @@ def favorites(): return render_template('favorites.html', favorites=favorites) @app.route('/unread/', methods=['GET']) +@login_required def unread(): feeds = models.Feed.objects().filter(articles__readed=False) - unread_articles = models.Article.objects.filter(readed = False) - print len(feeds) return render_template('unread.html', feeds=feeds) @app.route('/management/', methods=['GET']) +@login_required def management(): nb_article = models.Article.objects().count() return render_template('management.html', nb_article=nb_article)
\ No newline at end of file |