--- a/dbsetup.py +++ b/dbsetup.py @@ -20,7 +20,7 @@ # Import all modules which represents a SQLAlchemy model; # they have corresponding tables that are needed to be created -from swtstore.classes.models import Sweet, Context, Client +from swtstore.classes.models import Sweet, Context, Client, AuthorizedClients from swtstore.classes.models.um import User, Group, Membership # Create them! --- a/runserver.py +++ b/runserver.py @@ -19,5 +19,5 @@ # Run the server if this script is directly executed # Presumably, this is development mode if __name__ == '__main__': - app.run(host='0.0.0.0', port=5001) + app.run(debug=True, host='0.0.0.0', port=5001) --- a/swtstore/classes/models/__init__.py +++ b/swtstore/classes/models/__init__.py @@ -1,4 +1,4 @@ from context import Context from sweet import Sweet -from client import Client +from client import Client, AuthorizedClients --- a/swtstore/classes/models/client.py +++ b/swtstore/classes/models/client.py @@ -219,4 +219,47 @@ @oauth.usergetter def getUser(): return User.getCurrentUser() + + + +# Authorized Clients +class AuthorizedClients(db.Model): + """ + The clients authorized by users + """ + + __tablename__ = 'authorized_clients' + + id = db.Column(db.Integer, primary_key=True) + + client_id = db.Column(db.String(40), db.ForeignKey('clients.id'), + nullable=False) + client = db.relationship('Client') + + user_id = db.Column(db.Integer, db.ForeignKey('users.id')) + user = db.relationship('User') + + def persist(self): + db.session.add(self) + db.session.commit() + + @staticmethod + def revoke(**kwargs): + user = kwargs.get('user') + client = kwargs.get('client') + authorization = AuthorizedClients.query.filter_by(user_id=user.id, + client_id=client.client_id).first() + current_app.logger.debug('authorization to be revoked-- %s', + authorization) + db.session.delete(authorization) + db.session.commit() + + @staticmethod + def getByUser(user): + authorized_clients = [row.client for row in \ + AuthorizedClients.query.filter_by(user_id=user.id).all()] + + current_app.logger.debug('authorized clients %s', authorized_clients) + + return authorized_clients --- a/swtstore/classes/views/app.py +++ b/swtstore/classes/views/app.py @@ -22,7 +22,7 @@ return redirect(url_for('frontend.index')) if request.method == 'GET': - return render_template('register_app.html') + return render_template('app/register.html') elif request.method == 'POST': req_fields = ['name', 'host_url', 'redirect_uris', 'scopes'] --- a/swtstore/classes/views/context.py +++ b/swtstore/classes/views/context.py @@ -17,7 +17,7 @@ return redirect(url_for('frontend.index')) if request.method == 'GET': - return render_template('register_context.html') + return render_template('context/register.html') if request.method == 'POST': if not request.form.get('name') or not request.form.get('defn'): --- a/swtstore/classes/views/frontend.py +++ b/swtstore/classes/views/frontend.py @@ -19,7 +19,7 @@ user = User.getCurrentUser() - return render_template('index.html', sweets=sweets) + return render_template('frontend/index.html', sweets=sweets) # Create a new sweet context --- a/swtstore/classes/views/oauth.py +++ b/swtstore/classes/views/oauth.py @@ -3,20 +3,22 @@ from flask import Module, jsonify, request, render_template, redirect,\ url_for, current_app +import requests from swtstore.classes import oauth from swtstore.classes.models.um import User -from swtstore.classes.models import Client +from swtstore.classes.models import Client, AuthorizedClients Oauth = Module(__name__) + @Oauth.route('/authorize', methods=['GET', 'POST']) @oauth.authorize_handler def authorize(*args, **kwargs): current_user = User.getCurrentUser() if current_user is None: - return render_template('oauth_login.html') + return render_template('oauth/login.html') if request.method == 'GET': client_id = kwargs.get('client_id') @@ -25,11 +27,31 @@ kwargs['client'] = client kwargs['user'] = current_user current_app.logger.debug('kwargs %s', kwargs) - return render_template('authorize.html', **kwargs) + # See if this client is already authorized by user. If not then return + # a HTML to allow access. + authorized_clients = AuthorizedClients.getByUser(current_user) + if client in authorized_clients: + return render_template('oauth/authorized.html', **kwargs) + else: + return render_template('oauth/authorize.html', **kwargs) + + confirm = request.form.get('confirm', 'no') + authorized = request.form.get('authorized', 'no') current_app.logger.debug('confirm authorize from user: %s', confirm) - return confirm == 'yes' + client = Client.query.get(request.form.get('client_id')) + + if authorized == 'yes': + return True + else: + if confirm == 'yes': + authorization = AuthorizedClients(user=current_user, client=client) + authorization.persist() + return True + else: + return False + @Oauth.route('/token', methods=['GET', 'POST']) @oauth.token_handler --- a/swtstore/classes/views/sweet.py +++ b/swtstore/classes/views/sweet.py @@ -23,7 +23,7 @@ sweet = Sweet.query.get(id) if sweet: print "sweet found " + str(sweet) - return render_template('specific_sweet.html', sweet=sweet) + return render_template('sweet/specific.html', sweet=sweet) else: abort(404) --- a/swtstore/classes/views/user.py +++ b/swtstore/classes/views/user.py @@ -9,7 +9,7 @@ # swtstore imports from swtstore.classes.models.um import User -from swtstore.classes.models import Sweet, Context, Client +from swtstore.classes.models import Sweet, Context, Client, AuthorizedClients from swtstore.classes.utils.httputils import makeCORSHeaders from swtstore.config import DefaultConfig @@ -89,8 +89,9 @@ return redirect(url_for('frontend.index')) if request.method == 'GET': - return render_template('me.html', user=current_user) + return render_template('user/me.html', user=current_user) + # else POST request username = request.form.get('username') current_app.logger.debug('Updating username of %s to %s', @@ -109,7 +110,7 @@ return redirect(url_for('frontend.index')) swts = Sweet.getByCreator(user) - return render_template('my_sweets.html', sweets=swts) + return render_template('user/sweets.html', sweets=swts) @user.route('/me/contexts', methods=['GET']) @@ -120,7 +121,7 @@ return redirect(url_for('frontend.index')) contexts = Context.getByCreator(user.id) - return render_template('my_contexts.html', contexts=contexts) + return render_template('user/contexts.html', contexts=contexts) @user.route('/me/apps', methods=['GET']) @@ -132,5 +133,26 @@ return redirect(url_for('frontend.index')) apps = Client.getClientsByCreator(user.id) - return render_template('my_apps.html', apps=apps) + return render_template('user/apps.html', apps=apps) + +@user.route('/me/authorized_apps', methods=['GET', 'POST']) +def authorizedApps(): + + user = User.getCurrentUser() + if user is None: + return redirect(url_for('frontend.index')) + + if request.method == 'GET': + authorized_clients = AuthorizedClients.getByUser(user) + return render_template('user/authorized_apps.html', + authorized_clients=authorized_clients) + + # else POST request + client_id = request.form.get('revoke-id', '') + if client_id: + client = Client.query.get(client_id) + current_app.logger.info('user %s revoking access to %s', user, client) + AuthorizedClients.revoke(user=user, client=client) + + return redirect(url_for('authorizedApps')) --- /dev/null +++ b/swtstore/templates/app/list_apps.html @@ -1 +1,26 @@ +{% extends "layout.html" %} +{% block body %} +
Please fill in the details below and click Register button
+ + +{% endblock %} +{% block scripts %} + +{% endblock %} --- a/swtstore/templates/authorize.html +++ /dev/null @@ -1,44 +1 @@ -{% extends "layout.html" %} -{% block body %} -- The following application wants to get permission to do stuff(?) on the swt - web platform on your behalf. -
- - - -{% endblock %} - -{% block scripts %} - - - -{% endblock %} --- /dev/null +++ b/swtstore/templates/context/list_contexts.html @@ -1 +1,21 @@ +{% extends "layout.html" %} +{% block body %} +Please fill in the details below and click Register button
+ + +{% endblock %} --- /dev/null +++ b/swtstore/templates/frontend/index.html @@ -1 +1,47 @@ +{% extends "layout.html" %} + +{% block body %} +Please fill in the details below and click update button
- - - -{% endblock %} - -{% block scripts %} - - - -{% endblock %} --- a/swtstore/templates/my_apps.html +++ /dev/null @@ -1,26 +1 @@ -{% extends "layout.html" %} -{% block body %} -Please fill in the details below and click Register button
- - -{% endblock %} -{% block scripts %} - -{% endblock %} --- a/swtstore/templates/register_context.html +++ /dev/null @@ -1,20 +1 @@ -{% extends "layout.html" %} -{% block body %} -Please fill in the details below and click Register button
- - -{% endblock %} --- a/swtstore/templates/specific_sweet.html +++ /dev/null @@ -1,28 +1 @@ -{% extends "layout.html" %} - -{% block body %} - -+ You have given access to these apps to post sweets + to the swtstore on your behalf. You can revoke access to specific apps. +
+ + +{% else %} + You have not authorized any apps to access swtstore yet. +{% endif %} + +{% endblock %} + +{% block scripts %} + + + +{% endblock %} --- /dev/null +++ b/swtstore/templates/user/contexts.html @@ -1 +1,21 @@ +{% extends "layout.html" %} +{% block body %} +Please fill in the details below and click update button
+ + + +{% endblock %} + +{% block scripts %} + + + +{% endblock %} --- /dev/null +++ b/swtstore/templates/user/sweets.html @@ -1 +1,68 @@ +{% extends "layout.html" %} + +{% block body %} + + {% if sweets|length > 0 %} + +