mirror of
https://git.sr.ht/~tsileo/microblog.pub
synced 2024-11-15 03:04:28 +00:00
parent
afa33b4e7c
commit
126e5e8d59
2 changed files with 67 additions and 18 deletions
|
@ -77,6 +77,7 @@ def _api_required() -> None:
|
||||||
|
|
||||||
# Will raise a BadSignature on bad auth
|
# Will raise a BadSignature on bad auth
|
||||||
payload = JWT.loads(token)
|
payload = JWT.loads(token)
|
||||||
|
flask.g.jwt_payload = payload
|
||||||
app.logger.info(f"api call by {payload}")
|
app.logger.info(f"api call by {payload}")
|
||||||
|
|
||||||
|
|
||||||
|
@ -438,13 +439,50 @@ def api_remove_from_list() -> _Response:
|
||||||
return _user_api_response()
|
return _user_api_response()
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/new_note", methods=["POST"])
|
@blueprint.route("/new_note", methods=["POST"]) # noqa: C901 too complex
|
||||||
@api_required
|
@api_required
|
||||||
def api_new_note() -> _Response:
|
def api_new_note() -> _Response:
|
||||||
source = _user_api_arg("content")
|
source = None
|
||||||
|
summary = None
|
||||||
|
|
||||||
|
# Basic Micropub (https://www.w3.org/TR/micropub/) "create" support
|
||||||
|
is_micropub = False
|
||||||
|
# First, check if the Micropub specific fields are present
|
||||||
|
if (
|
||||||
|
_user_api_arg("h", default=None) == "entry"
|
||||||
|
or _user_api_arg("type", default=[None])[0] == "h-entry"
|
||||||
|
):
|
||||||
|
is_micropub = True
|
||||||
|
# Ensure the "create" scope is set
|
||||||
|
if "jwt_payload" not in flask.g or "create" not in flask.g.jwt_payload["scope"]:
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
# Handle JSON microformats2 data
|
||||||
|
if _user_api_arg("type", default=None):
|
||||||
|
try:
|
||||||
|
source = request.json["properties"]["content"][0]
|
||||||
|
except (ValueError, KeyError):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
summary = request.json["properties"]["name"][0]
|
||||||
|
except (ValueError, KeyError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Try to parse the name as summary if the payload is POSTed using form-data
|
||||||
|
if summary is None:
|
||||||
|
summary = _user_api_arg("name", default=None)
|
||||||
|
|
||||||
|
# This step will also parse content from Micropub request
|
||||||
|
if source is None:
|
||||||
|
source = _user_api_arg("content", default=None)
|
||||||
|
|
||||||
if not source:
|
if not source:
|
||||||
raise ValueError("missing content")
|
raise ValueError("missing content")
|
||||||
|
|
||||||
|
if summary is None:
|
||||||
|
summary = _user_api_arg("summary", default="")
|
||||||
|
|
||||||
|
# All the following fields are specific to the API (i.e. not Micropub related)
|
||||||
_reply, reply = None, None
|
_reply, reply = None, None
|
||||||
try:
|
try:
|
||||||
_reply = _user_api_arg("reply")
|
_reply = _user_api_arg("reply")
|
||||||
|
@ -490,7 +528,7 @@ def api_new_note() -> _Response:
|
||||||
attributedTo=MY_PERSON.id,
|
attributedTo=MY_PERSON.id,
|
||||||
cc=list(set(cc)),
|
cc=list(set(cc)),
|
||||||
to=list(set(to)),
|
to=list(set(to)),
|
||||||
summary=_user_api_arg("summary", default=""),
|
summary=summary,
|
||||||
content=content,
|
content=content,
|
||||||
tag=tags,
|
tag=tags,
|
||||||
source={"mediaType": "text/markdown", "content": source},
|
source={"mediaType": "text/markdown", "content": source},
|
||||||
|
@ -498,27 +536,37 @@ def api_new_note() -> _Response:
|
||||||
context=context,
|
context=context,
|
||||||
)
|
)
|
||||||
|
|
||||||
if "file" in request.files and request.files["file"].filename:
|
if request.files:
|
||||||
file = request.files["file"]
|
for f in request.files.keys():
|
||||||
rfilename = secure_filename(file.filename)
|
if not request.files[f].filename:
|
||||||
with BytesIO() as buf:
|
continue
|
||||||
file.save(buf)
|
|
||||||
oid = MEDIA_CACHE.save_upload(buf, rfilename)
|
|
||||||
mtype = mimetypes.guess_type(rfilename)[0]
|
|
||||||
|
|
||||||
raw_note["attachment"] = [
|
file = request.files[f]
|
||||||
{
|
rfilename = secure_filename(file.filename)
|
||||||
"mediaType": mtype,
|
with BytesIO() as buf:
|
||||||
"name": _user_api_arg("file_description", default=rfilename),
|
file.save(buf)
|
||||||
"type": "Document",
|
oid = MEDIA_CACHE.save_upload(buf, rfilename)
|
||||||
"url": f"{BASE_URL}/uploads/{oid}/{rfilename}",
|
mtype = mimetypes.guess_type(rfilename)[0]
|
||||||
}
|
|
||||||
]
|
raw_note["attachment"] = [
|
||||||
|
{
|
||||||
|
"mediaType": mtype,
|
||||||
|
"name": _user_api_arg("file_description", default=rfilename),
|
||||||
|
"type": "Document",
|
||||||
|
"url": f"{BASE_URL}/uploads/{oid}/{rfilename}",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
note = ap.Note(**raw_note)
|
note = ap.Note(**raw_note)
|
||||||
create = note.build_create()
|
create = note.build_create()
|
||||||
create_id = post_to_outbox(create)
|
create_id = post_to_outbox(create)
|
||||||
|
|
||||||
|
# Return a 201 with the note URL in the Location header if this was a Micropub request
|
||||||
|
if is_micropub:
|
||||||
|
resp = flask.Response("", headers={"Location": create_id})
|
||||||
|
resp.status_code = 201
|
||||||
|
return resp
|
||||||
|
|
||||||
return _user_api_response(activity=create_id)
|
return _user_api_response(activity=create_id)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<link rel="stylesheet" href="/static/pure.css">
|
<link rel="stylesheet" href="/static/pure.css">
|
||||||
<link rel="authorization_endpoint" href="{{ config.ID }}/indieauth">
|
<link rel="authorization_endpoint" href="{{ config.ID }}/indieauth">
|
||||||
<link rel="token_endpoint" href="{{ config.ID }}/token">
|
<link rel="token_endpoint" href="{{ config.ID }}/token">
|
||||||
|
<link rel="micropub" href="{{config.ID}}/api/new_note">
|
||||||
{% if not request.args.get("older_than") and not request.args.get("previous_than") %}<link rel="canonical" href="https://{{ config.DOMAIN }}{{ request.path }}">{% endif %}
|
{% if not request.args.get("older_than") and not request.args.get("previous_than") %}<link rel="canonical" href="https://{{ config.DOMAIN }}{{ request.path }}">{% endif %}
|
||||||
{% block links %}{% endblock %}
|
{% block links %}{% endblock %}
|
||||||
{% if config.THEME_COLOR %}<meta name="theme-color" content="{{ config.THEME_COLOR }}">{% endif %}
|
{% if config.THEME_COLOR %}<meta name="theme-color" content="{{ config.THEME_COLOR }}">{% endif %}
|
||||||
|
|
Loading…
Reference in a new issue