diff --git a/slinky/__init__.py b/slinky/__init__.py
index f524612..69756ca 100644
--- a/slinky/__init__.py
+++ b/slinky/__init__.py
@@ -71,7 +71,7 @@ class Slinky:
"""
shortcode = random_string(length=length)
- if self.get(shortcode).url:
+ if self.get_by_shortcode(shortcode).url:
raise ValueError(f'Shortcode {shortcode} already exists')
dbentry = db.ShortURL(
@@ -85,7 +85,7 @@ class Slinky:
return shortcode
- def get(self, shortcode: str) -> Shortcode:
+ def get_by_shortcode(self, shortcode: str) -> Shortcode:
"""
Return a Shortcode object for a given shortcode
@@ -130,3 +130,15 @@ class Slinky:
Shortcode: full Shortcode object for the given shortcode
"""
return list(self.session.query(db.ShortURL).all())
+
+ def delete_by_shortcode(self, shortcode: str) -> None:
+ """
+ Delete shortcode entry
+
+ Args:
+ shortcode (str): Shortcode of entry to delete
+ """
+ entry = self.session.query(db.ShortURL).filter_by(shortcode=shortcode).first()
+
+ self.session.delete(entry)
+ self.session.commit()
diff --git a/slinky/templates/add.html b/slinky/templates/add.html
index 61d40c8..4851bae 100644
--- a/slinky/templates/add.html
+++ b/slinky/templates/add.html
@@ -28,7 +28,7 @@
- {{request.host_url}}{{ shortcode }} |
+ {{request.host_url}}{{ shortcode }} |
diff --git a/slinky/templates/list.html b/slinky/templates/list.html
index 8c5cd90..f9fd973 100644
--- a/slinky/templates/list.html
+++ b/slinky/templates/list.html
@@ -15,6 +15,7 @@
URL |
Remaining views |
Expiry date |
+ |
@@ -24,6 +25,14 @@
{{ shortcode.url }} |
{{ shortcode.fixed_views if shortcode.fixed_views >= 0 else 'Unlimited' }} |
{{ shortcode.expiry if shortcode.expiry != '9999-12-31 23:59:59.999999' else 'None' }} |
+
+
+ |
{% endfor -%}
diff --git a/slinky/web.py b/slinky/web.py
index 66503af..755a459 100644
--- a/slinky/web.py
+++ b/slinky/web.py
@@ -8,7 +8,7 @@ from datetime import datetime
import yaml
from flask import Blueprint, Response, redirect, render_template
from flask_wtf import FlaskForm
-from wtforms import DateTimeLocalField, IntegerField, StringField
+from wtforms import DateTimeLocalField, HiddenField, IntegerField, StringField
from wtforms.validators import DataRequired, Length
from slinky import Slinky
@@ -19,9 +19,17 @@ with open('config.yaml', encoding='utf-8-sig') as conffile:
cfg = yaml.safe_load(conffile)
-class ShortURLForm(FlaskForm): # type: ignore[misc]
+class DelForm(FlaskForm): # type: ignore[misc]
"""
- Web form definition
+ Delete form definition
+ """
+
+ delete = HiddenField('delete')
+
+
+class AddForm(FlaskForm): # type: ignore[misc]
+ """
+ Add form definition
"""
url = StringField(
@@ -69,7 +77,7 @@ def try_path_as_shortcode(path: str) -> Response:
"""
should_redirect = True
slinky = Slinky(cfg['db'])
- shortcode = slinky.get(path)
+ shortcode = slinky.get_by_shortcode(path)
if shortcode.url:
if shortcode.fixed_views == 0:
logging.warning('Shortcode out of views')
@@ -97,7 +105,7 @@ def add() -> Response:
shortcode = ''
url = ''
- form = ShortURLForm(meta={'csrf': False})
+ form = AddForm(meta={'csrf': False})
if form.is_submitted():
url = form.url.data.strip()
@@ -129,5 +137,10 @@ def lister() -> str:
Returns:
str: shortcode for the URL
"""
+ form = DelForm(meta={'csrf': False})
slinky = Slinky(cfg['db'])
- return render_template('list.html', shortcodes=slinky.get_all())
+
+ if form.is_submitted():
+ slinky.delete_by_shortcode(form.delete.data.strip())
+
+ return render_template('list.html', form=form, shortcodes=slinky.get_all())
diff --git a/tests/test_slinky.py b/tests/test_slinky.py
index 033571e..76af67b 100644
--- a/tests/test_slinky.py
+++ b/tests/test_slinky.py
@@ -43,7 +43,9 @@ class TestSlinky(TestCase):
Ensure we can fetch a URL for a known shortcode
"""
- self.assertEqual('https://example.com', Slinky(self.test_db).get('egie').url)
+ self.assertEqual(
+ 'https://example.com', Slinky(self.test_db).get_by_shortcode('egie').url
+ )
@mock.patch('sqlalchemy.orm.session.Session.add', return_value=None)
@mock.patch('slinky.random_string', return_value='egie')
diff --git a/tests/test_web.py b/tests/test_web.py
index 3f47f19..4dda8b6 100644
--- a/tests/test_web.py
+++ b/tests/test_web.py
@@ -47,7 +47,7 @@ class TestWeb(TestCase):
@mock.patch('slinky.random_string', return_value='egie')
def test_no_unique_shortcode(self, *_: Any) -> None:
"""
- Ensure non-unique shortcodes return a 500 error
+ Ensure non-unique shortcode generation returns a 500 error
"""
response = web.add()
self.assertEqual(response.status_code, 500)