1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-16 15:32:43 +01:00
nix/src/libflake/config.cc
2025-10-14 23:20:35 -04:00

125 lines
4 KiB
C++

#include <nlohmann/json.hpp>
#include <assert.h>
#include <stdint.h>
#include <nlohmann/json_fwd.hpp>
#include <cctype>
#include <filesystem>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>
#include <format>
#include "nix/util/users.hh"
#include "nix/util/config-global.hh"
#include "nix/flake/settings.hh"
#include "nix/flake/flake.hh"
#include "nix/util/ansicolor.hh"
#include "nix/util/configuration.hh"
#include "nix/util/file-system.hh"
#include "nix/util/fmt.hh"
#include "nix/util/logging.hh"
#include "nix/util/strings.hh"
#include "nix/util/types.hh"
#include "nix/util/util.hh"
namespace nix::flake {
// setting name -> setting value -> allow or ignore.
typedef std::map<std::string, std::map<std::string, bool>> TrustedList;
Path trustedListPath()
{
return getDataDir() + "/trusted-settings.json";
}
static TrustedList readTrustedList()
{
auto path = trustedListPath();
if (!pathExists(path))
return {};
auto json = nlohmann::json::parse(readFile(path));
return json;
}
static void writeTrustedList(const TrustedList & trustedList)
{
auto path = trustedListPath();
createDirs(dirOf(path));
writeFile(path, nlohmann::json(trustedList).dump());
}
void ConfigFile::apply(const Settings & flakeSettings)
{
StringSet whitelist{
"bash-prompt",
"bash-prompt-prefix",
"bash-prompt-suffix",
"flake-registry",
"commit-lock-file-summary",
"commit-lockfile-summary"};
for (auto & [name, value] : settings) {
auto baseName = hasPrefix(name, "extra-") ? std::string(name, 6) : name;
// FIXME: Move into libutil/config.cc.
std::string valueS;
if (auto * s = std::get_if<std::string>(&value))
valueS = *s;
else if (auto * n = std::get_if<int64_t>(&value))
valueS = fmt("%d", *n);
else if (auto * b = std::get_if<Explicit<bool>>(&value))
valueS = b->t ? "true" : "false";
else if (auto ss = std::get_if<std::vector<std::string>>(&value))
valueS = dropEmptyInitThenConcatStringsSep(" ", *ss); // FIXME: evil
else
assert(false);
if (!whitelist.count(baseName) && !flakeSettings.acceptFlakeConfig) {
bool trusted = false;
auto trustedList = readTrustedList();
auto tlname = get(trustedList, name);
if (auto saved = tlname ? get(*tlname, valueS) : nullptr) {
trusted = *saved;
printInfo(
"Using saved setting for '%s = %s' from ~/.local/share/nix/trusted-settings.json.", name, valueS);
} else {
// FIXME: filter ANSI escapes, newlines, \r, etc.
if (std::tolower(logger
->ask(
fmt("do you want to allow configuration setting '%s' to be set to '" ANSI_RED
"%s" ANSI_NORMAL "' (y/N)?",
name,
valueS))
.value_or('n'))
== 'y') {
trusted = true;
}
if (std::tolower(logger
->ask(
fmt("do you want to permanently mark this value as %s (y/N)?",
trusted ? "trusted" : "untrusted"))
.value_or('n'))
== 'y') {
trustedList[name][valueS] = trusted;
writeTrustedList(trustedList);
}
}
if (!trusted) {
warn(
"ignoring untrusted flake configuration setting '%s'.\nPass '%s' to trust it",
name,
"--accept-flake-config");
continue;
}
}
globalConfig.set(name, valueS);
}
}
} // namespace nix::flake