<commit_before># -*- coding: utf-8 -*-
# ###
# Copyright (c) 2013, Rice University
# This software is subject to the provisions of the GNU Affero General
# Public License version 3 (AGPLv3).
# See LICENCE.txt for details.
# ###
import functools
import json
try:
    from urllib import urlencode # python 2
except ImportError:
    from urllib.parse import urlencode # renamed in python 3
try:
    import urlparse # python2
except ImportError:
    import urllib.parse as urlparse # renamed in python3

from pyramid.security import forget
from pyramid.view import view_config
from pyramid import httpexceptions
import requests
from openstax_accounts.interfaces import *

from .models import (create_content, derive_content, revise_content,
        Document, Resource, BINDER_MEDIATYPE, DocumentNotFoundError)
from .schemata import DocumentSchema, BinderSchema
from .storage import storage
from . import utils


def authenticated_only(function):
    @functools.wraps(function)
    def wrapper(request, *args, **kwargs):
        if not request.authenticated_userid:
            raise httpexceptions.HTTPUnauthorized()
        return function(request, *args, **kwargs)
    return wrapper


@view_config(route_name='login')
def login(request):
    # store where we should redirect to before login
    referer = request.referer or '/'
    redirect_to = request.params.get('redirect', referer)
    if redirect_to == request.route_url('login'):
        redirect_to = '/'
    if request.unauthenticated_userid:
        return httpexceptions.HTTPFound(location=redirect_to)
    request.session.update({'redirect_to': redirect_to})
    request.authenticated_userid # triggers login


@view_config(route_name='callback')
@authenticated_only
def callback(request):
    # callback must be protected so that effective_principals is called
    # callback must redirect
    redirect_to = '/'
    if request.session.get('redirect_to'):
        # redirect_to in session is from login
        redirect_to = request.session.pop('redirect_to')
    raise httpexceptions.HTTPFound(location=redirect_to)


@view_config(route_name='logout')
def logout(request):
    forget(request)
    referer = request.referer or '/'
    redirect_to = request.params.get('redirect', referer)
    if redirect_to == request.route_url('logout'):
        redirect_to = '/'
    raise httpexceptions.HTTPFound(location=redirect_to)


@view_config(route_name='options', request_method='OPTIONS', renderer='string')
def options(request):
    return ''


@view_config(route_name='user-search', request_method='GET', renderer='json')
@authenticated_only
def user_search(request):
    """Search for openstax accounts users"""
    q = request.GET.get('q', '')
    if not q:
        return []
    params = urlencode({'q': q})
    accounts = request.registry.getUtility(IOpenstaxAccounts)
    result = accounts.request(
            '/api/users/search.json?{}'.format(params))
    return result


@view_config(route_name='profile', request_method='GET', renderer='json')
@authenticated_only
def profile(request):
    return request.user

def update_content_state(request, content):
    """Updates content state if it is non-terminal by checking w/ publishing service"""
    if (content.metadata['state'] not in [None, 'Done/Success'] and
            content.metadata['publication']):
        publishing_url = request.registry.settings['publishing.url']
        if not publishing_url.endswith('/'):
            publishing_url = publishing_url + '/'
        response = requests.get(urlparse.urljoin(
            publishing_url, content.metadata['publication']))
        if response.status_code == 200:
            try:
                result = json.loads(response.content.decode('utf-8'))
                content.update(state=result['state'])
                storage.update(content)
                storage.persist()
            except (TypeError, ValueError):
                pass

@view_config(route_name='user-contents', request_method='GET', renderer='json')
@authenticated_only
def user_contents(request):
    """Extract of the contents that belong to the current logged in user"""
    items = []
    # TODO use acls instead of filter by submitter
    for content in storage.get_all(submitter=request.unauthenticated_userid):
        update_content_state(request, content)
        item = content.__json__()
        document = {k: item[k] for k in  
               ['mediaType', 'title', 'id', 'version', 'revised', 'derivedFrom','state']}
        document['id'] = '@'.join([document['id'], document['version']])
        items.append(document)
    items.sort(key=lambda item: item['revised'], reverse=True)
    return {
            u'query': {
                u'limits': [],
                },
            u'results': {
                u'items': items,
                u'total': len(items),
                u'limits': [],
                },
            }


@view_config(route_name='get-content-json', request_method='GET', renderer='json')
@authenticated_only
def get_content(request):
    """Acquisition of content by id"""<commit_msg>make workspace link for published content got to non-draft<commit_after># -*- coding: utf-8 -*-
