Created {{ post.created | naturalday }},
diff --git a/akarpov/templates/files/view.html b/akarpov/templates/files/view.html
index acacdb3..c5a9e85 100644
--- a/akarpov/templates/files/view.html
+++ b/akarpov/templates/files/view.html
@@ -1,4 +1,5 @@
{% extends 'base.html' %}
+{% load users_extras %}
{% load static %}
{% block meta %}
@@ -35,9 +36,7 @@
{% if not has_perm %}
-
Uploaded by:
- {% if file.user.image_cropped %} {% endif %}
- {{ file.user.username }}
+
Uploaded by: {% user_badge file.creator %}
{% endif %}
Last updated: {{ file.modified|date:"d.m.Y" }} {{ file.modified|time:"H:i" }}
File size: {{ file.file_size | filesizeformat }}
diff --git a/akarpov/templates/tools/shortener/public_view.html b/akarpov/templates/tools/shortener/public_view.html
new file mode 100644
index 0000000..6087111
--- /dev/null
+++ b/akarpov/templates/tools/shortener/public_view.html
@@ -0,0 +1,18 @@
+{% extends 'base.html' %}
+{% load users_extras %}
+{% load static %}
+
+{% block content %}
+
+
+
Issued by: {% user_badge link.creator %}
+
{{ request.get_host }}{% url 'short_url' slug=link.slug %}
+
+
+
+
+{% endblock %}
diff --git a/akarpov/templates/users/badge.html b/akarpov/templates/users/badge.html
new file mode 100644
index 0000000..51ff97b
--- /dev/null
+++ b/akarpov/templates/users/badge.html
@@ -0,0 +1,3 @@
+
+{% if user.image_cropped %} {% endif %}
+{{ user.username }}
diff --git a/akarpov/templates/users/user_detail.html b/akarpov/templates/users/user_detail.html
index 780d627..7e071d9 100644
--- a/akarpov/templates/users/user_detail.html
+++ b/akarpov/templates/users/user_detail.html
@@ -21,7 +21,6 @@
-
diff --git a/akarpov/tools/shortener/urls.py b/akarpov/tools/shortener/urls.py
index 8257d88..a083d13 100644
--- a/akarpov/tools/shortener/urls.py
+++ b/akarpov/tools/shortener/urls.py
@@ -1,11 +1,16 @@
from django.urls import path
-from akarpov.tools.shortener.views import link_detail_view, short_link_create_view
+from akarpov.tools.shortener.views import (
+ link_detail_view,
+ link_public_detail_view,
+ short_link_create_view,
+)
app_name = "shortener"
urlpatterns = [
path("", short_link_create_view, name="create"),
path("", link_detail_view, name="view"),
+ path("p/", link_public_detail_view, name="public_view"),
path("revoked", short_link_create_view, name="revoked"),
]
diff --git a/akarpov/tools/shortener/views.py b/akarpov/tools/shortener/views.py
index 4e5ae24..0871f6b 100644
--- a/akarpov/tools/shortener/views.py
+++ b/akarpov/tools/shortener/views.py
@@ -1,5 +1,6 @@
from django.core.exceptions import PermissionDenied
from django.http import Http404, HttpResponseNotFound, HttpResponseRedirect
+from django.urls import reverse
from django.views.generic import CreateView, DetailView, ListView, TemplateView
from ipware import get_client_ip
@@ -52,6 +53,16 @@ def get_context_data(self, **kwargs):
link_detail_view = LinkDetailView.as_view()
+class LinkPublicDetailView(DetailView):
+ template_name = "tools/shortener/public_view.html"
+
+ def get_object(self, *args, **kwargs):
+ return get_link_from_slug(self.kwargs["slug"])
+
+
+link_public_detail_view = LinkPublicDetailView.as_view()
+
+
class LinkRevokedView(TemplateView):
template_name = "tools/shortener/revoked.html"
@@ -60,7 +71,14 @@ class LinkRevokedView(TemplateView):
def redirect_view(request, slug):
- # TODO: move to faster framework, like FastAPI
+ # TODO: move to faster framework, like FastAPI, save token to celery to get user_id
+ # TODO: add meta proxy
+ if "+" in slug:
+ return HttpResponseRedirect(
+ reverse(
+ "tools:shortener:public_view", kwargs={"slug": slug.replace("+", "")}
+ )
+ )
link, pk = get_cached_link_source(slug)
if not link:
return HttpResponseNotFound("such link doesn't exist or has been revoked")
diff --git a/akarpov/users/templatetags/__init__.py b/akarpov/users/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/akarpov/users/templatetags/users_extras.py b/akarpov/users/templatetags/users_extras.py
new file mode 100644
index 0000000..eb06cf4
--- /dev/null
+++ b/akarpov/users/templatetags/users_extras.py
@@ -0,0 +1,10 @@
+from django import template
+
+from akarpov.users.models import User
+
+register = template.Library()
+
+
+@register.inclusion_tag("users/badge.html", name="user_badge")
+def user_badge(user: User):
+ return {"user": user}
diff --git a/akarpov/utils/generators.py b/akarpov/utils/generators.py
index 0830631..3160b2d 100644
--- a/akarpov/utils/generators.py
+++ b/akarpov/utils/generators.py
@@ -6,7 +6,7 @@
from akarpov.utils.consts import URL_BASE
from akarpov.utils.nums import to_base
-URL_CHARACTERS = string.ascii_letters + string.digits + ";,:@&+-_.!~*'()#"
+URL_CHARACTERS = string.ascii_letters + string.digits + ";,:@&-_.!~*'()#"
class TokenGenerator(PasswordResetTokenGenerator):
@@ -21,16 +21,20 @@ def generate_charset(length: int) -> str:
return "".join(random.choice(string.ascii_letters) for _ in range(length))
+url_list = list(URL_CHARACTERS)
+url_len = len(url_list)
+
+
def get_str_uuid(pk: int) -> str:
- return to_base(pk, list(URL_CHARACTERS))
+ return to_base(pk, url_list)
def get_pk_from_uuid(slug: str) -> int:
res = 0
for i, el in enumerate(slug[::-1]):
if el not in URL_BASE:
- raise ValueError
- res += URL_BASE[el] * 78**i
+ return 0
+ res += URL_BASE[el] * url_len**i
return res