from django.db import models from django.contrib.auth.models import User class EBook(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='ebooks') meta_ct = models.TextField() # base64 AES-GCM ciphertext of {title, author, filename} meta_iv = models.CharField(max_length=32) # hex IV for metadata data_ct = models.TextField() # base64 AES-GCM ciphertext of raw EPUB bytes data_iv = models.CharField(max_length=32) # hex IV for EPUB data uploaded_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['uploaded_at'] def __str__(self): return f"EBook #{self.pk} (user={self.user_id})" class EBookProgress(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='ebook_progress') book = models.ForeignKey(EBook, on_delete=models.CASCADE, related_name='progress') scroll_fraction = models.FloatField(default=0.0) updated_at = models.DateTimeField(auto_now=True) class Meta: unique_together = ('user', 'book') def __str__(self): return f"Progress book={self.book_id} user={self.user_id} {self.scroll_fraction:.2f}" class EBookHighlights(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='ebook_highlights') book = models.ForeignKey(EBook, on_delete=models.CASCADE, related_name='highlights') ct = models.TextField() # base64 AES-GCM ciphertext of JSON array iv = models.CharField(max_length=32) # hex IV updated_at = models.DateTimeField(auto_now=True) class Meta: unique_together = ('user', 'book') def __str__(self): return f"Highlights book={self.book_id} user={self.user_id}" class EBookBookmarks(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='ebook_bookmarks') book = models.ForeignKey(EBook, on_delete=models.CASCADE, related_name='bookmarks') ct = models.TextField() iv = models.CharField(max_length=32) updated_at = models.DateTimeField(auto_now=True) class Meta: unique_together = ('user', 'book') def __str__(self): return f"Bookmarks book={self.book_id} user={self.user_id}"