/
inbox.py
121 lines (100 loc) · 3.85 KB
/
inbox.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import asyncio
import aiohttp
from sanic import response, Blueprint
from sanic_openapi import doc
from little_boxes.httpsig import verify_request
from pubgate.api.v1.db.models import User, Inbox, Outbox
from pubgate.api.v1.renders import ordered_collection, context
from pubgate.api.v1.utils import make_label, random_object_id, auth_required
from pubgate.api.v1.deliver import deliver
inbox_v1 = Blueprint('inbox_v1')
@inbox_v1.route('/<user_id>', methods=['POST'])
@doc.summary("Post to user inbox")
@doc.consumes(Inbox, location="body")
async def inbox_post(request, user_id):
user = await User.find_one(dict(username=user_id))
if not user:
return response.json({"zrada": "no such user"}, status=404)
# profile = user_profile(request.app.config.back.base_url, user_id)
activity = request.json.copy()
# TODO verify signature
# x = verify_request(
# request.method, request.path, request.headers, activity
# )
#
# print(x)
# TODO skip blocked
# if Outbox.find_one(
# {
# "activity.type": "Block",
# "user_id": user_id,
# "meta.undo": False,
# }):
# return response.json({"zrada": "actor is blocked"}, status=403)
exists = await Inbox.find_one(dict(_id=activity["id"]))
if exists:
if user_id in exists['users']:
return response.json({"zrada": "activity allready exists"}, status=403)
else:
users = exists['users']
users.append(user_id)
await Inbox.update_one(
{'_id': exists.id},
{'$set': {"users": users}}
)
else:
# TODO validate actor and activity
# Disabled while issue https://github.com/tsileo/little-boxes/issues/8 will be fixed
# try:
# activity = await sync_to_async(parse_activity)(request.json)
# except (UnexpectedActivityTypeError, BadActivityError) as e:
# return response.json({"zrada": e})
await Inbox.insert_one({
"_id": activity["id"],
"users": [user_id],
# "actor_id": activity["acr"]
"activity": activity,
"label": make_label(activity),
"meta": {"undo": False, "deleted": False},
})
if activity["type"] == "Follow":
obj_id = random_object_id()
outbox_url = f"{request.app.v1_path}/outbox/{user_id}"
deliverance = {
"id": f"{outbox_url}/{obj_id}",
"type": "Accept",
"actor": activity["object"],
"object": {
"type": "Follow",
"id": activity["id"],
"actor": activity["actor"],
"object": activity["object"]
}
}
await Outbox.insert_one({
"_id": obj_id,
"user_id": user_id,
"activity": deliverance,
"label": make_label(deliverance),
"meta": {"undo": False, "deleted": False},
})
# post_to_remote_inbox
asyncio.ensure_future(deliver(deliverance, [activity["actor"]]))
return response.json({'peremoga': 'yep'})
@inbox_v1.route('/<user_id>', methods=['GET'])
@doc.summary("Returns user inbox, auth required")
@auth_required
async def inbox_list(request, user_id):
user = await User.find_one(dict(username=user_id))
if not user:
return response.json({"zrada": "no such user"}, status=404)
# TODO pagination
data = await Inbox.find(filter={
"meta.deleted": False,
"users": {"$in": [user_id]}},
sort="activity.published desc"
)
inbox_url = f"{request.app.v1_path}/inbox/{user_id}"
cleaned = [item["activity"] for item in data.objects]
resp = ordered_collection(inbox_url, cleaned)
return response.json(resp, headers={'Content-Type': 'application/jrd+json; charset=utf-8'})