# ###
# Copyright (c) 2013, Rice University
# This software is subject to the provisions of the GNU Affero General
# Public License version 3 (AGPLv3).
# See LICENCE.txt for details.
# ###
import functools
import json
try:
    from urllib import urlencode # python 2
except ImportError:
    from urllib.parse import urlencode # renamed in python 3
try:
    import urlparse # python2
except ImportError:
    import urllib.parse as urlparse # renamed in python3

from pyramid.security import forget
from pyramid.view import view_config
from pyramid import httpexceptions
import requests
from openstax_accounts.interfaces import *

from .models import (create_content, derive_content, revise_content,
        Document, Resource, BINDER_MEDIATYPE, DocumentNotFoundError)
from .schemata import DocumentSchema, BinderSchema
from .storage import storage
from . import utils


def authenticated_only(function):
    @functools.wraps(function)
    def wrapper(request, *args, **kwargs):
        if not request.authenticated_userid:
            raise httpexceptions.HTTPUnauthorized()
        return function(request, *args, **kwargs)
    return wrapper


@view_config(route_name='login')
def login(request):
    # store where we should redirect to before login
    referer = request.referer or '/'
    redirect_to = request.params.get('redirect', referer)
    if redirect_to == request.route_url('login'):
        redirect_to = '/'
    if request.unauthenticated_userid:
        return httpexceptions.HTTPFound(location=redirect_to)
    request.session.update({'redirect_to': redirect_to})
    request.authenticated_userid # triggers login


@view_config(route_name='callback')
@authenticated_only
def callback(request):
    # callback must be protected so that effective_principals is called
    # callback must redirect
    redirect_to = '/'
    if request.session.get('redirect_to'):
        # redirect_to in session is from login
        redirect_to = request.session.pop('redirect_to')
    raise httpexceptions.HTTPFound(location=redirect_to)


@view_config(route_name='logout')
def logout(request):
    forget(request)
    referer = request.referer or '/'
    redirect_to = request.params.get('redirect', referer)
    if redirect_to == request.route_url('logout'):
        redirect_to = '/'
    raise httpexceptions.HTTPFound(location=redirect_to)


@view_config(route_name='options', request_method='OPTIONS', renderer='string')
def options(request):
    return ''


@view_config(route_name='user-search', request_method='GET', renderer='json')
@authenticated_only
def user_search(request):
    """Search for openstax accounts users"""
    q = request.GET.get('q', '')
    if not q:
        return []
    params = urlencode({'q': q})
    accounts = request.registry.getUtility(IOpenstaxAccounts)
    result = accounts.request(
            '/api/users/search.json?{}'.format(params))
    return result


@view_config(route_name='profile', request_method='GET', renderer='json')
@authenticated_only
def profile(request):
    return request.user

def update_content_state(request, content):
    """Updates content state if it is non-terminal by checking w/ publishing service"""
    if (content.metadata['state'] not in [None, 'Done/Success'] and
            content.metadata['publication']):
        publishing_url = request.registry.settings['publishing.url']
        if not publishing_url.endswith('/'):
            publishing_url = publishing_url + '/'
        response = requests.get(urlparse.urljoin(
            publishing_url, content.metadata['publication']))
        if response.status_code == 200:
            try:
                result = json.loads(response.content.decode('utf-8'))
                content.update(state=result['state'])
                storage.update(content)
                storage.persist()
            except (TypeError, ValueError):
                pass

@view_config(route_name='user-contents', request_method='GET', renderer='json')
@authenticated_only
def user_contents(request):
    """Extract of the contents that belong to the current logged in user"""
    items = []
    # TODO use acls instead of filter by submitter
    for content in storage.get_all(submitter=request.unauthenticated_userid):
        update_content_state(request, content)
        item = content.__json__()
        document = {k: item[k] for k in  
               ['mediaType', 'title', 'id', 'version', 'revised', 'derivedFrom','state']}
        if document['state'] != 'Done/Success':
            document['id'] = '@'.join([document['id'], document['version']])
        items.append(document)
    items.sort(key=lambda item: item['revised'], reverse=True)
    return {
            u'query': {
                u'limits': [],
                },
            u'results': {
                u'items': items,
                u'total': len(items),
                u'limits': [],
                },
            }


@view_config(route_name='get-content-json', request_method='GET', renderer='json')
@authenticated_only
def get_content(request):
    """Acquisition of content by id"""
{'fraction_non_alphanumeric': 0.11494589061128985, 'fraction_numerical': 0.0029248318221702253, 'mean_word_length': 3.3969138448349763, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3670612', 'n_tokens_mistral': 2936, 'n_tokens_neox': 2859, 'n_words': 726}