Skip to content

Commit fb2c447

Browse files
oxbarOxbar - AKA Micael
andauthored
Origem do CORS explícita e configurável, com aviso para '*' (#119) (#125)
* Origem do CORS explícita e configurável, com aviso para '*' (#119) O CORS era habilitado nos templates do scaffold com cors() sem opções, liberando qualquer origem ('*') de forma invisível: nada no configuracao.delprops indicava esse comportamento nem alertava que é adequado apenas para desenvolvimento. Mudanças: - Nova propriedade liquido.roteador.corsOrigem (padrão '*'), aceitando uma origem única ou várias separadas por vírgula. Encanada por ConfiguracaoRoteador -> RoteadorInterface -> Roteador, com validação natural do centro de configurações (propriedade declarada existe na classe) e entrada no esquema delprops com explicação em português. - Roteador.resolverOpcoesCors() traduz o valor para as opções do middleware cors: '*' mantém o comportamento liberado; qualquer outro valor vira lista de origens permitidas ({ origin: [...] }), com espaços tolerados e itens vazios ignorados. Valor vazio volta ao padrão. - Aviso explícito na inicialização quando o CORS está habilitado com origem '*', orientando a restrição em produção via liquido.roteador.corsOrigem em configuracao.delprops. - Templates do scaffold (Delégua e Pituguês, MVC e API REST) e o configuracao.delprops do próprio repositório agora declaram corsOrigem = '*' explicitamente, com comentário avisando que o valor é adequado apenas para desenvolvimento. README documenta a nova propriedade nos exemplos de configuração. Sobre a segunda parte da issue (.gitignore): a geração já existe na principal e no pacote 1.4.0 publicado (gerarRepositorioGit escreve um .gitignore completo quando o Git é aceito) — o achado B4 do relatório estava incorreto nesse ponto, pois o caminho 'sim' da pergunta de Git não havia sido validado. Nenhuma mudança necessária. Validação de ponta a ponta com o código compilado sobreposto ao pacote liquido@1.4.0: - corsOrigem = 'https://meusite.com.br': header Access-Control-Allow-Origin ecoa apenas a origem permitida; origem não listada não recebe o header; sem aviso no boot; - corsOrigem = '*': header Access-Control-Allow-Origin: * e aviso em português na inicialização. Testes: novo testes/infraestrutura/cors-origem.test.ts com 13 casos (parsing de origens, aviso condicional na inicialização, repasse da configuração e presença da declaração explícita nos 4 templates); mocks de centro-configuracoes atualizados para o novo método. Suíte unitária completa: 240 testes passando. Fixes #119 * Renomeia propriedade corsOrigem para origensCors Atendendo à revisão do PR: a propriedade passa a se chamar liquido.roteador.origensCors, nome mais fiel ao conteúdo (aceita uma ou mais origens separadas por vírgula). Renomeados em conjunto, por consistência: o campo origensCors em ConfiguracaoRoteador e em Roteador, o método configurarOrigensCors na interface e na implementação, a entrada do esquema delprops, os quatro templates do scaffold, o configuracao.delprops do repositório, o README, a mensagem de aviso na inicialização e os testes. Sem mudança de comportamento; suíte completa com 240 testes passando. --------- Co-authored-by: Oxbar - AKA Micael <micaelparadox@gmail.com>
1 parent 6cbbd3f commit fb2c447

12 files changed

Lines changed: 217 additions & 1 deletion

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ Um exemplo de `configuracao.delprops` para um projeto em Delégua:
215215
liquido.arquetipo = 'rest'
216216
liquido.linguagem = 'delegua'
217217
liquido.roteador.cors = verdadeiro
218+
liquido.roteador.origensCors = '*'
218219
liquido.roteador.bodyParser = verdadeiro
219220
liquido.roteador.morgan = verdadeiro
220221
liquido.roteador.cookieParser = verdadeiro
@@ -229,6 +230,7 @@ Para usar Pituguês, basta alterar a propriedade `linguagem`:
229230
liquido.arquetipo = 'rest'
230231
liquido.linguagem = 'pituguês'
231232
liquido.roteador.cors = verdadeiro
233+
liquido.roteador.origensCors = '*'
232234
liquido.roteador.bodyParser = verdadeiro
233235
liquido.roteador.morgan = verdadeiro
234236
liquido.roteador.cookieParser = verdadeiro
@@ -237,6 +239,8 @@ liquido.roteador.json = verdadeiro
237239
liquido.roteador.helmet = verdadeiro
238240
```
239241

242+
A propriedade `liquido.roteador.origensCors` define a(s) origem(ns) permitida(s) para CORS, separadas por vírgula (por exemplo, `'https://meusite.com.br, https://admin.meusite.com.br'`). O valor `'*'` libera qualquer origem e é adequado apenas para desenvolvimento — em produção, restrinja para o(s) domínio(s) da aplicação. Quando o CORS está habilitado com `'*'`, Liquido exibe um aviso na inicialização.
243+
240244
### Servindo arquivos estáticos
241245

242246
Uma aplicação em Liquido pode servir arquivos estáticos se o roteador tiver uma configuração de diretório correspondente. Por exemplo:

configuracao.delprops

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ liquido.roteador.diretorioEstatico = 'publico'
44

55
// Configuração do roteador.
66
liquido.roteador.cors = verdadeiro
7+
// CORS liberado para qualquer origem ('*') é adequado apenas para desenvolvimento.
8+
// Em produção, restrinja para o(s) domínio(s) da aplicação, separados por vírgula.
9+
liquido.roteador.origensCors = '*'
710
liquido.roteador.bodyParser = verdadeiro
811
liquido.roteador.morgan = verdadeiro
912
liquido.roteador.cookieParser = verdadeiro

fontes/delprops/roteador.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ const roteador: DefinicaoPropriedade[] = [
1515
tipo: 'logico',
1616
detalhe: 'Habilita CORS (padrão: falso).',
1717
},
18+
{
19+
nome: 'origensCors',
20+
tipo: 'texto',
21+
detalhe:
22+
"Origem(ns) permitida(s) para CORS, separadas por vírgula. " +
23+
"O padrão '*' libera qualquer origem e é adequado apenas para desenvolvimento; " +
24+
"em produção, restrinja para o(s) domínio(s) da aplicação.",
25+
},
1826
{
1927
nome: 'bodyParser',
2028
tipo: 'logico',

fontes/infraestrutura/centro-configuracoes/configuracao-roteador.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ConfiguracaoComum } from "./configuracao-comum";
44
export class ConfiguracaoRoteador extends ConfiguracaoComum {
55
diretorioEstatico: string = 'publico';
66
cors: boolean = false;
7+
origensCors: string = '*';
78
bodyParser: boolean = true;
89
morgan: boolean = false;
910
cookieParser: boolean = true;
@@ -20,6 +21,7 @@ export class ConfiguracaoRoteador extends ConfiguracaoComum {
2021
const roteador = componentes['roteador'] as RoteadorInterface;
2122
roteador.ativarDesativarBodyParser(this.bodyParser);
2223
roteador.ativarDesativarCors(this.cors);
24+
roteador.configurarOrigensCors(this.origensCors);
2325
roteador.ativarDesativarCookieParser(this.cookieParser);
2426
roteador.ativarDesativarExpressJson(this.json);
2527
roteador.ativarDesativarHelmet(this.helmet);

fontes/infraestrutura/roteador/roteador.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export class Roteador implements RoteadorInterface {
3232
bodyParser = false;
3333

3434
cors = false;
35+
origensCors = '*';
3536
passport = false;
3637

3738
constructor(autoDocumentador: AutoDocumentador) {
@@ -122,7 +123,17 @@ export class Roteador implements RoteadorInterface {
122123
}
123124

124125
if (this.cors) {
125-
this.aplicacao.use(cors());
126+
const opcoesCors = this.resolverOpcoesCors();
127+
if (opcoesCors === undefined) {
128+
console.log(
129+
"[Liquido] CORS habilitado para qualquer origem ('*'). " +
130+
"Adequado apenas para desenvolvimento; em produção, restrinja com " +
131+
"liquido.roteador.origensCors = 'https://seudominio.com.br' em configuracao.delprops."
132+
);
133+
this.aplicacao.use(cors());
134+
} else {
135+
this.aplicacao.use(cors(opcoesCors));
136+
}
126137
}
127138

128139
if (this.passport) {
@@ -138,6 +149,38 @@ export class Roteador implements RoteadorInterface {
138149
this.cors = valor;
139150
}
140151

152+
/**
153+
* Define a(s) origem(ns) permitida(s) para CORS. Aceita uma única origem
154+
* ou várias separadas por vírgula. O valor '*' (padrão) libera qualquer
155+
* origem e deve ser usado apenas em desenvolvimento.
156+
*/
157+
configurarOrigensCors(origem: string): void {
158+
this.origensCors = origem && origem.trim().length > 0 ? origem : '*';
159+
}
160+
161+
/**
162+
* Traduz `origensCors` para as opções do middleware `cors`.
163+
* @returns `undefined` quando a origem é '*' (comportamento padrão do
164+
* middleware, que libera qualquer origem), ou um objeto com a
165+
* lista de origens permitidas.
166+
*/
167+
resolverOpcoesCors(): { origin: string[] } | undefined {
168+
if (this.origensCors === '*') {
169+
return undefined;
170+
}
171+
172+
const origens = this.origensCors
173+
.split(',')
174+
.map(origem => origem.trim())
175+
.filter(origem => origem.length > 0);
176+
177+
if (origens.length === 0) {
178+
return undefined;
179+
}
180+
181+
return { origin: origens };
182+
}
183+
141184
ativarDesativarPassport(valor: boolean): void {
142185
this.passport = valor;
143186
}

fontes/interface-linha-comando/exemplos/delegua/api-rest/configuracao.delprops

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ liquido.roteador.diretorioEstatico = 'publico'
1212

1313
// Configuração do roteador.
1414
liquido.roteador.cors = verdadeiro
15+
// CORS liberado para qualquer origem ('*') é adequado apenas para desenvolvimento.
16+
// Em produção, restrinja para o(s) domínio(s) da aplicação, separados por vírgula.
17+
liquido.roteador.origensCors = '*'
1518
liquido.roteador.bodyParser = verdadeiro
1619
liquido.roteador.morgan = verdadeiro
1720
liquido.roteador.cookieParser = verdadeiro

fontes/interface-linha-comando/exemplos/delegua/mvc/configuracao.delprops

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ liquido.roteador.diretorioEstatico = 'publico'
1212

1313
// Configuração do roteador.
1414
liquido.roteador.cors = verdadeiro
15+
// CORS liberado para qualquer origem ('*') é adequado apenas para desenvolvimento.
16+
// Em produção, restrinja para o(s) domínio(s) da aplicação, separados por vírgula.
17+
liquido.roteador.origensCors = '*'
1518
liquido.roteador.bodyParser = verdadeiro
1619
liquido.roteador.morgan = verdadeiro
1720
liquido.roteador.cookieParser = verdadeiro

fontes/interface-linha-comando/exemplos/pitugues/api-rest/configuracao.delprops

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ liquido.roteador.diretorioEstatico = 'publico'
1212

1313
// Configuração do roteador.
1414
liquido.roteador.cors = verdadeiro
15+
// CORS liberado para qualquer origem ('*') é adequado apenas para desenvolvimento.
16+
// Em produção, restrinja para o(s) domínio(s) da aplicação, separados por vírgula.
17+
liquido.roteador.origensCors = '*'
1518
liquido.roteador.bodyParser = verdadeiro
1619
liquido.roteador.morgan = verdadeiro
1720
liquido.roteador.cookieParser = verdadeiro

fontes/interface-linha-comando/exemplos/pitugues/mvc/configuracao.delprops

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ liquido.roteador.diretorioEstatico = 'publico'
1212

1313
// Configuração do roteador.
1414
liquido.roteador.cors = verdadeiro
15+
// CORS liberado para qualquer origem ('*') é adequado apenas para desenvolvimento.
16+
// Em produção, restrinja para o(s) domínio(s) da aplicação, separados por vírgula.
17+
liquido.roteador.origensCors = '*'
1518
liquido.roteador.bodyParser = verdadeiro
1619
liquido.roteador.morgan = verdadeiro
1720
liquido.roteador.cookieParser = verdadeiro

fontes/interfaces/roteador-interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export interface RoteadorInterface {
22
ativarDesativarCors(valor: boolean): void;
3+
configurarOrigensCors(origem: string): void;
34
ativarDesativarPassport(valor: boolean): void;
45
ativarDesativarCookieParser(valor: boolean): void;
56
ativarDesativarExpressJson(valor: boolean): void;

0 commit comments

Comments
 (0)