summaryrefslogtreecommitdiffstats
path: root/routes/uploads.py
diff options
context:
space:
mode:
authorFulgen301 <tokmajigeorge@gmail.com>2018-09-16 16:58:21 +0200
committerFulgen301 <tokmajigeorge@gmail.com>2018-09-16 16:58:21 +0200
commit027139279aa0e83c123ba26139d84505f1d4af90 (patch)
treeff9ecd64cab21f2b034288a476870282fb944fa5 /routes/uploads.py
parent0184fbb68c8bf1d8d1a123929dfab0497d5236af (diff)
downloadparry-027139279aa0e83c123ba26139d84505f1d4af90.tar.gz
parry-027139279aa0e83c123ba26139d84505f1d4af90.zip
Use sqlalchemy as backend, implement JWT authentication, add uploading, commenting and voting
Diffstat (limited to 'routes/uploads.py')
-rw-r--r--routes/uploads.py276
1 files changed, 168 insertions, 108 deletions
diff --git a/routes/uploads.py b/routes/uploads.py
index 5c7d7fc..3777795 100644
--- a/routes/uploads.py
+++ b/routes/uploads.py
@@ -13,68 +13,46 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from ..helpers import *
-import string, magic
+from .media import *
+from bottle import delete, put
+from itertools import chain
+import string
-def _add_upload(entry : Upload, session : DBSession):
- return {
- "voting" : {
- "sum" : 0,
- "count" : 0,
- "votes" : None
- },
- "id" : entry.id,
- "title" : entry.title,
- "author" : {
- "id" : entry.author.id if entry.author is not None else "0" * 24,
- "username" : entry.author.name if entry.author is not None else "N/A"
- },
- "tags" : entry.tags,
- "files" : [{
- "metadata" : {
- "hashes" : {
- "sha1" : file.hash
- }
- },
- "aliases" : None,
- "deleted" : False,
- "id" : file.id,
- "filename" : file.name,
- "content-type" : file.content_type,
- "length" : file.length,
- "chunkSize" : BLOCKSIZE,
- "uploadData" : file.date.isoformat()
- } for file in session.query(File).filter_by(upload=entry)
- ],
- "dependencies" : [], #TODO
- "deleted" : False,
- "description" : entry.description,
- "pic" : None, #TODO
- "slug" : entry.slug,
- "createdAt" : entry.created_at.isoformat(),
- "updatedAt" : entry.updated_at.isoformat(),
- "__v" : entry._v,
- "comments" : [{
- "voting" : {
- "sum" : 0,
- "count" : 0,
- "votes" : None
- },
- "deleted" : False,
- "id" : comment.id,
- "body" : comment.body,
- "author" : {
- "id" : comment.author.id,
- "username" : comment.author.name
- },
- "upload" : comment.upload.id,
- "createdAt" : comment.created_at.isoformat(),
- "updatedAt" : comment.updated_at.isoformat()
- } for comment in session.query(Comment).filter_by(upload=entry)
- ]
+_vote_dummy = {
+ "voting" : {
+ "sum" : 0,
+ "count" : 0,
+ "votes" : None
}
+ }
+
+def _add_upload(entry : Upload, session : DBSession):
+ e = entry.json()
+
+ #e.update(_vote_dummy)
+
+ e["comments"] = [{**(comment.json()), **_vote_dummy} for comment in session.query(Comment).filter_by(upload=entry)]
+ e["files"] = []
+ e["pictures"] = []
+
+ for file in session.query(File).filter_by(upload=entry):
+ if not file.content_type.startswith("image"):
+ e["files"].append(file.json())
+ else:
+ e["pictures"].append(file.json())
+
+ e["dependencies"] = [] #TODO
+
+ votes = session.query(Vote).filter_by(upload=entry)
+ e["voting"] = {
+ "sum" : sum(i.vote for i in votes),
+ "count" : votes.count()
+ }
+
+ return e
-@route("/api/uploads")
+@get("/api/uploads")
def get_uploads():
ret = {
"pagination" : {
@@ -89,36 +67,32 @@ def get_uploads():
session = DBSession()
for entry in session.query(Upload).order_by(Upload.updated_at.desc()):
ret["uploads"].append(_add_upload(entry, session))
-
ret["pagination"]["total"] = ret["pagination"]["limit"] = len(ret["uploads"])
return ret
-@route("/api/uploads/<id>")
-def get_upload(id):
- session = DBSession()
- entry = session.query(Upload).get(id)
- if entry is not None:
- return _add_upload(entry, session)
- else:
- raise HTTPResponse(status=404)
-
-@route("/api/uploads", method="POST")
-@auth_basic
-def post_upload():
+@post("/api/uploads")
+@put("/api/uploads/<id>")
+@jwt_auth_required
+def post_upload(id=None):
try:
session = DBSession()
- if len(session.query(Upload).filter_by(title=requests.forms.title).all()):
- raise HTTPResponse("An entry with the specified title already exists", 410)
+ if id is not None:
+ entry = session.query(Upload).get(id)
+ if not entry:
+ raise HTTPResponse(status=404)
+ else:
+ if session.query(Upload).filter_by(title=request_data()["title"]).count():
+ raise HTTPResponse("An entry with the specified title already exists", 410)
+
+ entry = Upload()
- entry = Upload(
- title=request.forms.title,
- author=session.query(User).filter_by(username=request.forms.username),
- description=request.forms.description,
- slug="".join(i for i in requests.forms.title.lower() if i in string.ascii_letters),
- tags=request.forms.tags.split(";") if "tags" in request.forms else []
- )
+ entry.title = request_data()["title"]
+ entry.description=request_data()["description"]
+ entry.slug = "".join(i for i in request_data()["title"].lower() if i in string.ascii_letters)
+ entry.tags = request_data().get("tags", [])
+ entry.author = get_user(session)
session.add(entry)
@@ -127,58 +101,144 @@ def post_upload():
except FileExistsError:
pass
- for file in request.files.values():
- f = File(
- name=file.filename,
- upload=entry
- )
-
- path = os.path.join(os.getcwd(), "media", f["id"])
- file.save(path)
-
- with open(path, "rb") as fobj:
- f.hash = calculateHashForFile(fobj).hexdigest()
- f.length = fobj.tell()
-
- f.content_type = magic.from_file(path, mime=True)
- session.add(f)
-
+ file_ids = []
+ if "files" in request_data():
+ for f in request_data()["files"]:
+ try:
+ f = f["id"]
+ except TypeError:
+ pass
+ if ObjectId.is_valid(f):
+ file_ids.append(ObjectId(f))
+ file = session.query(File).get(id)
+ file.upload = entry
+ session.add(file)
+
+ else:
+ for file in request.files.values():
+ f = _upload_file(file, entry)
+ session.add(f)
+ file_ids.append(f.id)
+
+ for file in session.query(File).filter(File.upload_id == entry.id, ~File.id.in_(file_ids)): # we change the upload above, so we can't use Filter.upload
+ session.delete(file)
+
except KeyError as e:
session.rollback()
raise HTTPResponse(f"Missing form value: {e.args[0]}", 400)
session.commit()
- return HTTPResponse(status=201)
+ return HTTPResponse(status=(201 if id is not None else 204))
-@route("/api/uploads/<id>/comments", method="POST")
-@auth_basic
-def post_comments(id):
+
+@get("/api/uploads/<id>")
+def get_upload(id):
session = DBSession()
+ entry = session.query(Upload).get(id)
+ if entry is not None:
+ return _add_upload(entry, session)
+
+ raise HTTPResponse(status=404)
+
+@delete("/api/uploads/<id>")
+@jwt_auth_required
+def delete_upload(id):
+ session = DBSession()
+ author = get_user(session)
try:
- session.query(Upload).filter_by(id=id).one()
+ entry = session.query(Upload).filter_by(id=id, author=author).one()
except db.orm.exc.NoResultFound:
+ raise HTTPResponse(status=404)
+
+ if entry.readonly:
+ raise HTTPResponse("Resource is read-only", 403)
+
+ session.delete(entry)
+ for i in [Comment, Voting]:
+ for e in session.query(i).filter_by(upload=entry):
+ session.delete(e)
+
+ for f in session.query(File).filter_by(upload=entry):
+ session.delete(e)
+ _delete_file(f)
+
+ #TODO: Dependencies
+ session.commit()
+ return HTTPResponse(status=204)
+
+
+@get("/api/uploads/<id>/comments")
+def get_comments(id):
+ session = DBSession()
+ upload = session.query(Upload).get(id)
+ if upload is None:
+ raise HTTPResponse("Invalid upload id", 404)
+
+ return {
+ "comments" : [{**(comment.json()), **_vote_dummy} for comment in session.query(Comment).filter_by(upload=upload)]
+ }
+
+@post("/api/uploads/<id>/comments")
+@jwt_auth_required
+def post_comments(id):
+ session = DBSession()
+ upload = session.query(Upload).get(id)
+ if upload is None:
raise HTTPResponse("Invalid upload id", 404)
try:
session.add(Comment(
- body=request.forms.body,
- author=session.query(User).filter_by(username=request.forms.username).one()
+ body=request_data()["body"],
+ author=get_user(session),
+ upload=upload
))
except KeyError as e:
- raise HTTPResponse(f"Missing form value: {e.args[0]}", 400)
+ raise HTTPResponse(f"Missing json value: {e.args[0]}", 400)
session.commit()
return HTTPResponse(status=201)
-@route("/api/uploads/<id>/comments/<comment_id>", method="DELETE")
-@auth_basic
+@delete("/api/uploads/<id>/comments/<comment_id>")
+@jwt_auth_required
def delete_comments(id, comment_id):
session = DBSession()
try:
- comment = session.query(Comment).filter_by(id=comment_id, author=session.query(User).filter_by(username).one(), upload=session.query(Upload).filter_by(id=id).one()).one()
+ comment = session.query(Comment).filter_by(id=comment_id, author=get_user(session), upload=session.query(Upload).get(id)).one()
except db.orm.exc.NoResultFound:
- raise HTTPResponse("Requested comment not found", 404)
+ raise HTTPResponse(status=404)
session.delete(comment)
session.commit()
return HTTPResponse(status=204)
+
+@get("/api/uploads/<id>/vote")
+@jwt_auth_required
+def get_vote(id):
+ session = DBSession()
+ upload = session.query(Upload).get(id)
+ if upload is None:
+ raise HTTPResponse("Invalid upload id", 404)
+
+ try:
+ return session.query(Vote).filter_by(upload=upload, author=get_user(session)).one().json()
+ except db.orm.exc.NoResultFound:
+ raise HTTPResponse(status=404)
+
+@post("/api/uploads/<id>/vote")
+@jwt_auth_required
+def post_vote(id):
+ session = DBSession()
+ upload = session.query(Upload).get(id)
+ if upload is None:
+ raise HTTPResponse("Invalid upload id", 404)
+
+ author = get_user(session)
+ try:
+ vote = session.query(Vote).filter_by(upload=upload, author=author).one()
+ except db.orm.exc.NoResultFound:
+ vote = Vote(author=author, upload=upload)
+
+ vote.impact = request_data()["impact"]
+ session.add(vote)
+ session.commit()
+ return HTTPResponse(status=204)