Add basic comment support and flesh out some other endpoints
[mediagoblin.git] / mediagoblin / federation / views.py
1 import json
2
3 from mediagoblin.decorators import oauth_required
4 from mediagoblin.db.models import User, MediaEntry, MediaComment
5 from mediagoblin.tools.response import redirect, json_response
6 from mediagoblin.meddleware.csrf import csrf_exempt
7
8 #@oauth_required
9 def profile(request, raw=False):
10 """ This is /api/user/<username>/profile - This will give profile info """
11 user = request.matchdict["username"]
12 requested_user = User.query.filter_by(username=user)
13
14 # check if the user exists
15 if requested_user is None:
16 error = "No such 'user' with id '{0}'".format(user)
17 return json_response({"error": error}, status=404)
18
19 user = requested_user[0]
20
21 if raw:
22 return (user, user.serialize(request))
23
24 # user profiles are public so return information
25 return json_response(user.serialize(request))
26
27 def user(request):
28 """ This is /api/user/<username> - This will get the user """
29 user, user_profile = profile(request, raw=True)
30 data = {
31 "nickname": user.username,
32 "updated": user.created.isoformat(),
33 "published": user.created.isoformat(),
34 "profile": user_profile
35 }
36
37 return json_response(data)
38
39 @oauth_required
40 @csrf_exempt
41 def feed(request):
42 """ Handles the user's outbox - /api/user/<username>/feed """
43 print request.user
44 user = request.matchdict["username"]
45 requested_user = User.query.filter_by(username=user)
46
47 # check if the user exists
48 if requested_user is None:
49 error = "No such 'user' with id '{0}'".format(user)
50 return json_response({"error": error}, status=404)
51
52 user = requested_user[0]
53
54 if request.method == "POST":
55 data = json.loads(request.data)
56 obj = data.get("object", None)
57 if obj is None:
58 error = {"error": "Could not find 'object' element."}
59 return json_response(error, status=400)
60
61 if obj.get("objectType", None) == "comment":
62 # post a comment
63 media = int(data["object"]["inReplyTo"]["id"])
64 author = request.user
65 comment = MediaComment(
66 media_entry=media,
67 author=request.user.id,
68 content=data["object"]["content"]
69 )
70 comment.save()
71 elif obj.get("objectType", None) is None:
72 error = {"error": "No objectType specified."}
73 return json_response(error, status=400)
74 else:
75 error = {"error": "Unknown object type '{0}'.".format(obj.get("objectType", None))}
76 return json_response(error, status=400)
77
78 feed_url = request.urlgen(
79 "mediagoblin.federation.feed",
80 username=user.username,
81 qualified=True
82 )
83
84 feed = {
85 "displayName": "Activities by {0}@{1}".format(user.username, request.host),
86 "objectTypes": ["activity"],
87 "url": feed_url,
88 "links": {
89 "first": {
90 "href": feed_url,
91 },
92 "self": {
93 "href": request.url,
94 },
95 "prev": {
96 "href": feed_url,
97 },
98 "next": {
99 "href": feed_url,
100 }
101 },
102 "author": user.serialize(request),
103 "items": [],
104 }
105
106
107 # Now lookup the user's feed.
108 for media in MediaEntry.query.all():
109 feed["items"].append({
110 "verb": "post",
111 "object": media.serialize(request),
112 "actor": user.serialize(request),
113 "content": "{0} posted a picture".format(user.username),
114 "id": 1,
115 })
116 feed["items"][-1]["updated"] = feed["items"][-1]["object"]["updated"]
117 feed["items"][-1]["published"] = feed["items"][-1]["object"]["published"]
118 feed["items"][-1]["url"] = feed["items"][-1]["object"]["url"]
119 feed["totalItems"] = len(feed["items"])
120
121 return json_response(feed)
122
123 @oauth_required
124 def inbox(request):
125 """ Handles the user's inbox - /api/user/<username>/inbox """
126 raise NotImplemented("Yet to implement looking up user's inbox")
127
128 #@oauth_required
129 def object(request, raw_obj=False):
130 """ Lookup for a object type """
131 objectType = request.matchdict["objectType"]
132 uuid = request.matchdict["uuid"]
133 if objectType not in ["image"]:
134 error = "Unknown type: {0}".format(objectType)
135 # not sure why this is 404, maybe ask evan. Maybe 400?
136 return json_response({"error": error}, status=404)
137
138 media = MediaEntry.query.filter_by(slug=uuid).first()
139 if media is None:
140 # no media found with that uuid
141 error = "Can't find a {0} with ID = {1}".format(objectType, uuid)
142 return json_response({"error": error}, status=404)
143
144 if raw_obj:
145 return media
146
147 return json_response(media.serialize(request))
148
149 def object_comments(request):
150 """ Looks up for the comments on a object """
151 media = object(request, raw_obj=True)
152 response = media
153 if isinstance(response, MediaEntry):
154 comments = response.serialize(request)
155 comments = comments.get("replies", {
156 "totalItems": 0,
157 "items": [],
158 "url": request.urlgen(
159 "mediagoblin.federation.object.comments",
160 objectType=media.objectType,
161 uuid=media.slug,
162 qualified=True)
163 })
164 comments["displayName"] = "Replies to {0}".format(comments["url"])
165 comments["links"] = {
166 "first": comments["url"],
167 "self": comments["url"],
168 }
169 response = json_response(comments)
170
171 return response
172
173
174 ##
175 # Well known
176 ##
177 def host_meta(request):
178 """ This is /.well-known/host-meta - provides URL's to resources on server """
179 links = []
180
181 # Client registration links
182 links.append({
183 "ref": "registration_endpoint",
184 "href": request.urlgen("mediagoblin.oauth.client_register", qualified=True),
185 })
186 links.append({
187 "ref": "http://apinamespace.org/oauth/request_token",
188 "href": request.urlgen("mediagoblin.oauth.request_token", qualified=True),
189 })
190 links.append({
191 "ref": "http://apinamespace.org/oauth/authorize",
192 "href": request.urlgen("mediagoblin.oauth.authorize", qualified=True),
193 })
194 links.append({
195 "ref": "http://apinamespace.org/oauth/access_token",
196 "href": request.urlgen("mediagoblin.oauth.access_token", qualified=True),
197 })
198
199 return json_response({"links": links})
200
201 def whoami(request):
202 """ This is /api/whoami - This is a HTTP redirect to api profile """
203 profile = request.urlgen(
204 "mediagoblin.federation.user.profile",
205 username=request.user.username,
206 qualified=True
207 )
208
209 return redirect(request, location=profile)