Tombstome handling (#23)

* Better Delete handling

* Tweak the tombstone support

* More work on Tombstone handling
This commit is contained in:
Thomas Sileo 2018-07-10 01:06:32 +02:00 committed by GitHub
parent 3d3e9da800
commit 5a13e4b362
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 12 deletions

View file

@ -24,6 +24,7 @@ from little_boxes import activitypub as ap
from little_boxes import strtobool from little_boxes import strtobool
from little_boxes.activitypub import _to_list from little_boxes.activitypub import _to_list
from little_boxes.backend import Backend from little_boxes.backend import Backend
from little_boxes.errors import ActivityGoneError
from little_boxes.errors import Error from little_boxes.errors import Error
from utils.media import Kind from utils.media import Kind
@ -150,6 +151,8 @@ class MicroblogPubBackend(Backend):
iri = iri.replace("/activity", "") iri = iri.replace("/activity", "")
is_a_note = True is_a_note = True
data = DB.activities.find_one({"box": Box.OUTBOX.value, "remote_id": iri}) data = DB.activities.find_one({"box": Box.OUTBOX.value, "remote_id": iri})
if data and data["meta"]["deleted"]:
raise ActivityGoneError(f"{iri} is gone")
if data and is_a_note: if data and is_a_note:
return data["activity"]["object"] return data["activity"]["object"]
elif data: elif data:
@ -158,6 +161,8 @@ class MicroblogPubBackend(Backend):
# Check if the activity is stored in the inbox # Check if the activity is stored in the inbox
data = DB.activities.find_one({"remote_id": iri}) data = DB.activities.find_one({"remote_id": iri})
if data: if data:
if data["meta"]["deleted"]:
raise ActivityGoneError(f"{iri} is gone")
return data["activity"] return data["activity"]
# Fetch the URL via HTTP # Fetch the URL via HTTP
@ -305,6 +310,12 @@ class MicroblogPubBackend(Backend):
).get_object() ).get_object()
logger.info(f"inbox_delete handle_replies obj={obj!r}") logger.info(f"inbox_delete handle_replies obj={obj!r}")
# Fake a Undo so any related Like/Announce doesn't appear on the web UI
DB.activities.update(
{"meta.object.id": obj.id},
{"$set": {"meta.undo": True, "meta.exta": "object deleted"}},
)
if obj: if obj:
self._handle_replies_delete(as_actor, obj) self._handle_replies_delete(as_actor, obj)
@ -325,6 +336,11 @@ class MicroblogPubBackend(Backend):
)["activity"] )["activity"]
).get_object() ).get_object()
DB.activities.update(
{"meta.object.id": obj.id},
{"$set": {"meta.undo": True, "meta.exta": "object deleted"}},
)
self._handle_replies_delete(as_actor, obj) self._handle_replies_delete(as_actor, obj)
@ensure_it_is_me @ensure_it_is_me

27
app.py
View file

@ -472,7 +472,9 @@ def admin_login():
session["challenge"] = None session["challenge"] = None
session["logged_in"] = True session["logged_in"] = True
return redirect(request.args.get("redirect") or url_for("admin_notifications")) return redirect(
request.args.get("redirect") or url_for("admin_notifications")
)
else: else:
abort(401) abort(401)
@ -940,7 +942,7 @@ def outbox():
# TODO(tsileo): returns the whole outbox if authenticated # TODO(tsileo): returns the whole outbox if authenticated
q = { q = {
"box": Box.OUTBOX.value, "box": Box.OUTBOX.value,
"meta.deleted": False, # TODO(tsileo): retrieve deleted and expose tombstone "meta.deleted": False,
"type": {"$in": [ActivityType.CREATE.value, ActivityType.ANNOUNCE.value]}, "type": {"$in": [ActivityType.CREATE.value, ActivityType.ANNOUNCE.value]},
} }
return jsonify( return jsonify(
@ -974,9 +976,12 @@ def outbox_detail(item_id):
doc = DB.activities.find_one( doc = DB.activities.find_one(
{"box": Box.OUTBOX.value, "remote_id": back.activity_url(item_id)} {"box": Box.OUTBOX.value, "remote_id": back.activity_url(item_id)}
) )
if not doc:
abort(404)
if doc["meta"].get("deleted", False): if doc["meta"].get("deleted", False):
obj = ap.parse_activity(doc["activity"]) obj = ap.parse_activity(doc["activity"])
resp = jsonify(**obj.get_object().get_tombstone()) resp = jsonify(**obj.get_tombstone().to_dict())
resp.status_code = 410 resp.status_code = 410
return resp return resp
return jsonify(**activity_from_doc(doc)) return jsonify(**activity_from_doc(doc))
@ -984,17 +989,18 @@ def outbox_detail(item_id):
@app.route("/outbox/<item_id>/activity") @app.route("/outbox/<item_id>/activity")
def outbox_activity(item_id): def outbox_activity(item_id):
# TODO(tsileo): handle Tombstone
data = DB.activities.find_one( data = DB.activities.find_one(
{ {"box": Box.OUTBOX.value, "remote_id": back.activity_url(item_id)}
"box": Box.OUTBOX.value,
"remote_id": back.activity_url(item_id),
"meta.deleted": False,
}
) )
if not data: if not data:
abort(404) abort(404)
obj = activity_from_doc(data) obj = activity_from_doc(data)
if data["meta"].get("deleted", False):
obj = ap.parse_activity(data["activity"])
resp = jsonify(**obj.get_object().get_tombstone().to_dict())
resp.status_code = 410
return resp
if obj["type"] != ActivityType.CREATE.value: if obj["type"] != ActivityType.CREATE.value:
abort(404) abort(404)
return jsonify(**obj["object"]) return jsonify(**obj["object"])
@ -1002,7 +1008,6 @@ def outbox_activity(item_id):
@app.route("/outbox/<item_id>/replies") @app.route("/outbox/<item_id>/replies")
def outbox_activity_replies(item_id): def outbox_activity_replies(item_id):
# TODO(tsileo): handle Tombstone
if not is_api_request(): if not is_api_request():
abort(404) abort(404)
data = DB.activities.find_one( data = DB.activities.find_one(
@ -1038,7 +1043,6 @@ def outbox_activity_replies(item_id):
@app.route("/outbox/<item_id>/likes") @app.route("/outbox/<item_id>/likes")
def outbox_activity_likes(item_id): def outbox_activity_likes(item_id):
# TODO(tsileo): handle Tombstone
if not is_api_request(): if not is_api_request():
abort(404) abort(404)
data = DB.activities.find_one( data = DB.activities.find_one(
@ -1077,7 +1081,6 @@ def outbox_activity_likes(item_id):
@app.route("/outbox/<item_id>/shares") @app.route("/outbox/<item_id>/shares")
def outbox_activity_shares(item_id): def outbox_activity_shares(item_id):
# TODO(tsileo): handle Tombstone
if not is_api_request(): if not is_api_request():
abort(404) abort(404)
data = DB.activities.find_one( data = DB.activities.find_one(