Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
df2b135
add cryptography e PyJWT
samuelveigarangel Sep 25, 2025
02f061e
Remove field size de BaseLogo
samuelveigarangel Sep 25, 2025
22f9159
Add purpose em Collection
samuelveigarangel Sep 25, 2025
cf7b1a1
Adiciona url e logo_url
samuelveigarangel Sep 25, 2025
1d730b2
Remove LOGO_SIZE
samuelveigarangel Sep 25, 2025
a57d962
Add LOGO_PURPOSE
samuelveigarangel Sep 25, 2025
16d4349
Var de ambiente local
samuelveigarangel Sep 25, 2025
03e82f7
Adiciona variaveis de ambiente relacionado a JWT
samuelveigarangel Sep 25, 2025
45b4f04
Adiciona classe ListSerializer para agrupar logos por purpose e ficar…
samuelveigarangel Sep 25, 2025
247bfdd
Adiciona signal e codificação do token para mandar requisições post p…
samuelveigarangel Sep 25, 2025
4cf1d9b
fix header
samuelveigarangel Sep 25, 2025
9511cc5
migration
samuelveigarangel Sep 25, 2025
823d7fe
remove jwt_private_local.pem
samuelveigarangel Sep 25, 2025
36dd9fb
Adiciona variável para ativar update da coleção em opac_5
samuelveigarangel Sep 25, 2025
5bb31a7
remove event em build_collection_webhook
samuelveigarangel Sep 25, 2025
4e5e7b4
remove ip fixo
samuelveigarangel Sep 26, 2025
d7bae8f
Merge branch 'main' into issue-opac-339
samuelveigarangel Sep 26, 2025
37c06aa
remove value JWT_PRIVATE_KEY_PATH
samuelveigarangel Oct 6, 2025
f79d60d
Cria função para ler chave privada
samuelveigarangel Oct 6, 2025
cdffec6
muda metodo post para get em fetch_with_schema_guess
samuelveigarangel Oct 6, 2025
c76f5ed
Muda nome da funcao fetch_with_schema_guess para fetch_with_protocol_…
samuelveigarangel Oct 6, 2025
cdee2ec
Move logging.error para handler exception
samuelveigarangel Oct 6, 2025
a9a4b3e
remove span duplicado
samuelveigarangel Oct 6, 2025
f5e1bf7
Merge branch 'issue-opac-339' of github.com:samuelveigarangel/core in…
samuelveigarangel Oct 6, 2025
b234dfa
Merge branch 'main' into issue-opac-339
samuelveigarangel Oct 6, 2025
e6e6f50
remove self.size em BaseLogo.__str__
samuelveigarangel Oct 6, 2025
36bdc83
refactor get_logo_url
samuelveigarangel Oct 28, 2025
3e8c2a9
Refactor get_logo_url
samuelveigarangel Oct 28, 2025
24640cf
fix: corrige validações e chamadas duplicadas em webhooks de coleção
samuelveigarangel Oct 28, 2025
8857316
Merge branch 'main' into issue-opac-339
samuelveigarangel Oct 28, 2025
1e3e1e8
Merge branch 'issue-opac-339' of github.com:samuelveigarangel/core in…
samuelveigarangel Oct 28, 2025
22344ae
organiza e remove imports
samuelveigarangel Oct 28, 2025
cd1e4cd
migration merge
samuelveigarangel Oct 28, 2025
b5091f4
Transforma leitura da chave privada em variavel de ambiente
samuelveigarangel Oct 29, 2025
98ff528
Merge branch 'main' into issue-opac-339
samuelveigarangel Nov 15, 2025
e530db2
Add validação de tamanho para logos
samuelveigarangel Nov 24, 2025
627ab2c
Fix build_collection_webhook
samuelveigarangel Nov 24, 2025
d43f61d
Cria funções para obter url de Imagefield e wagtail.images
samuelveigarangel Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .envs/.local/.django
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ CELERY_FLOWER_PASSWORD=QgScyefPrYhHgO6onW61u0nazc5xdBuP4sM7jMRrBBFuA2RjsFhZLp7xb
FETCH_DATA_TIMEOUT=2

DJANGO_PROFILING_ENABLED=True
RUN_ASYNC=False
RUN_ASYNC=False

# ENDPOINT PARA ATUALIZAÇÃO DE COLEÇÕES
# ------------------------------------------------------------------------------
ENDPOINT_COLLECTION="/api/v1/update_collection/"
6 changes: 6 additions & 0 deletions .envs/.local/.jwt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
JWT_ISS="https://api.seu-django.com"
JWT_AUD="seu-flask-servico"
JWT_EXP_SECONDS=600
JWT_ALG="RS256"
# JWT_PRIVATE_KEY JA CORRESPONDENTE AO jwt_public OPAC_5 PARA TESTES.
JWT_PRIVATE_KEY_PATH=
56 changes: 33 additions & 23 deletions collection/api/v1/serializers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from rest_framework import serializers
from wagtail.models.sites import Site

