add very basic tag support on upload
This commit is contained in:
parent
e2217fbc1d
commit
3f88cc00b5
4 changed files with 65 additions and 18 deletions
16
poetry.lock
generated
16
poetry.lock
generated
|
@ -232,14 +232,14 @@ tests = ["dj-database-url", "dj-email-url", "django-cache-url", "pytest"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flask"
|
name = "flask"
|
||||||
version = "2.3.3"
|
version = "3.0.0"
|
||||||
description = "A simple framework for building complex web applications."
|
description = "A simple framework for building complex web applications."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "flask-2.3.3-py3-none-any.whl", hash = "sha256:f69fcd559dc907ed196ab9df0e48471709175e696d6e698dd4dbe940f96ce66b"},
|
{file = "flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638"},
|
||||||
{file = "flask-2.3.3.tar.gz", hash = "sha256:09c347a92aa7ff4a8e7f3206795f30d826654baf38b873d0744cd571ca609efc"},
|
{file = "flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -247,7 +247,7 @@ blinker = ">=1.6.2"
|
||||||
click = ">=8.1.3"
|
click = ">=8.1.3"
|
||||||
itsdangerous = ">=2.1.2"
|
itsdangerous = ">=2.1.2"
|
||||||
Jinja2 = ">=3.1.2"
|
Jinja2 = ">=3.1.2"
|
||||||
Werkzeug = ">=2.3.7"
|
Werkzeug = ">=3.0.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
async = ["asgiref (>=3.2)"]
|
async = ["asgiref (>=3.2)"]
|
||||||
|
@ -515,14 +515,14 @@ files = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "werkzeug"
|
name = "werkzeug"
|
||||||
version = "2.3.7"
|
version = "3.0.0"
|
||||||
description = "The comprehensive WSGI web application library."
|
description = "The comprehensive WSGI web application library."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "werkzeug-2.3.7-py3-none-any.whl", hash = "sha256:effc12dba7f3bd72e605ce49807bbe692bd729c3bb122a3b91747a6ae77df528"},
|
{file = "werkzeug-3.0.0-py3-none-any.whl", hash = "sha256:cbb2600f7eabe51dbc0502f58be0b3e1b96b893b05695ea2b35b43d4de2d9962"},
|
||||||
{file = "werkzeug-2.3.7.tar.gz", hash = "sha256:2b8c0e447b4b9dbcc85dd97b6eeb4dcbaf6c8b6c3be0bd654e25553e0a2157d8"},
|
{file = "werkzeug-3.0.0.tar.gz", hash = "sha256:3ffff4dcc32db52ef3cc94dff3000a3c2846890f3a5a51800a27b909c5e770f0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -534,4 +534,4 @@ watchdog = ["watchdog (>=2.3)"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.11"
|
python-versions = "^3.11"
|
||||||
content-hash = "a8a740d71fe53f39a3e5d8ff069560abfb1e99db162b77892eb16cd0b34bda9d"
|
content-hash = "f0bb5dc5c2086b3834b9e7c46313f161aa0dab256d158209eb616101c4010d69"
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import Blueprint, g, request, jsonify
|
from flask import Blueprint, g, request, jsonify
|
||||||
from werkzeug.utils import secure_filename
|
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.files import upload_file
|
||||||
from pyles.user import token_required
|
from pyles.user import token_required
|
||||||
from pyles.settings import BASE_URL
|
from pyles.settings import BASE_URL
|
||||||
|
@ -11,25 +13,49 @@ from pyles.settings import BASE_URL
|
||||||
bp = Blueprint("files_api", __name__)
|
bp = Blueprint("files_api", __name__)
|
||||||
|
|
||||||
|
|
||||||
@bp.post("/upload")
|
@bp.post("/api/upload")
|
||||||
@token_required
|
@token_required
|
||||||
def upload():
|
def upload():
|
||||||
file = request.files.get("file")
|
file = request.files.get("file")
|
||||||
if not file:
|
if not file:
|
||||||
return jsonify({"error": "Missing file"}), 400
|
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)
|
hash, content_type = upload_file(file)
|
||||||
|
|
||||||
|
with db.atomic():
|
||||||
db_file: File = File.create(
|
db_file: File = File.create(
|
||||||
user=g.user,
|
user=g.user,
|
||||||
filename=secure_filename(file.filename),
|
filename=secure_filename(file.filename),
|
||||||
hash=hash,
|
hash=hash,
|
||||||
content_type=content_type,
|
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(
|
return jsonify(
|
||||||
{
|
{
|
||||||
"id": db_file.id,
|
"id": db_file.id,
|
||||||
"hash": db_file.hash,
|
"hash": db_file.hash,
|
||||||
"url": f"{BASE_URL}/{db_file.path}",
|
"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():
|
||||||
|
...
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from itsdangerous.url_safe import URLSafeSerializer
|
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.settings import SECRET_KEY
|
||||||
from pyles.db import User
|
from pyles.db import User
|
||||||
|
@ -27,3 +27,24 @@ def token_required(f):
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
return inner
|
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
|
||||||
|
|
|
@ -8,7 +8,7 @@ readme = "README.md"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.11"
|
python = "^3.11"
|
||||||
flask = "^2.3.3"
|
flask = "^3.0.0"
|
||||||
itsdangerous = "^2.1.2"
|
itsdangerous = "^2.1.2"
|
||||||
environs = "^9.5.0"
|
environs = "^9.5.0"
|
||||||
gunicorn = "^21.2.0"
|
gunicorn = "^21.2.0"
|
||||||
|
|
Loading…
Reference in a new issue