from pybossa.contributions_guard import ContributionsGuard from pybossa.auth import jwt_authorize_project from werkzeug.exceptions import MethodNotAllowed, Forbidden from completed_task import CompletedTaskAPI from completed_task_run import CompletedTaskRunAPI from pybossa.cache.helpers import n_available_tasks, n_available_tasks_for_user from pybossa.sched import (get_project_scheduler_and_timeout, get_scheduler_and_timeout, has_lock, release_lock, Schedulers, get_locks) from pybossa.api.project_by_name import ProjectByNameAPI from pybossa.api.pwd_manager import get_pwd_manager from pybossa.data_access import data_access_levels blueprint = Blueprint('api', __name__) error = ErrorStatus() @blueprint.route('/') @ratelimit(limit=ratelimits.get('LIMIT'), per=ratelimits.get('PER')) def index(): # pragma: no cover """Return dummy text for welcome page.""" return 'The %s API' % current_app.config.get('BRAND') @blueprint.before_request def _api_authentication_with_api_key(): """ Allow API access with valid api_key.""" secure_app_access = current_app.config.get('SECURE_APP_ACCESS', False) if secure_app_access: grant_access_with_api_key(secure_app_access)
class DiscourseClient(object): """Discourse client to interact with the Discourse API. :param app: The PyBossa application. """ def __init__(self, app=None): self.url = app.config['DISCOURSE_URL'] self.api_key = app.config['DISCOURSE_API_KEY'] self.api_username = app.config['DISCOURSE_API_USERNAME'] self.error_status = ErrorStatus() def _request(self, verb, endpoint, params): """Make a request.""" url = '{0}{1}'.format(self.url, endpoint) params['api_key'] = self.api_key params['api_username'] = self.api_username try: res = requests.request(verb, url, params=params) except requests.RequestException as e: # pragma: no cover return self.error_status.format_exception(e, target=endpoint, action=verb).json() try: return res.json() except ValueError as e: # pragma: no cover return self.error_status.format_exception(e, target=endpoint, action=verb).json() def _get(self, endpoint, params=dict()): """Make a GET request.""" return self._request('GET', endpoint, params) def _post(self, endpoint, params=dict()): """Make a POST request.""" return self._request('POST', endpoint, params) def _put(self, endpoint, params=dict()): """Make a PUT request.""" return self._request('PUT', endpoint, params) def _create_user(self): """Create a new Discourse user based on the current users email.""" endpoint = '/users' random_name = str(uuid.uuid4().get_hex().upper()[0:15]) random_username = str(uuid.uuid4().get_hex().upper()[0:15]) params = {'name': random_name, 'username': random_username, 'email': current_user.email_addr, 'password': '******', 'active': 'true', } return self._post(endpoint, params) def _get_username(self): """Return the current user's Discourse username. A new Discourse user will be created first, if necessary. """ if current_user.is_anonymous(): return None def get_username_response(): endpoint = '/admin/users/list/all.json' params = {'filter': current_user.email_addr} return self._get(endpoint, params) res = get_username_response() if len(res) == 0: self._create_user() res = get_username_response() return res[0]['username'] if len(res) == 0 else None def categories(self): """Return all categories.""" endpoint = '/categories.json' return self._get(endpoint) def category(self, category_id): """Return all topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}.json'.format(category_id) return self._get(endpoint) def category_topics_latest(self, category_id): """Return the latest topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/l/latest.json'.format(category_id) return self._get(endpoint) def category_topics_new(self, category_id): """Return the newest topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/l/new.json'.format(category_id) return self._get(endpoint) def category_topics_top(self, category_id): """Return the top topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/l/top.json'.format(category_id) return self._get(endpoint) def category_topics_subtopics(self, category_id, p_category_id): """Return the topics in a sub-category. :param p_category_id: The ID of the parent category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/{1}.json'.format(p_category_id, category_id) return self._get(endpoint) def topic(self, topic_id): """Return a specific topic. :param topic_id: The ID of the topic. """ endpoint = '/t/{0}.json'.format(topic_id) return self._get(endpoint) def topics_latest(self): """Return the latest topics.""" endpoint = '/latest.json' return self._get(endpoint) def topics_top(self): """Return the top topics.""" endpoint = '/top.json' return self._get(endpoint) def user_details(self): """Return the current user's details.""" username = self._get_username() if not username: return None endpoint = '/users/{0}.json'.format(username) return self._get(endpoint) def user_activity(self): """Return the current user's recent activity. :param username: The user's Discourse username. """ username = self._get_username() if not username: return None endpoint = '/user_actions.json' params = {'username': username} return self._get(endpoint, params) def user_messages(self): """Return the current user's private messages.""" username = self._get_username() if not username: return None endpoint = '/topics/private-messages/{0}.json'.format(username) return self._get(endpoint) def user_notifications(self): """Return the current user's notifications.""" username = self._get_username() if not username: return None endpoint = '/notifications.json' params = {'username': username} return self._get(endpoint, params) def user_unread_notifications_count(self): """Return a count of unread notifications for the current user.""" username = self._get_username() if not username: return None notifications = self.user_notifications() count = sum([1 for n in notifications['notifications'] if not n['read']]) return count def user_signout(self): """Sign out the current user from Discourse.""" details = self.user_details() if not details: return None user_id = details['user']['id'] endpoint = '/admin/users/{0}/log_out'.format(user_id) return self._post(endpoint) def badges(self): """Return all badges.""" endpoint = '/admin/badges.json' return self._get(endpoint) def search(self, query): """Perform a search. :param query: The search query. """ endpoint = '/search.json' params = {'q': query, 'order': 'posts', 'ascending': 'true'} return self._get(endpoint, params)
class DiscourseClient(object): """Discourse class to initialise the Flask-Discourse extension. :param app: The PyBossa application. """ def __init__(self, app=None): self.url = app.config['DISCOURSE_URL'] self.api_key = app.config['DISCOURSE_API_KEY'] self.api_username = app.config['DISCOURSE_API_USERNAME'] self.error_status = ErrorStatus() def _request(self, verb, endpoint, params): """Make a request.""" url = '{0}{1}'.format(self.url, endpoint) params['api_key'] = self.api_key params['api_username'] = self.api_username try: res = requests.request(verb, url, params=params) except requests.RequestException as e: # pragma: no cover return self.error_status.format_exception(e, target=endpoint, action=verb) if len(res.content.strip()) == 0: # pragma: no cover return None try: decoded = res.json() except ValueError as e: # pragma: no cover return self.error_status.format_exception(e, target=endpoint, action=verb) return decoded def _get(self, endpoint, params=dict()): """Make a GET request.""" return self._request('GET', endpoint, params) def _post(self, endpoint, params=dict()): """Make a POST request.""" return self._request('POST', endpoint, params) def _put(self, endpoint, params=dict()): """Make a PUT request.""" return self._request('PUT', endpoint, params) def _create_user(self): """Create a new Discourse user based on the current users email.""" endpoint = '/users' random_name = str(uuid.uuid4().get_hex().upper()[0:15]) random_username = str(uuid.uuid4().get_hex().upper()[0:15]) params = { 'name': random_name, 'username': random_username, 'email': current_user.email_addr, 'password': '******', 'active': 'true', } return self._post(endpoint, params) def _get_username(self): """Return the current user's Discourse username. A new Discourse user will be created first, if necessary. """ if current_user.is_anonymous(): return None def get_username_response(): endpoint = '/admin/users/list/all.json' params = {'filter': current_user.email_addr} return self._get(endpoint, params) res = get_username_response() if len(res) == 0: self._create_user() res = get_username_response() return res[0]['username'] def categories(self): """Return all categories.""" endpoint = '/categories.json' return self._get(endpoint) def category(self, category_id): """Return all topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}.json'.format(category_id) return self._get(endpoint) def category_topics_latest(self, category_id): """Return the latest topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/l/latest.json'.format(category_id) return self._get(endpoint) def category_topics_new(self, category_id): """Return the newest topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/l/new.json'.format(category_id) return self._get(endpoint) def category_topics_top(self, category_id): """Return the top topics in a category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/l/top.json'.format(category_id) return self._get(endpoint) def category_topics_subtopics(self, category_id, p_category_id): """Return the topics in a sub-category. :param p_category_id: The ID of the parent category. :param category_id: The ID of the category. """ endpoint = '/c/{0}/{1}.json'.format(p_category_id, category_id) return self._get(endpoint) def topic(self, topic_id): """Return a specific topic. :param topic_id: The ID of the topic. """ endpoint = '/t/{0}.json'.format(topic_id) return self._get(endpoint) def topics_latest(self): """Return the latest topics.""" endpoint = '/latest.json' return self._get(endpoint) def topics_top(self): """Return the top topics.""" endpoint = '/top.json' return self._get(endpoint) def user_details(self): """Return the current user's details.""" username = self._get_username() if not username: return None endpoint = '/users/{0}.json'.format(username) return self._get(endpoint) def user_activity(self): """Return the current user's recent activity. :param username: The user's Discourse username. """ username = self._get_username() if not username: return None endpoint = '/user_actions.json' params = {'username': username} return self._get(endpoint, params) def user_messages(self): """Return the current user's private messages.""" username = self._get_username() if not username: return None endpoint = '/topics/private-messages/{0}.json'.format(username) return self._get(endpoint) def user_notifications(self): """Return the current user's notifications.""" username = self._get_username() if not username: return None endpoint = '/notifications.json' params = {'username': username} return self._get(endpoint, params) def user_unread_notifications_count(self): """Return a count of unread notifications for the current user.""" username = self._get_username() if not username: return None notifications = self.user_notifications() count = sum( [1 for n in notifications['notifications'] if not n['read']]) return count def user_signout(self): """Sign out the current user from Discourse.""" details = self.user_details() if not details: return None user_id = details['user']['id'] endpoint = '/admin/users/{0}/log_out'.format(user_id) return self._post(endpoint) def badges(self): """Return all badges.""" endpoint = '/admin/badges.json' return self._get(endpoint) def search(self, query): """Perform a search. :param query: The search query. """ endpoint = '/search.json' params = {'q': query, 'order': 'posts', 'ascending': 'true'} return self._get(endpoint, params)
def __init__(self, app=None): self.url = app.config['DISCOURSE_URL'] self.api_key = app.config['DISCOURSE_API_KEY'] self.api_username = app.config['DISCOURSE_API_USERNAME'] self.error_status = ErrorStatus()