add very basic tag support on upload

This commit is contained in:
sam 2023-10-02 03:39:39 +02:00
parent e2217fbc1d
commit 3f88cc00b5
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
4 changed files with 65 additions and 18 deletions

16
poetry.lock generated
View file

@ -232,14 +232,14 @@ tests = ["dj-database-url", "dj-email-url", "django-cache-url", "pytest"]
[[package]]
name = "flask"
version = "2.3.3"
version = "3.0.0"
description = "A simple framework for building complex web applications."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "flask-2.3.3-py3-none-any.whl", hash = "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b"},
{file = "flask-2.3.3.tar.gz", hash = "sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc"},
{file = "flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638"},
{file = "flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58"},
]
[package.dependencies]
@ -247,7 +247,7 @@ blinker = ">=1.6.2"
click = ">=8.1.3"
itsdangerous = ">=2.1.2"
Jinja2 = ">=3.1.2"
Werkzeug = ">=2.3.7"
Werkzeug = ">=3.0.0"
[package.extras]
async = ["asgiref (>=3.2)"]
@ -515,14 +515,14 @@ files = [
[[package]]
name = "werkzeug"
version = "2.3.7"
version = "3.0.0"
description = "The comprehensive WSGI web application library."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "werkzeug-2.3.7-py3-none-any.whl", hash = "sha256:effc12dba7f3bd72e605ce49807bbe692bd729c3bb122a3b91747a6ae77df528"},
{file = "werkzeug-2.3.7.tar.gz", hash = "sha256:2b8c0e447b4b9dbcc85dd97b6eeb4dcbaf6c8b6c3be0bd654e25553e0a2157d8"},
{file = "werkzeug-3.0.0-py3-none-any.whl", hash = "sha256:cbb2600f7eabe51dbc0502f58be0b3e1b96b893b05695ea2b35b43d4de2d9962"},
{file = "werkzeug-3.0.0.tar.gz", hash = "sha256:3ffff4dcc32db52ef3cc94dff3000a3c2846890f3a5a51800a27b909c5e770f0"},
]
[package.dependencies]
@ -534,4 +534,4 @@ watchdog = ["watchdog (>=2.3)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "a8a740d71fe53f39a3e5d8ff069560abfb1e99db162b77892eb16cd0b34bda9d"
content-hash = "f0bb5dc5c2086b3834b9e7c46313f161aa0dab256d158209eb616101c4010d69"

View file

@ -1,9 +1,11 @@
# SPDX-License-Identifier: Apache-2.0
from datetime import datetime
from flask import Blueprint, g, request, jsonify
from werkzeug.utils import secure_filename
from pyles.db import File
from pyles.db import db, File, Tag, FileTag
from pyles.files import upload_file
from pyles.user import token_required
from pyles.settings import BASE_URL
@ -11,25 +13,49 @@ from pyles.settings import BASE_URL
bp = Blueprint("files_api", __name__)
@bp.post("/upload")
@bp.post("/api/upload")
@token_required
def upload():
file = request.files.get("file")
if not file:
return jsonify({"error": "Missing file"}), 400
expires = None
tags = []
try:
exp = request.args.get("expires", type=int)
expires = datetime.fromtimestamp(exp) if exp else None
except:
pass
if raw_tags := request.args.get("tags"):
tags = [int(raw) for raw in raw_tags.split(",")]
tags: list[Tag] = Tag.select().where(Tag.id.in_(tags), Tag.user_id == g.user.id)
hash, content_type = upload_file(file)
with db.atomic():
db_file: File = File.create(
user=g.user,
filename=secure_filename(file.filename),
hash=hash,
content_type=content_type,
expires=expires,
)
if len(tags) > 0:
FileTag.bulk_create(FileTag(file=db_file, tag=tag) for tag in tags)
return jsonify(
{
"id": db_file.id,
"hash": db_file.hash,
"url": f"{BASE_URL}/{db_file.path}",
"tags": [{"id": tag.id, "name": tag.name} for tag in tags],
}
)
@bp.patch("/api/files/<url_id>")
@token_required
def update_file():
...

View file

@ -3,7 +3,7 @@
from functools import wraps
from itsdangerous.url_safe import URLSafeSerializer
from flask import g, request, redirect, url_for, jsonify
from flask import g, request, redirect, url_for, jsonify, session
from pyles.settings import SECRET_KEY
from pyles.db import User
@ -27,3 +27,24 @@ def token_required(f):
return f(*args, **kwargs)
return inner
def login_required(f):
@wraps(f)
def inner(*args, **kwargs):
token = session.get("token", None)
if not token:
return redirect(url_for("index"))
_, id = URLSafeSerializer(SECRET_KEY).loads_unsafe(token)
u: User = User.get_or_none(id=id)
if u is None:
session.pop("token", None)
return redirect(url_for("index"))
if not u.verify_token(token):
session.pop("token", None)
return redirect(url_for("index"))
g.user = u
return f(*args, **kwargs)
return inner

View file

@ -8,7 +8,7 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11"
flask = "^2.3.3"
flask = "^3.0.0"
itsdangerous = "^2.1.2"
environs = "^9.5.0"
gunicorn = "^21.2.0"