diff --git a/akarpov/blog/signals.py b/akarpov/blog/signals.py index dbbd888..655b668 100644 --- a/akarpov/blog/signals.py +++ b/akarpov/blog/signals.py @@ -42,7 +42,7 @@ def post_rating(sender, instance: PostRating, **kwargs): @receiver(pre_save, sender=Post) def post_update(sender, instance: Post, **kwargs): if instance.id: - if "update_fields" in kwargs: + if "update_fields" in kwargs and kwargs["update_fields"]: for field in kwargs["update_fields"]: clear_model_cache(instance, field) else: diff --git a/akarpov/templates/blog/post.html b/akarpov/templates/blog/post.html index b51cb1b..9a12dbe 100644 --- a/akarpov/templates/blog/post.html +++ b/akarpov/templates/blog/post.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load users_extras %} {% load humanize %} {% load static %} @@ -14,9 +15,7 @@
- By: - {% if post.creator.image_cropped %} {% endif %} - {{ post.creator.username }} + By: {% user_badge post.creator %}
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 %} +
+

Link to: {{ link.full_source }}

+

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