rustploy-gui 0.1.21

Rustploy — desktop client (glacier-ui) for the Rustploy PaaS daemon
--!strict
--!nolint FunctionUnused
-- handlers/secrets.luau — aba "Secrets" do projeto: criar/sobrescrever e
-- apagar valores cifrados, e o atalho "usar secret" da aba Variáveis.
--
-- A UI é write-only DE PROPÓSITO: o daemon só devolve os NOMES (SecretList →
-- Response::SecretNames), nunca o blob cifrado, então não há o que exibir nem
-- como "editar" um valor — sobrescrever é salvar outro com o mesmo nome
-- (o SecretSet do daemon faz ON CONFLICT DO UPDATE). Ver docs/secrets.md.
--
-- A lista em si não é buscada aqui: vem no snapshot (`projects[].secrets`),
-- montada por handlers/stream.luau em
-- ctx.project_secrets/project_secrets_count.

local State = require("../state")
local Helpers = require("../helpers")
local Stream = require("stream")

-- Nomes atualmente conhecidos (do snapshot já renderizado), para saber se um
-- SecretSet cria ou substitui — o daemon não distingue os dois casos.
local function known_names(): { [string]: boolean }
    local names_set = {}
    local json_decode_ok, rows = Helpers.decode_list(ctx.project_secrets)
    if json_decode_ok and type(rows) == "table" then
        for _, row in ipairs(rows) do
            names_set[tostring(row.name)] = true
        end
    end
    return names_set
end

-- on_validation_error do form(name = secret_add) — NOME e valor são
-- `rules="required"` no form(...); o motor publica
-- {error_project_secret_new_name} / {error_project_secret_new_value} e acende
-- o :invalid. Aqui é só o aviso.
function secret_add_show_validation_errors(_erros_json: string?): ()
    toast { message = "Preencha nome e valor do secret", kind = "warning" }
end

function secret_add(): ()
    local project_id = ctx.selected_project_id or ""
    local api = State.api
    if project_id == "" or not api then
        return
    end
    -- rules="required" no form(...) garante nome e valor preenchidos aqui.
    local name = Helpers.trim(ctx.project_secret_new_name)
    local value = ctx.project_secret_new_value or ""
    local replacing = known_names()[name] == true
    local secret_set_ok, secret_set_response = api:rpc_checked {
        SecretSet = { project_id = project_id, name = name, value = value },
    }
    if secret_set_ok then
        ctx.project_secret_new_name = ""
        ctx.project_secret_new_value = ""
        local message = 'Secret "' .. name .. '" criado'
        if replacing then
            message = 'Secret "'
                .. name
                .. '" substituído — o novo valor vale no próximo deploy'
        end
        toast { message = message, kind = "success" }
        Stream.refresh_now()
    else
        toast { message = tostring(secret_set_response), kind = "error" }
    end
end

function secret_delete(name: string): ()
    local project_id = ctx.selected_project_id or ""
    if project_id == "" or name == "" then
        return
    end
    local confirmed = confirm {
        title = "Remover secret?",
        message = "O valor cifrado será apagado e não há como recuperá-lo. "
            .. 'Variáveis que referenciam "'
            .. name
            .. '" passarão a receber '
            .. "valor vazio no próximo deploy.",
        confirm_label = "Remover secret",
        destructive = true,
    }
    if not confirmed then
        return
    end
    local api = State.api
    if not api then
        return
    end
    local secret_delete_ok, secret_delete_response = api:rpc_checked {
        SecretDelete = { project_id = project_id, name = name },
    }
    if secret_delete_ok then
        toast { message = tostring("Secret removido"), kind = "success" }
        Stream.refresh_now()
    else
        toast { message = tostring(secret_delete_response), kind = "error" }
    end
end

-- Chip "usar secret" (aba Variáveis): arma o form de adicionar var em modo
-- secret com o nome escolhido. Quem grava é project_env_add
-- (handlers/projects.luau), que nesse modo monta { Secret = nome } em vez de {
-- Plain = valor }.
function secret_use(name: string): ()
    ctx.project_env_new_is_secret = "true"
    ctx.project_env_new_value = name
    if Helpers.trim(ctx.project_env_new_key) == "" then
        ctx.project_env_new_key = name
    end
end

function project_env_secret_toggle(): ()
    local on = Helpers.is_true(ctx.project_env_new_is_secret)
    ctx.project_env_new_is_secret = on and "false" or "true"
    ctx.project_env_new_value = ""
end