diff --git a/src/libfetchers-tests/access-tokens.cc b/src/libfetchers-tests/access-tokens.cc new file mode 100644 index 000000000..02ca082d4 --- /dev/null +++ b/src/libfetchers-tests/access-tokens.cc @@ -0,0 +1,79 @@ +#include +#include "fetchers.hh" +#include "fetch-settings.hh" +#include "json-utils.hh" +#include +#include "tests/characterization.hh" + +namespace nix::fetchers { + +using nlohmann::json; + +class AccessKeysTest : public ::testing::Test +{ +protected: + +public: + void SetUp() override { + experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes); + } + void TearDown() override { } +}; + +TEST_F(AccessKeysTest, singleGitHub) +{ + fetchers::Settings fetchSettings = fetchers::Settings{}; + fetchSettings.accessTokens.get().insert({"github.com","token"}); + auto i = Input::fromURL(fetchSettings, "github:a/b"); + + auto token = i.scheme->getAccessToken(fetchSettings, "github.com", "github.com/a/b"); + ASSERT_EQ(token,"token"); +} + +TEST_F(AccessKeysTest, repoGitHub) +{ + fetchers::Settings fetchSettings = fetchers::Settings{}; + fetchSettings.accessTokens.get().insert({"github.com","token"}); + fetchSettings.accessTokens.get().insert({"github.com/a/b","another_token"}); + fetchSettings.accessTokens.get().insert({"github.com/a/c","yet_another_token"}); + auto i = Input::fromURL(fetchSettings, "github:a/a"); + + auto token = i.scheme->getAccessToken(fetchSettings, "github.com", "github.com/a/a"); + ASSERT_EQ(token,"token"); + + token = i.scheme->getAccessToken(fetchSettings, "github.com", "github.com/a/b"); + ASSERT_EQ(token,"another_token"); + + token = i.scheme->getAccessToken(fetchSettings, "github.com", "github.com/a/c"); + ASSERT_EQ(token,"yet_another_token"); +} + +TEST_F(AccessKeysTest, multipleGitLab) +{ + fetchers::Settings fetchSettings = fetchers::Settings{}; + fetchSettings.accessTokens.get().insert({"gitlab.com","token"}); + fetchSettings.accessTokens.get().insert({"gitlab.com/a/b","another_token"}); + auto i = Input::fromURL(fetchSettings, "gitlab:a/b"); + + auto token = i.scheme->getAccessToken(fetchSettings, "gitlab.com", "gitlab.com/a/b"); + ASSERT_EQ(token,"another_token"); + + token = i.scheme->getAccessToken(fetchSettings, "gitlab.com", "gitlab.com/a/c"); + ASSERT_EQ(token,"token"); +} + +TEST_F(AccessKeysTest, multipleSourceHut) +{ + fetchers::Settings fetchSettings = fetchers::Settings{}; + fetchSettings.accessTokens.get().insert({"git.sr.ht","token"}); + fetchSettings.accessTokens.get().insert({"git.sr.ht/~a/b","another_token"}); + auto i = Input::fromURL(fetchSettings, "sourcehut:a/b"); + + auto token = i.scheme->getAccessToken(fetchSettings, "git.sr.ht", "git.sr.ht/~a/b"); + ASSERT_EQ(token,"another_token"); + + token = i.scheme->getAccessToken(fetchSettings, "git.sr.ht", "git.sr.ht/~a/c"); + ASSERT_EQ(token,"token"); +} + +} diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index 739435501..243bbab80 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -44,6 +44,7 @@ subdir('nix-meson-build-support/common') sources = files( 'public-key.cc', + 'access-tokens.cc', ) include_dirs = [include_directories('.')] diff --git a/src/libfetchers/fetch-settings.hh b/src/libfetchers/fetch-settings.hh index 2ad8aa327..c6c3ca7a7 100644 --- a/src/libfetchers/fetch-settings.hh +++ b/src/libfetchers/fetch-settings.hh @@ -23,9 +23,11 @@ struct Settings : public Config Access tokens are specified as a string made up of space-separated `host=token` values. The specific token used is selected by matching the `host` portion against the - "host" specification of the input. The actual use of the - `token` value is determined by the type of resource being - accessed: + "host" specification of the input. The `host` portion may + contain a path element which will match against the prefix + URL for the input. (eg: `github.com/org=token`). The actual use + of the `token` value is determined by the type of resource + being accessed: * Github: the token value is the OAUTH-TOKEN string obtained as the Personal Access Token from the Github server (see diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 37de1f507..01354a6e3 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -264,6 +264,9 @@ struct InputScheme virtual std::optional isRelative(const Input & input) const { return std::nullopt; } + + virtual std::optional getAccessToken(const fetchers::Settings & settings, const std::string & host, const std::string & url) const + { return {};} }; void registerInputScheme(std::shared_ptr && fetcher); diff --git a/src/libfetchers/github.cc b/src/libfetchers/github.cc index 87b7c0ad3..c34ed844b 100644 --- a/src/libfetchers/github.cc +++ b/src/libfetchers/github.cc @@ -172,7 +172,7 @@ struct GitArchiveInputScheme : InputScheme return input; } - std::optional getAccessToken(const fetchers::Settings & settings, const std::string & host, const std::string & url) const + std::optional getAccessToken(const fetchers::Settings & settings, const std::string & host, const std::string & url) const override { auto tokens = settings.accessTokens.get(); std::string answer;