From 7ea2cf120f3a016da7d14eac7eca475c796e6312 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Wed, 18 Jun 2014 09:49:59 +0200 Subject: Testing a REST API. --- pyaggr3g470r/__init__.py | 6 ++- pyaggr3g470r/rest.py | 113 +++++++++++++++++++++++++++++++++++++++++++++++ pyaggr3g470r/views.py | 4 +- requirements.txt | 1 + 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 pyaggr3g470r/rest.py diff --git a/pyaggr3g470r/__init__.py b/pyaggr3g470r/__init__.py index 5044d344..36f95bc0 100644 --- a/pyaggr3g470r/__init__.py +++ b/pyaggr3g470r/__init__.py @@ -42,4 +42,8 @@ app.jinja_env.filters['datetime'] = format_datetime gravatar = Gravatar(app, size=100, rating='g', default='retro', force_default=False, use_ssl=False, base_url=None) -from pyaggr3g470r import views +# Views +from flask.ext.restful import Api +api = Api(app) + +from pyaggr3g470r import views, rest diff --git a/pyaggr3g470r/rest.py b/pyaggr3g470r/rest.py new file mode 100644 index 00000000..3e92b596 --- /dev/null +++ b/pyaggr3g470r/rest.py @@ -0,0 +1,113 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +# pyAggr3g470r - A Web based news aggregator. +# Copyright (C) 2010-2014 Cédric Bonhomme - http://cedricbonhomme.org/ +# +# For more information : https://bitbucket.org/cedricbonhomme/pyaggr3g470r/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +__author__ = "Cedric Bonhomme" +__version__ = "$Revision: 0.1 $" +__date__ = "$Date: 2014/06/18 $" +__revision__ = "$Date: 2014/06/18 $" +__copyright__ = "Copyright (c) Cedric Bonhomme" +__license__ = "AGPLv3" + +from flask import g, Response, request, session, jsonify +from flask.ext.restful import Resource, reqparse + +from pyaggr3g470r import api +from pyaggr3g470r.models import User, Article + +from functools import wraps +def authenticate(func): + """ + Decorator for the authentication to the web services. + """ + @wraps(func) + def wrapper(*args, **kwargs): + if not getattr(func, 'authenticated', True): + return func(*args, **kwargs) + + if 'email' in session: + return func(*args, **kwargs) + + return Response('', 401, + {'WWWAuthenticate':'Basic realm="Login Required"'}) + return wrapper + +class ArticleAPI(Resource): + """ + Defines a RESTful API for Article elements. + """ + method_decorators = [authenticate] + + def __init__(self): + #self.reqparse = reqparse.RequestParser() + #self.reqparse.add_argument('item_id', type = str, location = 'json') + #self.reqparse.add_argument('item_title', type = unicode, location = 'json') + super(ArticleAPI, self).__init__() + + def get(self): + """ + Get the list of articles. + """ + feeds = {feed.id: feed.title for feed in g.user.feeds if feed.enabled} + articles = Article.query.filter(Article.feed_id.in_(feeds.keys()), + Article.user_id == g.user.id) + filter_ = request.args.get('filter_', 'unread') + feed_id = int(request.args.get('feed', 0)) + limit = request.args.get('limit', 1000) + if filter_ != 'all': + articles = articles.filter(Article.readed == (filter_ == 'read')) + if feed_id: + articles = articles.filter(Article.feed_id == feed_id) + + articles = articles.order_by(Article.date.desc()) + if limit != 'all': + limit = int(limit) + articles = articles.limit(limit) + + return jsonify(result= [{ + "title": article.title, + "link": article.link, + "content": article.content, + "readed": article.readed, + "like": article.like, + "date": article.date, + "retrieved_date": article.retrieved_date + } + for article in articles] + ) + + def post(self): + """ + Update an article. + """ + pass + + def put(self): + """ + Create an article. + """ + pass + + def delete(self): + """ + """ + pass + +api.add_resource(ArticleAPI, '/articles.json/', endpoint = 'articles.json') \ No newline at end of file diff --git a/pyaggr3g470r/views.py b/pyaggr3g470r/views.py index daf1d84e..25717dce 100644 --- a/pyaggr3g470r/views.py +++ b/pyaggr3g470r/views.py @@ -151,18 +151,20 @@ def login(): user = User.query.filter(User.email == form.email.data).first() login_user(user) g.user = user + session['email'] = form.email.data identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) flash(gettext("Logged in successfully."), 'success') return redirect(url_for('home')) return render_template('login.html', form=form) - @app.route('/logout/') @login_required def logout(): """ Log out view. Removes the user information from the session. """ + session.pop('email', None) + # Remove the user information from the session logout_user() diff --git a/requirements.txt b/requirements.txt index 42867a2c..a486c593 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ Flask-SQLAlchemy Flask-Login Flask-Principal Flask-WTF +Flask-RESTful Flask-Babel Flask-Gravatar WTForms -- cgit