Pular para o conteúdo

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#

dataforge
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:

dataforge
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#

dataforge
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á.

dataforge
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 árvore

Autenticação#

Registre a ação que confere usuário e senha. Ela recebe os dois e devolve o vault do usuário, ou void:

dataforge
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:

dataforge
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.

ChamadaDevolve
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çalhoContra
X-Content-Type-Options: nosniffo navegador adivinhar o tipo do conteúdo
X-Frame-Options: SAMEORIGINclickjacking
Referrer-Policyvazar a URL inteira para terceiros
Content-Security-Policyscript 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.