Leitura Pública de Documentos
Como exibir documentos em outros sites para leitura sem aceite formal
Guia: Leitura Pública de Documentos (Sem Aceite)
📖 Visão Geral
Este guia explica como exibir documentos (termos de uso, políticas, etc.) em outros sites para leitura, sem a necessidade de aceite formal.
Diferença importante: - Leitura: Apenas visualizar o conteúdo (este guia) - Aceite: Registrar aceite formal com verificação de identidade
---
🎯 Quando Usar
Use a leitura pública quando você quer: - Exibir termos de uso em uma página de "Sobre" de outro site - Mostrar política de privacidade para leitura - Incorporar documentos legais em sites externos - Permitir consulta sem obrigatoriedade de aceite
---
🚀 3 Formas de Implementação
Opção 1: Página HTML Completa (Melhor para links diretos)
#### URLs Disponíveis:
`
https://sua-plataforma.com/documents/read/<slug>/
`
Exemplo:
`
https://legal-docs.com/documents/read/termos-de-uso/
`
#### Como Usar:
1. Configure o public_acceptance_slug no documento
2. Ative public_acceptance_enabled = True
3. Compartilhe o link
#### Recursos: - ✅ Layout completo com header e footer - ✅ Botão para aceitar (se necessário) - ✅ Informações de versão e vigência - ✅ Botão de impressão - ✅ Responsivo
---
Opção 2: Iframe Embarcado (Melhor para incorporação)
#### URLs Disponíveis:
`
https://sua-plataforma.com/documents/read/embedded/<UUID>/
`
Exemplo:
`html
<!-- No seu site externo -->
<div class="terms-container">
<iframe
id="terms-iframe"
src="https://legal-docs.com/documents/read/embedded/550e8400-e29b-41d4-a716-446655440000/"
width="100%"
height="600"
frameborder="0"
title="Termos de Uso"
style="border: 1px solid #e5e7eb; border-radius: 8px;"
></iframe>
</div>
<script>
// Ajusta altura automaticamente
window.addEventListener('message', function(event) {
if (event.data.type === 'resize_iframe') {
document.getElementById('terms-iframe').style.height =
event.data.height + 'px';
}
});
</script>
`
#### Configuração (Opcional):
Se quiser controlar quais domínios podem incorporar:
`python
from apps.agreements.models import Document, EmbeddedAcceptanceConfig
document = Document.objects.get(public_acceptance_slug="termos-de-uso")
Cria ou atualiza configuração
config, _ = EmbeddedAcceptanceConfig.objects.get_or_create( document=document, defaults={ 'enabled': True, 'allowed_domains': [ 'seusite.com', 'www.seusite.com', '*.seusite.com', # Permite subdomínios ], 'custom_css': ''' .title { color: #2563eb; } .content { font-size: 16px; } ''', 'hide_powered_by': True, } )`#### Recursos: - ✅ Layout minimalista (sem header/footer) - ✅ Customizável via CSS - ✅ Validação de domínios permitidos - ✅ Ajuste automático de altura - ✅ Sem botões de aceite
---
Opção 3: API REST (JSON) (Melhor para customização total)
#### URLs Disponíveis:
`
GET https://sua-plataforma.com/api/documents/<slug>/
`
Exemplo de Request:
`bash
curl https://legal-docs.com/api/documents/termos-de-uso/
`
Resposta:
`json
{
"document_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Termos de Uso",
"slug": "termos-de-uso",
"description": "Termos e condições de uso da plataforma",
"version": {
"version_number": "2.0",
"title": "Termos de Uso - Versão 2.0",
"content_html": "<h1>Termos de Uso</h1><p>...</p>",
"content_plain": "Termos de Uso\n\n...",
"effective_date": "2024-01-01",
"published_at": "2024-01-01T10:00:00Z"
},
"urls": {
"read": "https://legal-docs.com/documents/read/termos-de-uso/",
"accept": "https://legal-docs.com/acceptance/termos-de-uso/",
"embedded": "https://legal-docs.com/documents/read/embedded/550e8400-e29b-41d4-a716-446655440000/"
},
"meta": {
"retrieved_at": "2024-01-15T14:30:00Z",
"cache_ttl": 3600
}
}
`
#### Implementação no Seu Site:
HTML:
`html
<div id="terms-content">
<div class="loading">Carregando termos de uso...</div>
</div>
`
JavaScript:
`javascript
async function loadTerms() {
try {
const response = await fetch(
'https://legal-docs.com/api/documents/termos-de-uso/'
);
const data = await response.json();
// Renderiza o conteúdo
document.getElementById('terms-content').innerHTML = `
<div class="terms-header">
<h1>${data.version.title}</h1>
<p class="meta">
Versão ${data.version.version_number} •
Vigência: ${new Date(data.version.effective_date).toLocaleDateString('pt-BR')}
</p>
</div>
<div class="terms-body">
${data.version.content_html}
</div>
<div class="terms-footer">
<a href="${data.urls.accept}" class="btn-accept">
Aceitar Termos de Uso
</a>
</div>
`;
} catch (error) {
console.error('Erro ao carregar termos:', error);
document.getElementById('terms-content').innerHTML =
'<p class="error">Erro ao carregar termos de uso.</p>';
}
}
// Carrega quando a página carregar
loadTerms();
`
React/Next.js:
`jsx
'use client';
import { useEffect, useState } from 'react';
export default function TermsOfService() { const [terms, setTerms] = useState(null); const [loading, setLoading] = useState(true);
useEffect(() => { fetch('https://legal-docs.com/api/documents/termos-de-uso/') .then(res => res.json()) .then(data => { setTerms(data); setLoading(false); }) .catch(err => { console.error(err); setLoading(false); }); }, []);
if (loading) return <div>Carregando...</div>; if (!terms) return <div>Erro ao carregar termos</div>;
return (
<div className="terms-container">
<h1>{terms.version.title}</h1>
<div className="meta">
Versão {terms.version.version_number} •
Vigência: {new Date(terms.version.effective_date).toLocaleDateString('pt-BR')}
</div>
<div
className="content"
dangerouslySetInnerHTML={{ __html: terms.version.content_html }}
/>
<a href={terms.urls.accept} className="btn-accept">
Aceitar Termos
</a>
</div>
);
}
`
#### Recursos:
- ✅ Customização total do design
- ✅ CORS habilitado (Access-Control-Allow-Origin: *)
- ✅ Cache HTTP (1 hora)
- ✅ HTML e texto puro disponíveis
- ✅ Links para aceite e embedded inclusos
---
📊 Comparação das Opções
| Aspecto | Página HTML | Iframe | API REST | |---------|------------|--------|----------| | Implementação | ⭐⭐⭐ Muito fácil | ⭐⭐ Fácil | ⭐ Requer código | | Customização | ❌ Limitada | ⚠️ CSS apenas | ✅ Total | | Manutenção | ✅ Zero | ✅ Zero | ⚠️ Você controla | | Atualização | ✅ Automática | ✅ Automática | ⚠️ Depende do cache | | Performance | ⭐⭐ Boa | ⭐⭐ Boa | ⭐⭐⭐ Excelente | | SEO | ✅ Indexável | ❌ Não indexa | ✅ Você controla | | Mobile | ✅ Responsivo | ✅ Responsivo | ✅ Você controla |
---
🔧 Configuração Passo a Passo
1. No Django Admin:
`python
Via shell ou admin
from apps.agreements.models import Document1. Configure o documento
document = Document.objects.get(name="Termos de Uso") document.public_acceptance_slug = "termos-de-uso" document.public_acceptance_enabled = True document.is_active = True document.save()2. Certifique-se de ter uma versão ativa
version = document.get_active_version() print(f"Versão ativa: {version.version}")3. Obtenha as URLs
print(f"URL Leitura: /documents/read/{document.public_acceptance_slug}/") print(f"URL Embedded: /documents/read/embedded/{document.document_key}/") print(f"URL API: /api/documents/{document.public_acceptance_slug}/")`2. (Opcional) Configure Embedding com Domínios Restritos:
`python
from apps.agreements.models import EmbeddedAcceptanceConfig
config = EmbeddedAcceptanceConfig.objects.create(
document=document,
enabled=True,
allowed_domains=[
'seusite.com',
'www.seusite.com',
'staging.seusite.com',
],
custom_css='''
.title {
color: #1a56db;
font-family: 'Inter', sans-serif;
}
.content {
font-size: 15px;
line-height: 1.8;
}
''',
hide_powered_by=True,
)
`
3. Teste as URLs:
Página HTML:
`
http://localhost:8000/documents/read/termos-de-uso/
`
Iframe:
`
http://localhost:8000/documents/read/embedded/550e8400-e29b-41d4-a716-446655440000/
`
API:
`bash
curl http://localhost:8000/api/documents/termos-de-uso/
`
---
🎨 Exemplos de Customização CSS
Estilo Moderno (para Iframe):
`css
.title {
font-family: 'Inter', -apple-system, sans-serif;
font-size: 28px;
font-weight: 700;
color: #111827;
letter-spacing: -0.02em;
}
.content { font-size: 16px; line-height: 1.75; color: #374151; }
.content h2 { color: #1f2937; font-size: 20px; font-weight: 600; margin-top: 2em; border-bottom: 2px solid #e5e7eb; padding-bottom: 0.5em; }
.content ul { list-style: none; padding-left: 0; }
.content li::before {
content: "✓ ";
color: #10b981;
font-weight: bold;
margin-right: 8px;
}
`
Estilo Minimalista:
`css
* {
font-family: 'Georgia', serif;
}
.title { font-size: 32px; font-weight: 400; color: #000; text-align: center; }
.content {
max-width: 650px;
margin: 0 auto;
font-size: 18px;
line-height: 1.6;
color: #333;
}
`
---
🔒 Segurança
CORS (API):
- A API retornaAccess-Control-Allow-Origin: *
- Permite acesso de qualquer domínio
- Sem autenticação necessária (conteúdo público)Iframe:
- Headers CSP configurados automaticamente - Validação de domínios permitidos (se configurado) - Sem cookies ou sessões necessários---
💡 Casos de Uso
1. Site Institucional:
`html
<!-- Em https://meusite.com/termos -->
<iframe src="https://legal-docs.com/documents/read/embedded/UUID/"
width="100%" height="800"></iframe>
`2. SPA/React App:
`jsx
import TermsAPI from './components/TermsAPI';function TermsPage() {
return <TermsAPI slug="termos-de-uso" />;
}
`
3. Link Direto:
`html
<a href="https://legal-docs.com/documents/read/termos-de-uso/"
target="_blank">
Leia nossos Termos de Uso
</a>
`---
🆚 Comparação: Leitura vs Aceite
| Feature | Leitura | Aceite | |---------|---------|--------| | Formulário | ❌ Não | ✅ Sim | | Verificação Email | ❌ Não | ✅ Sim (Magic Link/OTP) | | Registro em BD | ❌ Não | ✅ Sim | | Auditoria | ❌ Não | ✅ Completa | | Certificado | ❌ Não | ✅ Sim | | Uso | Consulta | Aceite Legal |
---
📱 Responsividade
Todas as 3 opções são mobile-friendly: - Página HTML: Responsiva com Tailwind CSS - Iframe: Ajusta altura automaticamente - API: Você controla o design
---
⚡ Performance
Cache:
- API: Cache HTTP de 1 hora (Cache-Control: public, max-age=3600)
- HTML/Iframe: Cache controlado pelo navegadorCDN (recomendado):
`nginx
Nginx
location ~ ^/documents/read/ { proxy_cache my_cache; proxy_cache_valid 200 1h; add_header X-Cache-Status $upstream_cache_status; }`---
🐛 Troubleshooting
Iframe não carrega:
1. Verifiqueallowed_domains na configuração
2. Teste com allowed_domains = [] (modo permissivo)
3. Verifique console do navegador (CORS/CSP)API retorna 404:
1. Verifiquepublic_acceptance_enabled = True
2. Verifique is_active = True
3. Verifique se existe versão ativaConteúdo não atualiza:
1. Limpe cache do navegador 2. Verifique se a versão está publicada 3. Force refresh: Ctrl+Shift+R---
🎓 Próximos Passos
- [ ] Configure seus documentos - [ ] Escolha o método (HTML, Iframe ou API) - [ ] Implemente no seu site - [ ] (Opcional) Configure domínios permitidos - [ ] (Opcional) Customize o CSS - [ ] Teste em produção
---
💬 Dúvidas?
Se precisar de aceite formal (com verificação de identidade), use:
- /acceptance/<slug>/ - Formulário de aceite público
- /embedded/<uuid>/ - Aceite via iframe (com formulário)
Este guia é para leitura apenas, sem aceite.