from collection import models
from core.api.v1.serializers import LanguageSerializer
from core.utils.utils import get_url_file_from_wagtail_images
from organization.api.v1.serializers import OrganizationSerializer


class CollectionNameSerializer(serializers.ModelSerializer):
"""Serializer para nomes traduzidos da coleção"""
language = LanguageSerializer(many=False, read_only=True)
Expand All @@ -14,6 +18,32 @@ class Meta:
"language",
]

class CollectionLogoListSerializer(serializers.ListSerializer):
"""
Agrupa os logos por 'purpose' e consolida por idioma,
eliminando duplicatas por (purpose, lang_code2).
"""
def to_representation(self, data):
items = super().to_representation(data)
grouped = {}
seen = set()

for item in items:
purpose = item.get("purpose")
url = item.get("logo_url")
lang = item.get("language", {})
code2 = lang.get("code2")

if not purpose or not code2 or not url:
continue

key = (purpose, code2)
if key in seen:
continue
seen.add(key)

grouped.setdefault(purpose, {}).update({code2: url})
return grouped

class CollectionLogoSerializer(serializers.ModelSerializer):
"""Serializer para logos da coleção"""
Expand All @@ -22,38 +52,19 @@ class CollectionLogoSerializer(serializers.ModelSerializer):

class Meta:
model = models.CollectionLogo
list_serializer_class = CollectionLogoListSerializer
fields = [
"logo",
"logo_url",
"size",
"purpose",
"language",
]

def get_logo_url(self, obj):
"""Retorna a URL do logo renderizado no tamanho apropriado"""
if obj.logo:
# Ajusta o rendition baseado no tamanho
rendition_specs = {
'small': 'fill-100x100',
'medium': 'fill-200x200',
'large': 'fill-400x400',
'banner': 'width-1200',
'thumbnail': 'fill-150x150',
'header': 'height-80',
'footer': 'height-60',
}
spec = rendition_specs.get(obj.size, 'fill-200x200')
rendition = obj.logo.get_rendition(spec)

# Retorna URL completa se houver request no contexto
request = self.context.get('request')
if request:
return request.build_absolute_uri(rendition.url)
return rendition.url
return get_url_file_from_wagtail_images(obj.logo)
return None



class SupportingOrganizationSerializer(serializers.ModelSerializer):
"""Serializer para organizações de suporte"""
organization = OrganizationSerializer(read_only=True, many=False)
Expand Down Expand Up @@ -93,7 +104,6 @@ class Meta:

class CollectionSerializer(serializers.ModelSerializer):
"""Serializer principal para Collection com todos os relacionamentos"""
# Campos relacionados (read-only por padrão)
collection_names = CollectionNameSerializer(source='collection_name', many=True, read_only=True)
logos = CollectionLogoSerializer(many=True, read_only=True)
supporting_organizations = SupportingOrganizationSerializer(source='supporting_organization', many=True, read_only=True)
Expand Down
3 changes: 3 additions & 0 deletions collection/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
class CollectionConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "collection"

def ready(self):
from . import signals
9 changes: 9 additions & 0 deletions collection/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
("books", _("Books")),
("data", _("Data repository")),
]

LOGO_PURPOSE = [
("homepage", _("Homepage")),
("header", _("Header")),
("logo_drop_menu", _("Logo drop menu")),
("footer", _("Footer")),
("menu", _("Menu")),
]

PLATFORM_STATUS = [
("classic", _("Classic")),
("new", _("New")),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Generated by Django 5.2.3 on 2025-09-25 17:30

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
(
"collection",
"0006_alter_collection_options_alter_collection_acron2_and_more",
),
("core", "0007_alter_language_options_alter_license_options_and_more"),
]

operations = [
migrations.AlterModelOptions(
name="collectionexecutingorganization",
options={
"ordering": ["sort_order"],
"verbose_name": "Executing Organization",
"verbose_name_plural": "Executing Organizations",
},
),
migrations.AlterModelOptions(
name="collectionlogo",
options={
"ordering": ["sort_order", "language"],
"verbose_name": "Collection Logo",
"verbose_name_plural": "Collection Logos",
},
),
migrations.AlterModelOptions(
name="collectionsupportingorganization",
options={
"ordering": ["sort_order"],
"verbose_name": "Supporting Organization",
"verbose_name_plural": "Supporting Organizations",
},
),
migrations.AlterUniqueTogether(
name="collectionlogo",
unique_together={("collection", "language", "purpose")},
),
migrations.AddField(
model_name="collectionlogo",
name="purpose",
field=models.CharField(
blank=True,
choices=[
("homepage", "Homepage"),
("header", "Header"),
("logo_drop_menu", "Logo drop menu"),
("footer", "Footer"),
("menu", "Menu"),
],
help_text="Select the purpose of this logo",
max_length=20,
),
),
migrations.RemoveField(
model_name="collectionlogo",
name="size",
),
]
13 changes: 13 additions & 0 deletions collection/migrations/0008_merge_20251028_0412.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 5.2.3 on 2025-10-28 04:12

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("collection", "0007_alter_collectionexecutingorganization_options_and_more"),
("collection", "0007_collection_platform_status"),
]

operations = []
60 changes: 57 additions & 3 deletions collection/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from wagtail.admin.panels import FieldPanel, InlinePanel, ObjectList, TabbedInterface
from wagtail.models import Orderable
from wagtailautocomplete.edit_handlers import AutocompletePanel
from django.core.exceptions import ValidationError

from core.forms import CoreAdminModelForm
from core.models import (
Expand Down Expand Up @@ -321,6 +322,7 @@ def get_acronyms(cls, collection_acron_list):
return queryset.filter(acron3__in=collection_acron_list).values_list("acron3", flat=True)



class CollectionSocialNetwork(Orderable, SocialNetwork):
page = ParentalKey(
Collection,
Expand Down Expand Up @@ -352,6 +354,7 @@ class CollectionSupportingOrganization(Orderable, ClusterableModel, BaseHistory)
class Meta:
verbose_name = _("Supporting Organization")
verbose_name_plural = _("Supporting Organizations")
ordering = ['sort_order'] # Ordena os icons no opac_5

def __str__(self):
return str(self.organization)
Expand Down Expand Up @@ -379,6 +382,7 @@ class CollectionExecutingOrganization(Orderable, ClusterableModel, BaseHistory):
class Meta:
verbose_name = _("Executing Organization")
verbose_name_plural = _("Executing Organizations")
ordering = ['sort_order'] # Ordena os icons no opac_5

def __str__(self):
return str(self.organization)
Expand All @@ -396,14 +400,64 @@ class CollectionLogo(Orderable, BaseLogo):
related_name="logos",
verbose_name=_("Collection"),
)
purpose = models.CharField(
max_length=20,
choices=choices.LOGO_PURPOSE,
blank=True,
help_text=_("Select the purpose of this logo"),
)

panels = [
FieldPanel("logo"),
AutocompletePanel("language"),
FieldPanel("purpose"),
]
class Meta:
verbose_name = _("Collection Logo")
verbose_name_plural = _("Collection Logos")
ordering = ["sort_order", "language", "size"]
ordering = ['sort_order', 'language']
unique_together = [
("collection", "size", "language"),
('collection', 'language', 'purpose'),
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The unique constraint uses single quotes while other parts of the codebase use double quotes for consistency. Consider using double quotes.

Suggested change
('collection', 'language', 'purpose'),
("collection", "language", "purpose"),

Copilot uses AI. Check for mistakes.
]

def clean(self):
validation_logo_dimensions = {
'homepage': {
'max_width': 200,
'max_height': 100,
},
'header': {
'max_width': 200,
'max_height': 100,
},
'logo_drop_menu': {
'max_width': 200,
'max_height': 100,
},
'footer': {
'max_width': 200,
'max_height': 100,
},
'menu': {
'max_width': 200,
'max_height': 100,
},
}
if self.logo:
self.validate_image_dimensions(self.logo, validation_logo_dimensions[self.purpose])

@staticmethod
def validate_image_dimensions(image, validation_logo_dimensions):
width = image.width
height = image.height
max_width = validation_logo_dimensions['max_width']
max_height = validation_logo_dimensions['max_height']
if width < max_width or height > max_height:
raise ValidationError({
'logo': _(f'Image dimensions ({width}x{height}px) exceed the maximum allowed size. '
f' Width must be ≤ {max_width}px and height must be ≤ {max_height}px. '
)
})

def __str__(self):
return f"{self.collection} - {self.language} ({self.size})"
return f"{self.collection} - {self.language} ({self.purpose})"
21 changes: 21 additions & 0 deletions collection/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from .models import Collection
from .tasks import build_collection_webhook


@receiver(post_save, sender=Collection, dispatch_uid="collection.signals.post_save")
def collection_post_save(sender, instance, created, **kwargs):
def _on_commit():
if settings.ACTIVATE_UPDATE_COLLECTION_WEBHOOK:
event = "collection.created" if created else "collection.updated"
build_collection_webhook.apply_async(
kwargs=dict(
event=event,
collection_acron=instance.acron3,
# headers=headers,
)
)
transaction.on_commit(_on_commit)
Loading
Loading