Páginas e segurança
Multipágina, rotas com parâmetro, autenticação, permissões e os cabeçalhos que toda resposta leva.
Várias páginas#
V.app("Painel")
V.pagina("/", inicio, titulo := "Início", icone := "🏠")
V.pagina("/vendas", vendas, titulo := "Vendas", icone := "📊")
V.pagina("/produto/:id", produto, oculta := yes)
V.rodar(porta := 8501)Também funciona como decorador:
mark @V.pagina("/vendas")
action vendas():
V.titulo("Vendas")V.menu() desenha o menu das páginas registradas na barra lateral, na ordem do registro. Uma página oculta continua alcançável pela URL e não aparece no menu.
Parâmetros#
action produto():
id := V.parametro("id") // da rota: /produto/:id
ordem := V.parametro("ordem", "asc") // da query: ?ordem=desc
V.titulo($"Produto {id}")V.parametros() devolve os dois juntos; V.caminho() devolve onde a página está.
Navegar e parar#
V.navegar("/entrar") // vai para outra página, e para aqui
V.parar() // acaba a página neste ponto, sem erro
V.recarregar() // roda de novo, do começo, jogando fora a árvoreAutenticação#
Registre a ação que confere usuário e senha. Ela recebe os dois e devolve o vault do usuário, ou void:
action conferir(usuario, senha):
linha := Banco.um("SELECT * FROM usuarios WHERE email = ?", [usuario])
given linha is not void and Crypto.conferir_senha(senha, linha["hash"]):
yield {"nome": linha["nome"], "papel": linha["papel"]}
yield void
V.autenticacao(conferir, {
"admin": ["ver", "editar", "apagar"],
"leitor": ["ver"]
})E a barreira, na primeira linha de cada página protegida:
action relatorio():
V.exigir_login()
V.titulo($"Olá, {V.usuario()["nome"]}")
action edicao():
V.exigir_permissao("editar")
V.titulo("Edição")V.exigir_login() desenha o formulário de entrada e para a página. Quando já há alguém logado, ela devolve o usuário e não desenha nada — o que permite chamá-la sempre na primeira linha.
| Chamada | Devolve |
|---|---|
V.usuario() | o vault de quem está logado, ou void |
V.autenticado() | yes/no |
V.pode(permissão) | yes/no, pelo papel |
V.entrar(usuario, senha) | o vault, ou void |
V.sair() | derruba a sessão de quem está logado |
Segurança#
Toda resposta HTML leva estes cabeçalhos, sem configuração:
| Cabeçalho | Contra |
|---|---|
X-Content-Type-Options: nosniff | o navegador adivinhar o tipo do conteúdo |
X-Frame-Options: SAMEORIGIN | clickjacking |
Referrer-Policy | vazar a URL inteira para terceiros |
Content-Security-Policy | script de outra origem |
O cookie de sessão é HttpOnly e SameSite=Lax. Com V.configurar("https", yes) ele também ganha Secure.
Todo texto que vai à página é escapado — o único que não é passa por V.html, que avisa disso. E V.markdown escapa antes de reconhecer a marcação, além de recusar link javascript:.
Para limite de taxa e CORS, use o middleware do Kiln sobre V.montar() — ver Middleware do Kiln.