Django SAAS Framework
Project description
apt install libpango-1.0-0 libpangoft2-1.0-0 libffi-dev libxml2 libxslt1.1 pip install weasyprint
ViewSet Rule
All concrete ViewSets MUST define a base queryset.
The BaseAPIView only applies multi-tenant filters and permissions, it does not define the base queryset.
Example:
class PessoaViewSet(BaseAPIView):
queryset = Pessoa.objects.select_related('user', 'endereco')
Translate (Project Rule)
All text returned by the API MUST be translated using the Translate class.
Frontend applications must not translate text.
Example:
python
from django_resaas.classes.Translate import Translate
return Response({
'alert_error': Translate.tdc(request, 'Permission denied')
}, status=403)
CoreFileMiddleware
This middleware protects access to media files.
Only requests with a valid token are allowed.
Behavior
- Intercepts requests to MEDIA_URL
- Validates token from querystring
- Returns translated error messages
Example
/media/document.pdf?token=XYZ
Unauthorized response
{
"alert_error": "Nao autorizado"
}
CoreMiddleware
Este middleware controla o acesso às rotas da API.
O acesso é permitido apenas para:
- Frontends autorizados (FEK + FEP)
- Endereços IP autorizados
Comportamento
- Ignora URLs públicas definidas em
settings.AUTH_URL - Valida headers FEK e FEP
- Caso inválido, retorna erro traduzido via
Translate
Headers esperados
FEK: Frontend Key
FEP: Frontend Password
Resposta não autorizada
{
"code": 10001,
"alert_error": "Não autorizado"
}
File Token Configuration
A biblioteca suporta dois tipos de token para acesso a ficheiros:
- 🔐 Token permanente (não expira)
- ⏱️ Token temporário (com TTL)
Settings
DJANGO_REST_AUTH = {
'FILE_TOKEN': {
'ENABLE_TEMPORARY': True,
'TEMP_TTL': 300,
'ENABLE_PERMANENT': True,
},
'REQUIRE_FE_CREDENTIALS': True,
'TENANT_HEADERS': {
'ENTIDADE': 'E',
'SUCURSAL': 'S',
'GRUPO': 'G',
'TIPO_ENTIDADE': 'ET',
'LANG': 'L',
}
}
Email Templates
A biblioteca permite substituir os templates de email via settings.
Exemplo:
DJANGO_REST_AUTH = {
'EMAIL_TEMPLATES': {
'REGISTER_CONFIRM': 'emails/confirmacao.html',
'PASSWORD_RESET': 'emails/reset.html',
'GENERIC_RESET': 'emails/generico.html',
}
}
E no settings.py:
TEMPLATES[0]['DIRS'] += [BASE_DIR / 'templates']
No projeto final:
project/
└── templates/
└── emails/
├── meu_confirmacao.html
├── meu_reset.html
└── meu_generico.html
📘 PADRÃO DE PERISSÕES – FRAMEWORK MULTI-TENANT
Este projeto implementa um sistema de permissões centralizado, multi-tenant e orientado a APIs, baseado em:
Django Permissions (auth_permission)
Groups (auth_group)
Contexto dinâmico via headers
Validação automática no BaseAPIView
Uma única query por request (alta performance)
🧱 Conceitos Fundamentais
🔹 Tipo de Entidade
Classificação da organização (ex: Clínica, Escola, Empresa).
🔹 Entidade
Organização principal (ex: Clínica ABC).
🔹 Sucursal
Unidade da entidade (ex: Filial Luanda).
🔹 Grupo
Papel do utilizador numa sucursal (ex: Admin, RH, Médico).
🔹 Utilizador
Pode pertencer a:
múltiplas Entidades
múltiplas Sucursais
múltiplos Grupos
🧭 Contexto Obrigatório (Headers)
Todo request autenticado DEVE enviar os headers abaixo:
Header Descrição
ET ID do Tipo de Entidade
E ID da Entidade
S ID da Sucursal
G ID do Grupo
L Idioma
📌 Sem estes headers, o acesso é negado.
🔐 Modelo de Permissões (Padrão)
O sistema segue o padrão Django com extensão para list.
CRUD padrão
Action (DRF) Permissão
list list_<model>
retrieve view_<model>
create add_<model>
update change_<model>
partial_update change_<model>
destroy delete_<model>
📌 <model> é o nome do model em minúsculas.
Exemplo (Colaborador)
list_colaborador
view_colaborador
add_colaborador
change_colaborador
delete_colaborador
⚙️ Permissões Automáticas
Após cada migrate, o sistema cria automaticamente:
list_<model>
Apenas para os apps definidos em:
settings.MY_APPS
✔️ Não há risco de duplicação
✔️ Usa get_or_create()
✔️ (codename, content_type) é único no Django
✨ Permissões Customizadas no Model
Models podem definir permissões adicionais:
class Colaborador(models.Model):
class Meta:
permissions = (
('icon', 'Menu Icon'),
('list_contauser', 'Can list Conta User'),
)
Estas permissões:
são criadas pelo Django
podem ser atribuídas a grupos
podem ser usadas nas views
🧠 Verificação de Permissões
Toda a verificação acontece via:
isPermited(request=request, role=[codename])
Internamente, o sistema valida numa única query:
user ∈ grupo
grupo ∈ sucursal
sucursal ∈ entidade
entidade ∈ tipo_entidade
grupo possui a permissão solicitada
Se qualquer condição falhar → acesso negado.
🧩 BaseAPIView (Automático)
Todas as APIs devem herdar de:
ds.views.BaseAPIView
O que o BaseAPIView faz
✔️ valida permissões automaticamente
✔️ injeta contexto (entidade_id, sucursal_id, etc.)
✔️ filtra queryset por tenant
✔️ implementa soft delete
✔️ não usa decorators
🔁 Mapeamento de Permissões por Action
🔹 Mapa padrão (interno)
permission_action_map = {
'list': 'list',
'retrieve': 'view',
'create': 'add',
'update': 'change',
'partial_update': 'change',
'destroy': 'delete',
}
✍️ method_permission (Override por ViewSet)
Cada ViewSet pode estender ou sobrescrever permissões usando:
method_permission = {}
Prioridade
method_permission > permission_action_map
📌 Exemplos Práticos
✔️ ViewSet simples (CRUD padrão)
class ColaboradorViewSet(BaseAPIView):
queryset = Colaborador.objects.all()
serializer_class = ColaboradorSerializer
Permissões usadas automaticamente:
list_colaborador
add_colaborador
change_colaborador
delete_colaborador
✔️ Action custom (bulk_create)
class ColaboradorViewSet(BaseAPIView):
queryset = Colaborador.objects.all()
serializer_class = ColaboradorSerializer
method_permission = {
'bulk_create': 'add',
}
@action(detail=False, methods=['post'])
def bulk_create(self, request):
...
Permissão exigida:
add_colaborador
✔️ Sobrescrever permissão de action padrão
class ColaboradorViewSet(BaseAPIView):
method_permission = {
'list': 'view',
}
Agora o list exige:
view_colaborador
🚫 O que NÃO fazer
❌ Criar views sem herdar de BaseAPIView
❌ Ignorar headers de contexto
❌ Usar decorators de permissão em views
❌ Implementar lógica de tenant fora do core
⚡ Performance
✔️ 1 query por request para permissões
✔️ Usa exists() + JOIN
✔️ Sem carregar objetos em memória
✔️ Escala bem com muitos utilizadores
🏁 Conclusão
Este padrão fornece:
🔒 Segurança forte
⚡ Alta performance
🔁 Reutilização total
🧱 Arquitetura de framework
📦 Preparado para múltiplos domínios (RH, Clínica, Escola, etc.)
Se quiseres, posso:
gerar isto em Markdown final
criar um diagrama de fluxo
documentar BaseRHViewSet
criar exemplos reais do RH
É só dizer 🚀
# MetanoStack Architecture Rules
## Core Principles
1. Every model MUST inherit from BaseModel
2. Every serializer MUST inherit from BaseSerializer
3. Every viewset MUST inherit from BaseAPIView
4. No relative imports allowed
5. One class per file
6. User model must be django_resaas User
7. Multi-tenant enforced via middleware
8. No business logic inside ViewSets
9. Serializers define API contract (OpenAPI source of truth)
10. RH must support skills (Especialidades)
## Forbidden Patterns
- class X(models.Model)
- class X(ModelSerializer)
- class X(ModelViewSet)
- from . import something
- Big models.py files
## Structure Standard
module/
├─ models/
├─ serializers/
├─ views/
├─ services/
└─ urls.py
## Enterprise Compliance
- Audit fields required
- UUID primary keys
- Soft delete via estado
- Multi-tenant aware
INSTALLED_APPS = [
'corsheaders',
...
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
CORS_ALLOWED_ORIGINS = [
"http://84.247.162.222:9000",
]
CORS_ALLOW_CREDENTIALS = True
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = list(default_headers) + [
"fek",
"fep",
]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_resaas-0.0.19.tar.gz.
File metadata
- Download URL: django_resaas-0.0.19.tar.gz
- Upload date:
- Size: 85.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dd4d39726bd448e3e2d58e70b55c66e772f3a185791ffca296f77c3a4788a35
|
|
| MD5 |
9fba857ce4fe9446fd2aba8b0493447a
|
|
| BLAKE2b-256 |
81c7ba01416fec69e4cd4b27a301181efbcf27c20714e7870afcea68920b722a
|
Provenance
The following attestation bundles were made for django_resaas-0.0.19.tar.gz:
Publisher:
publish_pypi.yml on metanochava/django_resaas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_resaas-0.0.19.tar.gz -
Subject digest:
4dd4d39726bd448e3e2d58e70b55c66e772f3a185791ffca296f77c3a4788a35 - Sigstore transparency entry: 1066678248
- Sigstore integration time:
-
Permalink:
metanochava/django_resaas@310edd1dbaedc04e7f417429f8a88ee097ff17a0 -
Branch / Tag:
refs/tags/0.0.19 - Owner: https://github.com/metanochava
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_pypi.yml@310edd1dbaedc04e7f417429f8a88ee097ff17a0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_resaas-0.0.19-py3-none-any.whl.
File metadata
- Download URL: django_resaas-0.0.19-py3-none-any.whl
- Upload date:
- Size: 132.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0353f375f6b5322eaab369cdec73904be0e108ae5a082f304ba5814ee709c689
|
|
| MD5 |
3f5ffa682b759f1d20ee3ae00f295b73
|
|
| BLAKE2b-256 |
0307d9b3f732ba033653f4b2916c11e21d2fb29fc436e43616cf1d46763a8c0c
|
Provenance
The following attestation bundles were made for django_resaas-0.0.19-py3-none-any.whl:
Publisher:
publish_pypi.yml on metanochava/django_resaas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_resaas-0.0.19-py3-none-any.whl -
Subject digest:
0353f375f6b5322eaab369cdec73904be0e108ae5a082f304ba5814ee709c689 - Sigstore transparency entry: 1066678252
- Sigstore integration time:
-
Permalink:
metanochava/django_resaas@310edd1dbaedc04e7f417429f8a88ee097ff17a0 -
Branch / Tag:
refs/tags/0.0.19 - Owner: https://github.com/metanochava
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_pypi.yml@310edd1dbaedc04e7f417429f8a88ee097ff17a0 -
Trigger Event:
push
-
Statement type: