From fc8527d69f204ae74a3afea7778ad716fb93b243 Mon Sep 17 00:00:00 2001 From: Ada Date: Tue, 26 Sep 2023 14:53:08 +0200 Subject: [PATCH] add(backend): possibility to delete paste --- paste/db.py | 7 ++++-- paste/home.py | 45 ++++++++++++++++++++++++++---------- paste/templates/home.html.j2 | 18 +++++++++++---- paste/utils.py | 9 ++++++++ 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/paste/db.py b/paste/db.py index 938672e..ed26bc3 100755 --- a/paste/db.py +++ b/paste/db.py @@ -26,9 +26,10 @@ def check_content_exist(key: str) -> bool: return db.exists(key) -def insert_content_db(url_id: str, expiration: int, content: str) -> None: +def insert_content_db(url_id: str, expiration: int, content: str, secret: str) -> None: """ + :param secret: Secret key for delete url :param url_id: key for access to content. :param expiration: Content expiration in second. :param content: Paste content @@ -36,7 +37,9 @@ def insert_content_db(url_id: str, expiration: int, content: str) -> None: """ if not check_content_exist(url_id): db = connect_redis() - db.set(url_id, content) + data = {"content": content, "secret": secret} + for key, key_content in data.items(): + db.hset(url_id, key, key_content) db.expire(url_id, expiration) else: logging.error(f"Key : {url_id} already exist") # noqa: G004 diff --git a/paste/home.py b/paste/home.py index b7a4fb4..939b64b 100755 --- a/paste/home.py +++ b/paste/home.py @@ -1,31 +1,35 @@ """Manage view and create paste.""" + from flask import ( Blueprint, + abort, flash, redirect, render_template, request, - url_for, abort, + url_for, ) from werkzeug import Response from paste.db import check_content_exist, connect_redis, insert_content_db -from paste.utils import generate_id +from paste.utils import generate_id, generate_secret home = Blueprint("home", __name__, url_prefix="/") -def create_paste(content: str, time:int) -> str: +def create_paste(content: str, time: int) -> dict[str, str]: """ Create paste in DB. + :param time: Expiration time in second :param content: Content to add in redis. - :return: None. + :return: A dict with url_id and delete secret. """ + secret = generate_secret() url_id = generate_id() while check_content_exist(url_id): url_id = generate_id() - insert_content_db(url_id, time, content) - return url_id + insert_content_db(url_id, time, content, secret) + return {"url_id": url_id, "secret": secret} @home.route("/") @@ -47,11 +51,28 @@ def create() -> Response: time = request.form.get("time") time = 86400 if time == "" else int(time) - url_id = create_paste(content, time) - flash(f"{request.host_url}{url_id}") + flash_data = create_paste(content, time) + flash(flash_data["url_id"], category="create") + flash(flash_data["secret"], category="create") return redirect(url_for("home.homepage")) +@home.route("/delete/") +def delete_paste(path: str) -> Response: + """ + Delete a paste + :param path: path fetched from url + :return: forbidden (403) or homepage. + """ + db = connect_redis() + secret = request.args.get("secret") + if db.hget(path, "secret") == secret: + db.delete(path) + flash(path, category="delete") + return redirect(url_for("home.homepage")) + return abort(403) + + @home.route("/") def get_content(path: str) -> str: """ @@ -60,9 +81,9 @@ def get_content(path: str) -> str: :return: Paste content. """ db = connect_redis() - data = db.get(path) + data = db.hgetall(path) if check_content_exist(path): - flash(data) + flash(data["content"]) return render_template("content.html.j2") - else: - abort(404) + + return abort(404) diff --git a/paste/templates/home.html.j2 b/paste/templates/home.html.j2 index 580c897..cc8ccee 100755 --- a/paste/templates/home.html.j2 +++ b/paste/templates/home.html.j2 @@ -1,11 +1,21 @@
- +
-{% with messages = get_flashed_messages() %} - {% if messages %} -

Paste available at : {{ messages[0] }}

+{% with messages = get_flashed_messages(category_filter=["create"]) %} + {% if messages[0] %} +

Paste available at : {{ messages[0] }}

+ {% endif %} + {% if messages[1] %} +

You can delete paste with : delete

{% endif %} {% endwith %} + +{% with messages = get_flashed_messages(category_filter=["delete"]) %} + {% if messages[0] %} +

Paste {{ messages[0] }} deleted

+ {% endif %} +{% endwith %} + diff --git a/paste/utils.py b/paste/utils.py index 3135afb..8183b60 100755 --- a/paste/utils.py +++ b/paste/utils.py @@ -1,6 +1,7 @@ # ruff: noqa: S311 """Shared utils function.""" import random +import secrets import string from paste import config @@ -15,3 +16,11 @@ def generate_id() -> str: random.choices(string.ascii_letters + string.digits, k=config.URL_LENGTH) ) + + +def generate_secret() -> str: + """ + Generate hex secret for delete paste. + :return: The secret. + """ + return secrets.token_hex()