added user badge tag, link info lookup

This commit is contained in:
Alexander Karpov 2023-08-05 17:50:34 +03:00
parent e2dd282bd9
commit 87d323ab2d
11 changed files with 69 additions and 14 deletions

View File

@ -42,7 +42,7 @@ def post_rating(sender, instance: PostRating, **kwargs):
@receiver(pre_save, sender=Post) @receiver(pre_save, sender=Post)
def post_update(sender, instance: Post, **kwargs): def post_update(sender, instance: Post, **kwargs):
if instance.id: if instance.id:
if "update_fields" in kwargs: if "update_fields" in kwargs and kwargs["update_fields"]:
for field in kwargs["update_fields"]: for field in kwargs["update_fields"]:
clear_model_cache(instance, field) clear_model_cache(instance, field)
else: else:

View File

@ -1,4 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load users_extras %}
{% load humanize %} {% load humanize %}
{% load static %} {% load static %}
@ -14,9 +15,7 @@
</h1> </h1>
<div class="row g-2 ms-1"> <div class="row g-2 ms-1">
<div class="col-md-auto"> <div class="col-md-auto">
By: <a href="{% url 'users:detail' post.creator.username %}"> By: {% user_badge post.creator %}
{% if post.creator.image_cropped %}<img class="rounded" width="20" src="{{ post.creator.image_cropped.url }}" alt=""> {% endif %}
{{ post.creator.username }}</a>
</div> </div>
<div class="col-md-auto fw-light"> <div class="col-md-auto fw-light">
Created {{ post.created | naturalday }}, Created {{ post.created | naturalday }},

View File

@ -1,4 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load users_extras %}
{% load static %} {% load static %}
{% block meta %} {% block meta %}
@ -35,9 +36,7 @@
</h1> </h1>
<div class="col-md-4 col-sm-6 col-xs-auto mb-5"> <div class="col-md-4 col-sm-6 col-xs-auto mb-5">
{% if not has_perm %} {% if not has_perm %}
<p>Uploaded by: <a href="{% url 'users:detail' file.user.username %}"> <p>Uploaded by: {% user_badge file.creator %}</p>
{% if file.user.image_cropped %}<img class="rounded" width="20" src="{{ file.user.image_cropped.url }}" alt=""> {% endif %}
{{ file.user.username }}</a></p>
{% endif %} {% endif %}
<p class="mt-2">Last updated: {{ file.modified|date:"d.m.Y" }} {{ file.modified|time:"H:i" }}</p> <p class="mt-2">Last updated: {{ file.modified|date:"d.m.Y" }} {{ file.modified|time:"H:i" }}</p>
<p>File size: {{ file.file_size | filesizeformat }}</p> <p>File size: {{ file.file_size | filesizeformat }}</p>

View File

@ -0,0 +1,18 @@
{% extends 'base.html' %}
{% load users_extras %}
{% load static %}
{% block content %}
<div class="m-2">
<h4>Link to: <a class="fs-4" href="{{ link.source }}">{{ link.full_source }}</a></h4>
<p>Issued by: {% user_badge link.creator %}</p>
<p>{{ request.get_host }}{% url 'short_url' slug=link.slug %} <button class="btn" data-clipboard-text="{{ request.get_host }}{% url 'short_url' slug=link.slug %}">
<i style="font-size: 0.8em" class="bi bi-clipboard ml-2"></i>
</button></p>
</div>
<script src="{% static 'js/clipboard.min.js' %}"></script>
<script>
new ClipboardJS('.btn');
</script>
{% endblock %}

View File

@ -0,0 +1,3 @@
<a href="{% url 'users:detail' user.username %}">
{% if user.image_cropped %}<img class="rounded" width="20" src="{{ user.image_cropped.url }}" alt=""> {% endif %}
{{ user.username }}</a>

View File

@ -21,7 +21,6 @@
</header> </header>
<!-- bit of a bio; who are you? -->
<div class="profile-bio"> <div class="profile-bio">
<p> <p>

View File

@ -1,11 +1,16 @@
from django.urls import path 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" app_name = "shortener"
urlpatterns = [ urlpatterns = [
path("", short_link_create_view, name="create"), path("", short_link_create_view, name="create"),
path("<str:slug>", link_detail_view, name="view"), path("<str:slug>", link_detail_view, name="view"),
path("p/<str:slug>", link_public_detail_view, name="public_view"),
path("revoked", short_link_create_view, name="revoked"), path("revoked", short_link_create_view, name="revoked"),
] ]

View File

@ -1,5 +1,6 @@
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http import Http404, HttpResponseNotFound, HttpResponseRedirect from django.http import Http404, HttpResponseNotFound, HttpResponseRedirect
from django.urls import reverse
from django.views.generic import CreateView, DetailView, ListView, TemplateView from django.views.generic import CreateView, DetailView, ListView, TemplateView
from ipware import get_client_ip from ipware import get_client_ip
@ -52,6 +53,16 @@ def get_context_data(self, **kwargs):
link_detail_view = LinkDetailView.as_view() 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): class LinkRevokedView(TemplateView):
template_name = "tools/shortener/revoked.html" template_name = "tools/shortener/revoked.html"
@ -60,7 +71,14 @@ class LinkRevokedView(TemplateView):
def redirect_view(request, slug): 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) link, pk = get_cached_link_source(slug)
if not link: if not link:
return HttpResponseNotFound("such link doesn't exist or has been revoked") return HttpResponseNotFound("such link doesn't exist or has been revoked")

View File

View File

@ -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}

View File

@ -6,7 +6,7 @@
from akarpov.utils.consts import URL_BASE from akarpov.utils.consts import URL_BASE
from akarpov.utils.nums import to_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): class TokenGenerator(PasswordResetTokenGenerator):
@ -21,16 +21,20 @@ def generate_charset(length: int) -> str:
return "".join(random.choice(string.ascii_letters) for _ in range(length)) 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: 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: def get_pk_from_uuid(slug: str) -> int:
res = 0 res = 0
for i, el in enumerate(slug[::-1]): for i, el in enumerate(slug[::-1]):
if el not in URL_BASE: if el not in URL_BASE:
raise ValueError return 0
res += URL_BASE[el] * 78**i res += URL_BASE[el] * url_len**i
return res return res