Add more tests for federation APIs
This commit is contained in:
parent
967df5eff0
commit
51ab51921e
@ -446,9 +446,8 @@ class MediaEntry(Base, MediaEntryMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"author": author.serialize(request),
|
"author": author.serialize(request),
|
||||||
"displayName": self.title,
|
|
||||||
"objectType": self.objectType,
|
"objectType": self.objectType,
|
||||||
"url": url,
|
"url": url,
|
||||||
"image": {
|
"image": {
|
||||||
@ -464,6 +463,15 @@ class MediaEntry(Base, MediaEntryMixin):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.title:
|
||||||
|
context["displayName"] = self.title
|
||||||
|
|
||||||
|
if self.description:
|
||||||
|
context["content"] = self.description
|
||||||
|
|
||||||
|
if self.license:
|
||||||
|
context["license"] = self.license
|
||||||
|
|
||||||
if show_comments:
|
if show_comments:
|
||||||
comments = [comment.serialize(request) for comment in self.get_comments()]
|
comments = [comment.serialize(request) for comment in self.get_comments()]
|
||||||
total = len(comments)
|
total = len(comments)
|
||||||
@ -478,7 +486,7 @@ class MediaEntry(Base, MediaEntryMixin):
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
class FileKeynames(Base):
|
class FileKeynames(Base):
|
||||||
"""
|
"""
|
||||||
@ -630,6 +638,7 @@ class MediaComment(Base, MediaCommentMixin):
|
|||||||
media = MediaEntry.query.filter_by(id=self.media_entry).first()
|
media = MediaEntry.query.filter_by(id=self.media_entry).first()
|
||||||
author = self.get_author
|
author = self.get_author
|
||||||
context = {
|
context = {
|
||||||
|
"id": self.id,
|
||||||
"objectType": "comment",
|
"objectType": "comment",
|
||||||
"content": self.content,
|
"content": self.content,
|
||||||
"inReplyTo": media.serialize(request, show_comments=False),
|
"inReplyTo": media.serialize(request, show_comments=False),
|
||||||
|
@ -116,15 +116,27 @@ def feed(request):
|
|||||||
|
|
||||||
elif obj.get("objectType", None) == "image":
|
elif obj.get("objectType", None) == "image":
|
||||||
# Posting an image to the feed
|
# Posting an image to the feed
|
||||||
# NB: This is currently just handing the image back until we have an
|
|
||||||
# to send the image to the actual feed
|
|
||||||
|
|
||||||
media_id = int(data["object"]["id"])
|
media_id = int(data["object"]["id"])
|
||||||
media = MediaEntry.query.filter_by(id=media_id)
|
media = MediaEntry.query.filter_by(id=media_id)
|
||||||
if media is None:
|
if media is None:
|
||||||
error = "No such 'image' with id '{0}'".format(id=media_id)
|
error = "No such 'image' with id '{0}'".format(id=media_id)
|
||||||
return json_response(error, status=404)
|
return json_response(error, status=404)
|
||||||
media = media[0]
|
|
||||||
|
media = media.first()
|
||||||
|
obj = data["object"]
|
||||||
|
|
||||||
|
if "displayName" in obj:
|
||||||
|
media.title = obj["displayName"]
|
||||||
|
|
||||||
|
if "content" in obj:
|
||||||
|
media.description = obj["content"]
|
||||||
|
|
||||||
|
if "license" in obj:
|
||||||
|
media.license = obj["license"]
|
||||||
|
|
||||||
|
media.save()
|
||||||
|
manager = media.media_manager.api_add_to_feed(request, media)
|
||||||
|
|
||||||
return json_response({
|
return json_response({
|
||||||
"verb": "post",
|
"verb": "post",
|
||||||
"object": media.serialize(request)
|
"object": media.serialize(request)
|
||||||
@ -206,6 +218,11 @@ def feed(request):
|
|||||||
}
|
}
|
||||||
return json_response(activity)
|
return json_response(activity)
|
||||||
|
|
||||||
|
elif request.method != "GET":
|
||||||
|
# Currently unsupported
|
||||||
|
error = "Unsupported HTTP method {0}".format(request.method)
|
||||||
|
return json_response({"error": error}, status=501)
|
||||||
|
|
||||||
feed_url = request.urlgen(
|
feed_url = request.urlgen(
|
||||||
"mediagoblin.federation.feed",
|
"mediagoblin.federation.feed",
|
||||||
username=request.user.username,
|
username=request.user.username,
|
||||||
|
@ -63,10 +63,7 @@ class ImageMediaManager(MediaManagerBase):
|
|||||||
""" This handles a image upload request """
|
""" This handles a image upload request """
|
||||||
# Use the same kind of method from mediagoblin/submit/views:submit_start
|
# Use the same kind of method from mediagoblin/submit/views:submit_start
|
||||||
entry.media_type = unicode(MEDIA_TYPE)
|
entry.media_type = unicode(MEDIA_TYPE)
|
||||||
entry.title = unicode(request.args.get("title", file_data.filename))
|
entry.title = file_data.filename
|
||||||
entry.description = unicode(request.args.get("description", ""))
|
|
||||||
entry.license = request.args.get("license", "") # not part of the standard API
|
|
||||||
|
|
||||||
entry.generate_slug()
|
entry.generate_slug()
|
||||||
|
|
||||||
queue_file = prepare_queue_task(request.app, entry, file_data.filename)
|
queue_file = prepare_queue_task(request.app, entry, file_data.filename)
|
||||||
@ -74,6 +71,16 @@ class ImageMediaManager(MediaManagerBase):
|
|||||||
queue_file.write(request.data)
|
queue_file.write(request.data)
|
||||||
|
|
||||||
entry.save()
|
entry.save()
|
||||||
|
return json_response(entry.serialize(request))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def api_add_to_feed(request, entry):
|
||||||
|
""" Add media to Feed """
|
||||||
|
if entry.title:
|
||||||
|
# Shame we have to do this here but we didn't have the data in
|
||||||
|
# api_upload_request as no filename is usually specified.
|
||||||
|
entry.slug = None
|
||||||
|
entry.generate_slug()
|
||||||
|
|
||||||
feed_url = request.urlgen(
|
feed_url = request.urlgen(
|
||||||
'mediagoblin.user_pages.atom_feed',
|
'mediagoblin.user_pages.atom_feed',
|
||||||
|
@ -23,11 +23,10 @@ from webtest import AppError
|
|||||||
|
|
||||||
from mediagoblin import mg_globals
|
from mediagoblin import mg_globals
|
||||||
from .resources import GOOD_JPG
|
from .resources import GOOD_JPG
|
||||||
from mediagoblin.db.models import User
|
from mediagoblin.db.models import User, MediaEntry
|
||||||
from mediagoblin.tests.tools import fixture_add_user
|
from mediagoblin.tests.tools import fixture_add_user
|
||||||
from mediagoblin.moderation.tools import take_away_privileges
|
from mediagoblin.moderation.tools import take_away_privileges
|
||||||
from .resources import GOOD_JPG, GOOD_PNG, EVIL_FILE, EVIL_JPG, EVIL_PNG, \
|
from .resources import GOOD_JPG
|
||||||
BIG_BLUE
|
|
||||||
|
|
||||||
class TestAPI(object):
|
class TestAPI(object):
|
||||||
|
|
||||||
@ -35,8 +34,54 @@ class TestAPI(object):
|
|||||||
def setup(self, test_app):
|
def setup(self, test_app):
|
||||||
self.test_app = test_app
|
self.test_app = test_app
|
||||||
self.db = mg_globals.database
|
self.db = mg_globals.database
|
||||||
|
|
||||||
self.user = fixture_add_user(privileges=[u'active', u'uploader'])
|
self.user = fixture_add_user(privileges=[u'active', u'uploader'])
|
||||||
|
|
||||||
|
def _activity_to_feed(self, test_app, activity, headers=None):
|
||||||
|
""" Posts an activity to the user's feed """
|
||||||
|
if headers:
|
||||||
|
headers.setdefault("Content-Type", "application/json")
|
||||||
|
else:
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
|
||||||
|
response = test_app.post(
|
||||||
|
"/api/user/{0}/feed".format(self.user.username),
|
||||||
|
json.dumps(activity),
|
||||||
|
headers=headers
|
||||||
|
)
|
||||||
|
|
||||||
|
return response, json.loads(response.body)
|
||||||
|
|
||||||
|
def _upload_image(self, test_app, image):
|
||||||
|
""" Uploads and image to MediaGoblin via pump.io API """
|
||||||
|
data = open(image, "rb").read()
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "image/jpeg",
|
||||||
|
"Content-Length": str(len(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
|
||||||
|
response = test_app.post(
|
||||||
|
"/api/user/{0}/uploads".format(self.user.username),
|
||||||
|
data,
|
||||||
|
headers=headers
|
||||||
|
)
|
||||||
|
image = json.loads(response.body)
|
||||||
|
|
||||||
|
return response, image
|
||||||
|
|
||||||
|
def _post_image_to_feed(self, test_app, image):
|
||||||
|
""" Posts an already uploaded image to feed """
|
||||||
|
activity = {
|
||||||
|
"verb": "post",
|
||||||
|
"object": image,
|
||||||
|
}
|
||||||
|
|
||||||
|
return self._activity_to_feed(test_app, activity)
|
||||||
|
|
||||||
|
|
||||||
def mocked_oauth_required(self, *args, **kwargs):
|
def mocked_oauth_required(self, *args, **kwargs):
|
||||||
""" Mocks mediagoblin.decorator.oauth_required to always validate """
|
""" Mocks mediagoblin.decorator.oauth_required to always validate """
|
||||||
|
|
||||||
@ -52,46 +97,63 @@ class TestAPI(object):
|
|||||||
def test_can_post_image(self, test_app):
|
def test_can_post_image(self, test_app):
|
||||||
""" Tests that an image can be posted to the API """
|
""" Tests that an image can be posted to the API """
|
||||||
# First request we need to do is to upload the image
|
# First request we need to do is to upload the image
|
||||||
data = open(GOOD_JPG, "rb").read()
|
response, image = self._upload_image(test_app, GOOD_JPG)
|
||||||
headers = {
|
|
||||||
"Content-Type": "image/jpeg",
|
|
||||||
"Content-Length": str(len(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
# I should have got certain things back
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
assert "id" in image
|
||||||
|
assert "fullImage" in image
|
||||||
|
assert "url" in image["fullImage"]
|
||||||
|
assert "url" in image
|
||||||
|
assert "author" in image
|
||||||
|
assert "published" in image
|
||||||
|
assert "updated" in image
|
||||||
|
assert image["objectType"] == "image"
|
||||||
|
|
||||||
|
# Check that we got the response we're expecting
|
||||||
|
response, _ = self._post_image_to_feed(test_app, image)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
def test_upload_image_with_filename(self, test_app):
|
||||||
|
""" Tests that you can upload an image with filename and description """
|
||||||
|
response, data = self._upload_image(test_app, GOOD_JPG)
|
||||||
|
response, data = self._post_image_to_feed(test_app, data)
|
||||||
|
|
||||||
|
image = data["object"]
|
||||||
|
|
||||||
|
# Now we need to add a title and description
|
||||||
|
title = "My image ^_^"
|
||||||
|
description = "This is my super awesome image :D"
|
||||||
|
license = "CC-BY-SA"
|
||||||
|
|
||||||
|
image["displayName"] = title
|
||||||
|
image["content"] = description
|
||||||
|
image["license"] = license
|
||||||
|
|
||||||
|
activity = {"verb": "update", "object": image}
|
||||||
|
|
||||||
with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
|
with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
|
||||||
response = test_app.post(
|
|
||||||
"/api/user/{0}/uploads".format(self.user.username),
|
|
||||||
data,
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
image = json.loads(response.body)
|
|
||||||
|
|
||||||
|
|
||||||
# I should have got certain things back
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
assert "id" in image
|
|
||||||
assert "fullImage" in image
|
|
||||||
assert "url" in image["fullImage"]
|
|
||||||
assert "url" in image
|
|
||||||
assert "author" in image
|
|
||||||
assert "published" in image
|
|
||||||
assert "updated" in image
|
|
||||||
assert image["objectType"] == "image"
|
|
||||||
|
|
||||||
# Now post this to the feed
|
|
||||||
activity = {
|
|
||||||
"verb": "post",
|
|
||||||
"object": image,
|
|
||||||
}
|
|
||||||
response = test_app.post(
|
response = test_app.post(
|
||||||
"/api/user/{0}/feed".format(self.user.username),
|
"/api/user/{0}/feed".format(self.user.username),
|
||||||
activity
|
json.dumps(activity),
|
||||||
|
headers={"Content-Type": "application/json"}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check that we got the response we're expecting
|
image = json.loads(response.body)["object"]
|
||||||
assert response.status_code == 200
|
|
||||||
|
# Check everything has been set on the media correctly
|
||||||
|
media = MediaEntry.query.filter_by(id=image["id"]).first()
|
||||||
|
assert media.title == title
|
||||||
|
assert media.description == description
|
||||||
|
assert media.license == license
|
||||||
|
|
||||||
|
# Check we're being given back everything we should on an update
|
||||||
|
assert image["id"] == media.id
|
||||||
|
assert image["displayName"] == title
|
||||||
|
assert image["content"] == description
|
||||||
|
assert image["license"] == license
|
||||||
|
|
||||||
|
|
||||||
def test_only_uploaders_post_image(self, test_app):
|
def test_only_uploaders_post_image(self, test_app):
|
||||||
""" Test that only uploaders can upload images """
|
""" Test that only uploaders can upload images """
|
||||||
@ -115,3 +177,50 @@ class TestAPI(object):
|
|||||||
|
|
||||||
# Assert that we've got a 403
|
# Assert that we've got a 403
|
||||||
assert "403 FORBIDDEN" in excinfo.value.message
|
assert "403 FORBIDDEN" in excinfo.value.message
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_comment(self, test_app):
|
||||||
|
""" Tests that I can post an comment media """
|
||||||
|
# Upload some media to comment on
|
||||||
|
response, data = self._upload_image(test_app, GOOD_JPG)
|
||||||
|
response, data = self._post_image_to_feed(test_app, data)
|
||||||
|
|
||||||
|
content = "Hai this is a comment on this lovely picture ^_^"
|
||||||
|
|
||||||
|
activity = {
|
||||||
|
"verb": "post",
|
||||||
|
"object": {
|
||||||
|
"objectType": "comment",
|
||||||
|
"content": content,
|
||||||
|
"inReplyTo": data["object"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response, comment_data = self._activity_to_feed(test_app, activity)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
# Find the objects in the database
|
||||||
|
media = MediaEntry.query.filter_by(id=data["object"]["id"]).first()
|
||||||
|
comment = media.get_comments()[0]
|
||||||
|
|
||||||
|
# Tests that it matches in the database
|
||||||
|
assert comment.author == self.user.id
|
||||||
|
assert comment.content == content
|
||||||
|
|
||||||
|
# Test that the response is what we should be given
|
||||||
|
assert comment.id == comment_data["object"]["id"]
|
||||||
|
assert comment.content == comment_data["object"]["content"]
|
||||||
|
|
||||||
|
def test_profile(self, test_app):
|
||||||
|
""" Tests profile endpoint """
|
||||||
|
uri = "/api/user/{0}/profile".format(self.user.username)
|
||||||
|
with mock.patch("mediagoblin.decorators.oauth_required", new_callable=self.mocked_oauth_required):
|
||||||
|
response = test_app.get(uri)
|
||||||
|
profile = json.loads(response.body)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
assert profile["preferredUsername"] == self.user.username
|
||||||
|
assert profile["objectType"] == "person"
|
||||||
|
|
||||||
|
assert "links" in profile
|
||||||
|
@ -347,61 +347,3 @@ def fixture_add_comment_report(comment=None, reported_user=None,
|
|||||||
|
|
||||||
return comment_report
|
return comment_report
|
||||||
|
|
||||||
def fixture_add_oauth_client(client_name=None, client_type="native",
|
|
||||||
redirect_uri=None, contacts=None):
|
|
||||||
|
|
||||||
client_id = random_string(22, OAUTH_ALPHABET)
|
|
||||||
client_secret = random_string(43, OAUTH_ALPHABET)
|
|
||||||
|
|
||||||
client = Client(
|
|
||||||
id=client_id,
|
|
||||||
secret=client_secret,
|
|
||||||
expirey=None,
|
|
||||||
application_type=client_type,
|
|
||||||
application_name=client_name,
|
|
||||||
contacts=contacts,
|
|
||||||
redirect_uri=redirect_uri
|
|
||||||
)
|
|
||||||
client.save()
|
|
||||||
|
|
||||||
return client
|
|
||||||
|
|
||||||
def fixture_add_oauth_request_token(user, client=None):
|
|
||||||
if client is None:
|
|
||||||
client = fixture_add_oauth_client()
|
|
||||||
|
|
||||||
rt_token = random_string(22, OAUTH_ALPHABET)
|
|
||||||
rt_secret = random_string(43, OAUTH_ALPHABET)
|
|
||||||
rt_verifier = random_string(22, OAUTH_ALPHABET)
|
|
||||||
|
|
||||||
request_token = RequestToken(
|
|
||||||
token=rt_token,
|
|
||||||
secret=rt_secret,
|
|
||||||
user=user.id,
|
|
||||||
used=True,
|
|
||||||
authenticated=True,
|
|
||||||
verifier=rt_verifier,
|
|
||||||
)
|
|
||||||
request_token.save()
|
|
||||||
|
|
||||||
return request_token
|
|
||||||
|
|
||||||
def fixture_add_oauth_access_token(user, client=None, request_token=None):
|
|
||||||
if client is None:
|
|
||||||
client = fixture_add_oauth_client()
|
|
||||||
|
|
||||||
if request_token is None:
|
|
||||||
request_token = fixture_add_oauth_request_token(user)
|
|
||||||
|
|
||||||
at_token = random_string(22, OAUTH_ALPHABET)
|
|
||||||
at_secret = random_string(43, OAUTH_ALPHABET)
|
|
||||||
|
|
||||||
access_token = AccessToken(
|
|
||||||
token=at_token,
|
|
||||||
secret=at_secret,
|
|
||||||
user=user.id,
|
|
||||||
request_token=request_token.token
|
|
||||||
)
|
|
||||||
access_token.save()
|
|
||||||
|
|
||||||
return access_token
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user