from datetime import datetime, timedelta from hashlib import sha256 import shortuuid from django.core.validators import MaxLengthValidator from django.db import models from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext_lazy as _ from webtools import settings class PasteQuerySet(models.QuerySet): def by_secret(self, secret): auth = sha256(secret.encode("UTF-8")).hexdigest() return self.filter(auth=auth) class Paste(models.Model): """Paste object.""" objects = PasteQuerySet.as_manager() filename = models.CharField(max_length=255, default="") slug = models.SlugField(unique=True, editable=False) content = models.TextField( validators=[MaxLengthValidator(settings.PASTE["max_characters"])] ) size = models.IntegerField(default=0, editable=False) paste_time = models.DateTimeField(auto_now_add=True) access_time = models.DateTimeField(auto_now=True) viewcount = models.IntegerField(default=0, editable=False) # auth stores a sha256 (hexdigest) of the Authentication header. auth = models.CharField(max_length=64, default="") def set_secret(self, secret=None): if not secret: return self.auth = sha256(secret.encode("UTF-8")).hexdigest() def compute_size(self): """Computes size.""" self.size = len(self.content) def get_absolute_url(self): return reverse("short_paste", kwargs={"slug": self.slug}) def incr_viewcount(self): """Increment view counter.""" self.viewcount = self.viewcount + 1 self.save() def __str__(self): excerpt = repr(self.content.split("\n")[0][:100]) + ( "..." if len(self.content) > 100 else "" ) return f"{self.slug} - {excerpt}" @classmethod def choose_prefix(cls, filenames): """Find a prefix free for all the given filenames. Such as /filename is unused. """ while True: uuid = shortuuid.uuid() for i in range(4, len(uuid) + 1): potential_uuid = uuid[:i] for filename in filenames: slug = f"{potential_uuid}/{filename}" if not any(cls.objects.filter(slug=slug) for filename in filenames): return potential_uuid def choose_slug(self): while True: uuid = shortuuid.uuid() for i in range(4, len(uuid)): potential_uuid = uuid[:i] if not type(self).objects.filter(slug=potential_uuid): self.slug = potential_uuid return