aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake/config.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/flake/config.cc')
-rw-r--r--src/libexpr/flake/config.cc83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/libexpr/flake/config.cc b/src/libexpr/flake/config.cc
new file mode 100644
index 000000000..41b6f78ed
--- /dev/null
+++ b/src/libexpr/flake/config.cc
@@ -0,0 +1,83 @@
+#include "flake.hh"
+
+#include <nlohmann/json.hpp>
+
+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() + "/nix/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()
+{
+ std::set<std::string> whitelist{"bash-prompt", "bash-prompt-suffix", "flake-registry"};
+
+ 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 = concatStringsSep(" ", *ss); // FIXME: evil
+ else
+ assert(false);
+
+ if (!whitelist.count(baseName)) {
+ auto trustedList = readTrustedList();
+
+ bool trusted = false;
+
+ if (auto saved = get(get(trustedList, name).value_or(std::map<std::string, bool>()), valueS)) {
+ trusted = *saved;
+ } 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') {
+ if (std::tolower(logger->ask("do you want to permanently mark this value as untrusted (y/N)?").value_or('n')) == 'y') {
+ trustedList[name][valueS] = false;
+ writeTrustedList(trustedList);
+ }
+ } else {
+ if (std::tolower(logger->ask("do you want to permanently mark this value as trusted (y/N)?").value_or('n')) == 'y') {
+ trustedList[name][valueS] = trusted = true;
+ writeTrustedList(trustedList);
+ }
+ }
+ }
+
+ if (!trusted) {
+ warn("ignoring untrusted flake configuration setting '%s'", name);
+ continue;
+ }
+ }
+
+ globalConfig.set(name, valueS);
+ }
+}
+
+}