From 1edbef452c2ddb06e665522586572e6d47a72415 Mon Sep 17 00:00:00 2001 From: skrzepto Date: Aug 17 2016 20:45:21 +0000 Subject: Plus-Plus service backend integration * initial work on plus-plus * adding error handling with proper error displayed to client * Removing debug statements, adding try/except if the plus-plus service is unavailable * adding plus_plus tests * adding case where trying to plus_plus a user who doesnt exist * cleaning up mock request classes * seperating the status and update routes of plus_plus, adding more tests and made a bool helper function for updating karma --- diff --git a/hubs/app.py b/hubs/app.py index 17b56ad..9484bfb 100755 --- a/hubs/app.py +++ b/hubs/app.py @@ -10,6 +10,7 @@ import flask.json import munch from flask.ext.oidc import OpenIDConnect +from requests import request import hubs.models import hubs.widgets @@ -732,3 +733,69 @@ def hub_leave(hub): return flask.abort(400) session.commit() return flask.redirect(flask.url_for('hub', name=hub.name)) + + +@app.route('/plus_plus//status', methods=['GET']) +def plus_plus_status(user): + receiver = hubs.models.User.by_username(session, user) + + if not receiver: + return 'User does not exist', 403 + + pp_url = app.config['PLUS_PLUS_URL'] + str(receiver.username) + req = None + try: + req = request('GET', pp_url) + except: + flask.abort(500) + + if req.status_code == 200: + return flask.jsonify(req.json()) + else: + return req.text, req.status_code + + +def plus_plus_update_bool_helper(val): + if isinstance(val, bool): + return val + elif isinstance(val, (str, unicode)): + fmt_str = str(val).replace("'", "").replace('"', '').lower() + return fmt_str in ("yes", "true", "t", "1") + else: + raise ValueError + + +@app.route('/plus_plus//update', methods=['POST']) +@login_required +def plus_plus_update(user): + receiver = hubs.models.User.by_username(session, user) + + if not receiver: + return 'User does not exist', 403 + + if user == flask.g.auth.nickname: + return 'You may not modify your own karma.', 403 + + if 'decrement' not in flask.request.form \ + and 'increment' not in flask.request.form: + return "You must set 'decrement' or 'increment' " \ + "with a boolean value in the body", 403 + + update = 'increment' if 'increment' in flask.request.form else 'decrement' + + update_bool_val = plus_plus_update_bool_helper(flask.request.form[update]) + pp_url = app.config['PLUS_PLUS_URL'] + str(receiver.username) + sender = hubs.models.User.by_username(session, flask.g.auth.nickname) + pp_token = app.config['PLUS_PLUS_TOKEN'] + auth_header = {'Authorization': 'token {}'.format(pp_token)} + data = {'sender': sender.username, update: update_bool_val} + req = None + try: + req = request('POST', url=pp_url, headers=auth_header, data=data) + except: + flask.abort(500) + + if req.status_code == 200: + return flask.jsonify(req.json()) + else: + return req.text, req.status_code diff --git a/hubs/default_config.py b/hubs/default_config.py index 4125923..bb9ef80 100755 --- a/hubs/default_config.py +++ b/hubs/default_config.py @@ -10,6 +10,8 @@ PROMOTED_GROUPS = [ HUB_OF_THE_MONTH = 'commops' SSE_URL = 'http://localhost:8080/user/' +PLUS_PLUS_URL = 'http://localhost:5001/user/' +PLUS_PLUS_TOKEN = 'thisismytoken' OIDC_CLIENT_SECRETS = os.path.join(os.path.dirname( os.path.abspath(__file__)), '..', 'client_secrets.json') diff --git a/hubs/tests/test_fedora_hubs_flask_api.py b/hubs/tests/test_fedora_hubs_flask_api.py index 6808456..d2966ed 100644 --- a/hubs/tests/test_fedora_hubs_flask_api.py +++ b/hubs/tests/test_fedora_hubs_flask_api.py @@ -4,6 +4,7 @@ from urlparse import urlparse from flask import json from os.path import dirname import vcr +from mock import mock from werkzeug.datastructures import ImmutableMultiDict import hubs @@ -357,6 +358,117 @@ class HubsAPITest(hubs.tests.APPTest): result = self.app.get(url) self.assertEqual(result.status_code, 404) + def mocked_requests_get(*args, **kwargs): + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + + def json(self): + return self.json_data + + if '/plus_plus/decause/status' in args: + data = { + "current": 0, + "decrements": 0, + "increments": 0, + "release": "f24", + "total": 0, + "username": "decause" + } + return MockResponse(json_data=data, status_code=200) + + return MockResponse({}, 404) + + def mocked_requests_post(*args, **kwargs): + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + + def json(self): + return self.json_data + + if '/plus_plus/decause/update' in args: + data = { + "current": 1, + "decrements": 0, + "increments": 1, + "release": "f24", + "total": 1, + "username": "decause" + } + return MockResponse(json_data=data, status_code=200) + + return MockResponse({}, 404) + + @mock.patch('requests.get', side_effect=mocked_requests_get) + def test_plus_plus_get_valid(self, mock_get): + url = '/plus_plus/decause/status' + result = self.app.get(url) + expected = { + "current": 0, + "decrements": 0, + "increments": 0, + "release": "f24", + "total": 0, + "username": "decause" + } + self.assertEqual(json.loads(result.data), expected) + + @mock.patch('requests.post', side_effect=mocked_requests_post) + def test_plus_plus_post_increment_valid(self, mock_post): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + url = '/plus_plus/decause/update' + result = self.app.post(url, data={'increment': True}) + expected = { + "current": 1, + "decrements": 0, + "increments": 1, + "release": "f24", + "total": 1, + "username": "decause" + } + self.assertEqual(json.loads(result.data), expected) + + @mock.patch('requests.post', side_effect=mocked_requests_post) + def test_plus_plus_post_increment_myself_error(self, mock_post): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + url = '/plus_plus/ralph/update' + result = self.app.post(url, data={'increment': True}) + self.assertEqual(result.status_code, 403) + self.assertEqual(result.data, 'You may not modify your own karma.') + + @mock.patch('requests.post', side_effect=mocked_requests_post) + def test_plus_plus_post_increment_user_does_not_exist(self, mock_post): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + url = '/plus_plus/doesnotexist/update' + result = self.app.post(url, data={'increment': True}) + self.assertEqual(result.status_code, 403) + self.assertEqual(result.data, 'User does not exist') + + @mock.patch('requests.post', side_effect=mocked_requests_post) + def test_plus_plus_post_increment_no_data_error(self, mock_post): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + url = '/plus_plus/decause/update' + result = self.app.post(url, data={}) + self.assertEqual(result.status_code, 403) + exp_str = "You must set 'decrement' or 'increment' " \ + "with a boolean value in the body" + self.assertEqual(result.data, exp_str) + + def test_plus_plus_receiver_does_not_exist(self): + url = '/plus_plus/doesnotexist/status' + result = self.app.get(url) + self.assertEqual(result.status_code, 403) + self.assertEqual(result.data, 'User does not exist') + + + if __name__ == '__main__': unittest.main()