Skip to content

Commit

Permalink
Merge pull request #214 from offa/90-authtoken
Browse files Browse the repository at this point in the history
Support auth token
  • Loading branch information
offa committed Oct 24, 2023
2 parents 6f90a5e + 86be861 commit 085e6db
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 8 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ const auto response = influxdb->execute("SHOW DATABASES");
An underlying transport is fully configurable by passing an URI:
```
[protocol]://[username:password@]host:port[?db=database]
# Auth token:
[protocol]://[token@]host:port[?db=database]
```
<br>
List of supported transport is following:
Expand Down
7 changes: 6 additions & 1 deletion src/HTTP.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,15 @@ namespace influxdb::transports
session.SetAuth(cpr::Authentication{user, pass, cpr::AuthMode::BASIC});
}

void HTTP::setAuthToken(const std::string& token)
{
session.UpdateHeader(cpr::Header{{"Authorization", "Token " + token}});
}

void HTTP::send(std::string&& lineprotocol)
{
session.SetUrl(cpr::Url{endpointUrl + "/write"});
session.SetHeader(cpr::Header{{"Content-Type", "application/json"}});
session.UpdateHeader(cpr::Header{{"Content-Type", "application/json"}});
session.SetParameters(cpr::Parameters{{"db", databaseName}});
session.SetBody(cpr::Body{lineprotocol});

Expand Down
4 changes: 4 additions & 0 deletions src/HTTP.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ namespace influxdb::transports
/// \param pass password
void setBasicAuthentication(const std::string& user, const std::string& pass);

/// Sets the API token for authentication
/// \param token API token
void setAuthToken(const std::string& token);

/// Sets proxy
void setProxy(const Proxy& proxy) override;

Expand Down
6 changes: 5 additions & 1 deletion src/InfluxDBFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ namespace influxdb
std::unique_ptr<Transport> withHttpTransport(const http::url& uri)
{
auto transport = std::make_unique<transports::HTTP>(uri.url);
if (!uri.user.empty())
if (!uri.user.empty() && !uri.password.empty())
{
transport->setBasicAuthentication(uri.user, uri.password);
}
else if (!uri.password.empty())
{
transport->setAuthToken(uri.password);
}
return transport;
}

Expand Down
11 changes: 9 additions & 2 deletions src/UriParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,15 @@ namespace http
const auto search = ExtractSearch(in);
const auto path = ExtractPath(in);
std::string userpass = ExtractUserpass(in);
const auto password = ExtractPassword(userpass);
const auto user = userpass;

auto [password, user] = [](auto str)
{
if (str.find(":") != std::string::npos)
{
return std::make_pair(ExtractPassword(str), str);
}
return std::make_pair(str, std::string{""});
}(userpass);
const auto port = ExtractPort(in);
const auto host = in;

Expand Down
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_unittest(InfluxDBTest DEPENDS InfluxDB)
add_unittest(InfluxDBFactoryTest DEPENDS InfluxDB)
add_unittest(ProxyTest DEPENDS InfluxDB)
add_unittest(HttpTest DEPENDS InfluxDB-Core InfluxDB-Internal InfluxDB-BoostSupport CprMock Threads::Threads)
add_unittest(UriParserTest)

add_unittest(NoBoostSupportTest)
target_sources(NoBoostSupportTest PRIVATE ${PROJECT_SOURCE_DIR}/src/NoBoostSupport.cxx)
Expand All @@ -53,6 +54,7 @@ add_custom_target(unittest PointTest
COMMAND InfluxDBFactoryTest
COMMAND ProxyTest
COMMAND HttpTest
COMMAND UriParserTest
COMMAND NoBoostSupportTest
COMMAND $<$<AND:$<BOOL:${INFLUXCXX_WITH_BOOST}>,$<NOT:$<PLATFORM_ID:Windows>>>:BoostSupportTest>

Expand Down
16 changes: 12 additions & 4 deletions test/HttpTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ namespace influxdb::test

REQUIRE_CALL(sessionMock, Post()).RETURN(createResponse(cpr::ErrorCode::OK, cpr::status::HTTP_OK));
REQUIRE_CALL(sessionMock, SetUrl(eq("http://localhost:8086/write")));
REQUIRE_CALL(sessionMock, SetHeader(_)).WITH(_1.at("Content-Type") == "application/json");
REQUIRE_CALL(sessionMock, UpdateHeader(_)).WITH(_1.at("Content-Type") == "application/json");
REQUIRE_CALL(sessionMock, SetBody(_)).WITH(_1.str() == data);
REQUIRE_CALL(sessionMock, SetParameters(ParamMap{{"db", "test"}}));

Expand All @@ -95,7 +95,7 @@ namespace influxdb::test

REQUIRE_CALL(sessionMock, Post()).RETURN(createResponse(cpr::ErrorCode::INTERNAL_ERROR, cpr::status::HTTP_OK));
ALLOW_CALL(sessionMock, SetUrl(_));
ALLOW_CALL(sessionMock, SetHeader(_));
ALLOW_CALL(sessionMock, UpdateHeader(_));
ALLOW_CALL(sessionMock, SetBody(_));
ALLOW_CALL(sessionMock, SetParameters(_));

Expand All @@ -108,7 +108,7 @@ namespace influxdb::test

REQUIRE_CALL(sessionMock, Post()).RETURN(createResponse(cpr::ErrorCode::OK, cpr::status::HTTP_OK));
ALLOW_CALL(sessionMock, SetUrl(_));
ALLOW_CALL(sessionMock, SetHeader(_));
ALLOW_CALL(sessionMock, UpdateHeader(_));
ALLOW_CALL(sessionMock, SetBody(_));
ALLOW_CALL(sessionMock, SetParameters(_));

Expand All @@ -121,7 +121,7 @@ namespace influxdb::test

REQUIRE_CALL(sessionMock, Post()).RETURN(createResponse(cpr::ErrorCode::OK, cpr::status::HTTP_NOT_FOUND));
ALLOW_CALL(sessionMock, SetUrl(_));
ALLOW_CALL(sessionMock, SetHeader(_));
ALLOW_CALL(sessionMock, UpdateHeader(_));
ALLOW_CALL(sessionMock, SetBody(_));
ALLOW_CALL(sessionMock, SetParameters(_));

Expand Down Expand Up @@ -225,6 +225,14 @@ namespace influxdb::test
http.setBasicAuthentication("user0", "pass0");
}

TEST_CASE("Set auth token sets auth header", "[HttpTest]")
{
auto http = createHttp();

REQUIRE_CALL(sessionMock, UpdateHeader(_)).WITH(_1.at("Authorization") == "Token not-a-real-api-token");
http.setAuthToken("not-a-real-api-token");
}

TEST_CASE("Set proxy without authentication", "[HttpTest]")
{
auto http = createHttp();
Expand Down
83 changes: 83 additions & 0 deletions test/UriParserTest.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// MIT License
//
// Copyright (c) 2020-2023 offa
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "UriParser.h"
#include <catch2/catch_test_macros.hpp>
#include <catch2/trompeloeil.hpp>

namespace influxdb::test
{
namespace
{
http::url parse(std::string in)
{
return http::ParseHttpUrl(in);
}
}


TEST_CASE("Parse url", "[UriParserTest]")
{
const std::string input{"https://xyz.com/fghi/jklm"};
const auto url = parse(input);

CHECK(url.protocol == "https");
CHECK(url.user == "");
CHECK(url.password == "");
CHECK(url.host == "xyz.com");
CHECK(url.path == "/fghi/jklm");
CHECK(url.search == "");
CHECK(url.url == input);
CHECK(url.port == 0);
}

TEST_CASE("Parse protocol", "[UriParserTest]")
{
CHECK(parse("http://xyz.com").protocol == "http");
CHECK(parse("https://xyz.com").protocol == "https");
CHECK(parse("udp://xyz.com").protocol == "udp");
CHECK(parse("unix://xyz.com").protocol == "unix");
}

TEST_CASE("Parse param", "[UriParserTest]")
{
CHECK(parse("http://xyz.com/aaa?param=value").search == "param=value");
}

TEST_CASE("Parse port", "[UriParserTest]")
{
CHECK(parse("http://xyz.com:12345").port == 12345);
}

TEST_CASE("Parse basic auth", "[UriParserTest]")
{
const auto url = parse("https://aaa:bbb@host0");
CHECK(url.user == "aaa");
CHECK(url.password == "bbb");
}

TEST_CASE("Parse auth token", "[UriParserTest]")
{
CHECK(parse("http://token@xyz.com").password == "token");
}

}
4 changes: 4 additions & 0 deletions test/mock/CprMock.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ namespace cpr
influxdb::test::sessionMock.SetHeader(header);
}

void Session::UpdateHeader(const Header& header)
{
influxdb::test::sessionMock.UpdateHeader(header);
}

Parameters::Parameters(const std::initializer_list<Parameter>& parameters)
: CurlContainer<Parameter>(parameters)
Expand Down
1 change: 1 addition & 0 deletions test/mock/CprMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace influxdb::test
MAKE_MOCK0(Post, cpr::Response());
MAKE_MOCK1(SetUrl, void(const cpr::Url&));
MAKE_MOCK1(SetHeader, void(const cpr::Header&));
MAKE_MOCK1(UpdateHeader, void(const cpr::Header&));
MAKE_MOCK1(SetBody, void(cpr::Body&&));
MAKE_MOCK1(SetParameters, void(std::map<std::string, std::string>));
MAKE_MOCK1(SetAuth, void(const cpr::Authentication&));
Expand Down

0 comments on commit 085e6db

Please sign in to comment.