Special entry points for getting latest assets etc. from public projects.

This commit is contained in:
Sybren A. Stüvel 2016-05-02 19:07:21 +02:00
parent 3e8494e3bf
commit a216e5c00d
4 changed files with 89 additions and 6 deletions

View File

@ -101,6 +101,8 @@ if from_envvar:
# configfile doesn't exist, it should error out (i.e. silent=False).
app.config.from_pyfile(from_envvar, silent=False)
# Set the TMP
# Configure logging
logging.basicConfig(
level=logging.WARNING,
@ -225,11 +227,13 @@ from modules import local_auth
from modules import file_storage
from modules import users
from modules import nodes
from modules import latest
app.register_blueprint(encoding, url_prefix='/encoding')
app.register_blueprint(blender_id, url_prefix='/blender_id')
projects.setup_app(app, url_prefix='/p')
local_auth.setup_app(app, url_prefix='/auth')
file_storage.setup_app(app, url_prefix='/storage')
latest.setup_app(app, url_prefix='/latest')
users.setup_app(app)
nodes.setup_app(app)

View File

@ -0,0 +1,73 @@
import itertools
import pymongo
from flask import Blueprint, current_app
from application.utils import jsonify
blueprint = Blueprint('latest', __name__)
def keep_fetching(collection, db_filter, projection, sort, py_filter, batch_size=12):
"""Yields results for which py_filter returns True"""
curs = collection.find(db_filter, projection).sort(sort)
curs.batch_size(batch_size)
for doc in curs:
if py_filter(doc):
yield doc
def latest_nodes(db_filter, projection, py_filter, limit):
nodes = current_app.data.driver.db['nodes']
latest = keep_fetching(nodes, db_filter, projection,
[('_updated', pymongo.DESCENDING)],
py_filter, limit)
result = list(itertools.islice(latest, limit))
return jsonify({'_items': result})
def has_public_project(node_doc):
"""Returns True iff the project the node belongs to is public."""
project_id = node_doc.get('project')
return is_project_public(project_id)
# TODO: cache result, at least for a limited amt. of time, or for this HTTP request.
def is_project_public(project_id):
"""Returns True iff the project is public."""
project = current_app.data.driver.db['projects'].find_one(project_id)
if not project:
return False
return not project.get('is_private')
@blueprint.route('/assets')
def latest_assets():
latest = latest_nodes({'node_type': 'asset', 'properties.status': 'published'},
{'name': 1, 'project': 1, 'user': 1, 'node_type': 1,
'picture': 1, 'properties.status': 1,
'properties.content_type': 1,
'permissions.world': 1},
has_public_project, 12)
return latest
@blueprint.route('/comments')
def latest_comments():
latest = latest_nodes({'node_type': 'comment', 'properties.status': 'published'},
{'project': 1, 'parent': 1, 'user': 1,
'properties.content': 1, 'node_type': 1, 'properties.status': 1,
'properties.is_reply': 1},
has_public_project, 6)
return latest
def setup_app(app, url_prefix):
app.register_blueprint(blueprint, url_prefix=url_prefix)

View File

@ -6,7 +6,7 @@ from eve.methods.post import post_internal
from eve.methods.patch import patch_internal
from flask import g, Blueprint, request, abort, current_app
from application.utils import remove_private_keys, authorization, PillarJSONEncoder
from application.utils import remove_private_keys, authorization, jsonify
from application.utils.gcs import GoogleCloudStorageBucket
from application.utils.authorization import user_has_role, check_permissions
from manage_extra.node_types.asset import node_type_asset
@ -213,11 +213,7 @@ def create_project(overrides=None):
project = _create_new_project(project_name, user_id, overrides)
# Return the project in the response.
resp = current_app.response_class(json.dumps(project, cls=PillarJSONEncoder),
mimetype='application/json',
status=201,
headers={'Location': '/projects/%s' % project['_id']})
return resp
return jsonify(project, status=201, headers={'Location': '/projects/%s' % project['_id']})
def abort_with_error(status):

View File

@ -4,6 +4,7 @@ import datetime
import bson
from eve import RFC1123_DATE_FORMAT
from flask import current_app
__all__ = ('remove_private_keys', 'PillarJSONEncoder')
@ -37,3 +38,12 @@ class PillarJSONEncoder(json.JSONEncoder):
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, obj)
def jsonify(mongo_doc, status=200, headers=None):
"""JSonifies a Mongo document into a Flask response object."""
return current_app.response_class(json.dumps(mongo_doc, cls=PillarJSONEncoder),
mimetype='application/json',
status=status,
headers=headers)