Skip to content

Commit

Permalink
Switch redactions test case to OAuth 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mmd-osm committed Dec 21, 2023
1 parent 5af7d97 commit 9975486
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 50 deletions.
13 changes: 12 additions & 1 deletion include/cgimap/backend/staticxml/staticxml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,21 @@

#include "cgimap/backend.hpp"

#include <map>
#include <memory>

struct oauth2_token_detail_t
{
bool expired;
bool revoked;
bool api_write;
osm_user_id_t user_id;
};

using oauth2_tokens = std::map<std::string, oauth2_token_detail_t>;

using user_roles_t = std::map<osm_user_id_t, std::set<osm_user_role_t> >;

std::unique_ptr<backend> make_staticxml_backend(user_roles_t = {});
std::unique_ptr<backend> make_staticxml_backend(user_roles_t = {}, oauth2_tokens = {});

#endif /* STATICXML_BACKEND_HPP */
42 changes: 29 additions & 13 deletions src/backend/staticxml/staticxml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,14 @@ inline void write_element<relation>(const relation &r, output_formatter &formatt
}

struct static_data_selection : public data_selection {
explicit static_data_selection(database& db) : static_data_selection(db, {}) {}
explicit static_data_selection(database& db) : static_data_selection(db, {}, {}) {}

explicit static_data_selection(database& db, user_roles_t m_user_roles)
explicit static_data_selection(database& db, user_roles_t m_user_roles, oauth2_tokens m_oauth2_tokens)
: m_db(db)
, m_include_changeset_comments(false)
, m_redactions_visible(false)
, m_user_roles(m_user_roles) {}
, m_user_roles(m_user_roles)
, m_oauth2_tokens(m_oauth2_tokens){}

~static_data_selection() override = default;

Expand Down Expand Up @@ -591,6 +592,16 @@ struct static_data_selection : public data_selection {
std::optional< osm_user_id_t > get_user_id_for_oauth2_token(
const std::string &token_id, bool &expired, bool &revoked,
bool &allow_api_write) {

auto itr = m_oauth2_tokens.find(token_id);
if (itr != m_oauth2_tokens.end())
{
expired = itr->second.expired;
revoked = itr->second.revoked;
allow_api_write = itr->second.api_write;
return itr->second.user_id;
}

expired = false;
revoked = false;
allow_api_write = false;
Expand Down Expand Up @@ -751,6 +762,7 @@ struct static_data_selection : public data_selection {
std::set<osm_edition_t> m_historic_nodes, m_historic_ways, m_historic_relations;
bool m_include_changeset_comments, m_redactions_visible;
user_roles_t m_user_roles;
oauth2_tokens m_oauth2_tokens;
};

template <>
Expand All @@ -769,16 +781,17 @@ const std::map<id_version, relation> &static_data_selection::map_of<relation>()
}

struct factory : public data_selection::factory {
explicit factory(const std::string &file) : factory(file, {}) {}
explicit factory(const std::string &file) : factory(file, {}, {}) {}

explicit factory(const std::string &file, user_roles_t user_roles)
: m_database(parse_xml(file.c_str())),
m_user_roles(user_roles) {}
explicit factory(const std::string &file, user_roles_t user_roles, oauth2_tokens oauth2_tokens)
: m_database(parse_xml(file.c_str()))
, m_user_roles(user_roles)
, m_oauth2_tokens(oauth2_tokens) {}

~factory() override = default;

std::unique_ptr<data_selection> make_selection(Transaction_Owner_Base&) const override {
return std::make_unique<static_data_selection>(*m_database, m_user_roles);
return std::make_unique<static_data_selection>(*m_database, m_user_roles, m_oauth2_tokens);
}

std::unique_ptr<Transaction_Owner_Base> get_default_transaction() override {
Expand All @@ -788,15 +801,17 @@ struct factory : public data_selection::factory {
private:
std::unique_ptr<database> m_database;
user_roles_t m_user_roles;
oauth2_tokens m_oauth2_tokens;
};

struct staticxml_backend : public backend {
staticxml_backend() : staticxml_backend(user_roles_t{}) {}
staticxml_backend() : staticxml_backend(user_roles_t{}, oauth2_tokens{}) {}

staticxml_backend(user_roles_t user_roles) {
staticxml_backend(user_roles_t user_roles, oauth2_tokens oauth2_tokens) {
m_options.add_options()("file", po::value<std::string>()->required(),
"file to load static OSM XML from.");
m_user_roles = user_roles;
m_oauth2_tokens = oauth2_tokens;
}

~staticxml_backend() override = default;
Expand All @@ -806,7 +821,7 @@ struct staticxml_backend : public backend {

std::unique_ptr<data_selection::factory> create(const po::variables_map &opts) override {
std::string file = opts["file"].as<std::string>();
return std::make_unique<factory>(file, m_user_roles);
return std::make_unique<factory>(file, m_user_roles, m_oauth2_tokens);
}

std::unique_ptr<data_update::factory> create_data_update(const po::variables_map &) override {
Expand All @@ -817,11 +832,12 @@ struct staticxml_backend : public backend {
std::string m_name{"staticxml"};
po::options_description m_options{"Static XML backend options"};
user_roles_t m_user_roles;
oauth2_tokens m_oauth2_tokens;
};

} // anonymous namespace


std::unique_ptr<backend> make_staticxml_backend(user_roles_t user_roles) {
return std::make_unique<staticxml_backend>(user_roles);
std::unique_ptr<backend> make_staticxml_backend(user_roles_t user_roles, oauth2_tokens oauth2_tokens) {
return std::make_unique<staticxml_backend>(user_roles, oauth2_tokens);
}
4 changes: 2 additions & 2 deletions test/redactions.testcore/changeset_download_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Request-Method: GET
Request-URI: /api/0.6/changeset/2/download?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-03-13T16:47:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/changeset/2/download", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="dqndteqmzduesxyjetrd", oauth_timestamp="1489423620", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="2KQpmh%2FAJi9xTpZvCIo82inmdho%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
!Content-Disposition:
!Content-Disposition:
---
<osmChange version="0.6" generator="***" copyright="***" attribution="***" license="***">
<modify>
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/node_history_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/node/1/history?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T17:11:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/node/1/history", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="ylxApRr7uw94cVGRwxbx", oauth_timestamp="1486141860", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="IcgPfe%2F4C4Rh5HlnZQg388bn5Fo%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/node_version_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/node/1/2?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-01-23T20:25:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/node/1/2", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="ykvbwrcver", oauth_timestamp="1485203100", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="NzUgxE%2B%2BueNwfnHtbLyJBTxdVus%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/nodes_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/nodes?nodes=1v1,1v2&show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T17:22:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/nodes", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="X1VcT5srCUFk7NMbDBBi", oauth_timestamp="1486142520", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="LanUZRlaRV7uJYaXgTJ30Mqog3M%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
11 changes: 0 additions & 11 deletions test/redactions.testcore/oauth.json

This file was deleted.

10 changes: 10 additions & 0 deletions test/redactions.testcore/oauth2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"tokens": {
"1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI": {
"expired": false,
"revoked": false,
"api_write": false,
"user_id": 2
}
}
}
2 changes: 1 addition & 1 deletion test/redactions.testcore/relation_history_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/relation/1/history?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T17:15:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/relation/1/history", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="i89B012BEg0Y5KHiiG5j", oauth_timestamp="1486142100", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="dI%2F6nEplWIcCUtwXul3LYC8ZuZI%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/relation_version_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Request-Method: GET
Request-URI: /api/0.6/relation/1/2?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T16:37:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/relation/1/2", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="OFP9OGKNWTfBUw7hvB3A", oauth_timestamp="1486139820", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="N9V4%2FqNx5an7gOmmL4MhDBfKec0%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/relations_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/relations?relations=1v1,1v2&show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T17:26:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/relations", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="s5ikn2rEXP8sEY4yWioL", oauth_timestamp="1486142760", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="OQMjxYyDtdnAkz%2Fz%2FYVN7cQDj6w%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/way_history_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/way/1/history?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T17:13:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/way/1/history", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="EsHFWX0Ru330NARIKysY", oauth_timestamp="1486141980", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="Mkx4Sg%2BXWQkd7P0lhmPyszo2zIo%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/way_version_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Request-Method: GET
Request-URI: /api/0.6/way/1/2?show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T16:31:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/way/1/2", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="ng8dUT94UOvYmX98sAof", oauth_timestamp="1486139460", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="QnliNV2%2BjeQWVDPZUXwTxrc%2BhDQ%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
2 changes: 1 addition & 1 deletion test/redactions.testcore/ways_moderator.case
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Request-Method: GET
Request-URI: /api/0.6/ways?ways=1v1,1v2&show_redactions=true
Http-Host: cgimap.example.com
Date: 2017-02-03T17:24:00Z
Http-Authorization: OAuth realm="http://cgimap.example.com/api/0.6/ways", oauth_consumer_key="heqfjrcolc", oauth_token="scgncknxqr", oauth_nonce="sD8ADXbFprXuraBKHyH5", oauth_timestamp="1486142640", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="fQdcQw1OdVF%2BEhrPrFzxCD3c5Y0%3D"
Http-Authorization: Bearer 1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI
---
Status: 200 OK
Content-Type: application/xml; charset=utf-8
Expand Down
79 changes: 65 additions & 14 deletions test/test_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ osm_user_role_t parse_role(const std::string &str) {
}
}

user_roles_t get_user_roles(const pt::ptree &config)
user_roles_t parse_user_roles(const pt::ptree &config)
{
user_roles_t user_roles;
boost::optional< const pt::ptree& > users = config.get_child_optional("users");
Expand All @@ -554,6 +554,65 @@ user_roles_t get_user_roles(const pt::ptree &config)
return user_roles;
}

user_roles_t get_user_roles(const fs::path &roles_file)
{
if (fs::is_regular_file(roles_file))
{
try
{
pt::ptree config;
pt::read_json(roles_file.string(), config);
return parse_user_roles(config);
}
catch (const std::exception &ex)
{
throw std::runtime_error(
fmt::format("{}, while reading expected JSON.", ex.what()));
}
}
return {};
}


oauth2_tokens parse_oauth2_tokens(const pt::ptree &config)
{
oauth2_tokens oauth2_tokens;
boost::optional< const pt::ptree& > tokens = config.get_child_optional("tokens");
if (tokens)
{
for (const auto &entry : *tokens)
{
oauth2_token_detail_t detail;
auto token = entry.first;
detail.api_write = entry.second.get<bool>("api_write", false);
detail.expired = entry.second.get<bool>("expired", true);
detail.revoked = entry.second.get<bool>("revoked", true);
detail.user_id = entry.second.get<osm_user_id_t>("user_id", {});
oauth2_tokens[token] = std::move(detail);
}
}
return oauth2_tokens;
}

oauth2_tokens get_oauth2_tokens(const fs::path &oauth2_file)
{
if (fs::is_regular_file(oauth2_file))
{
try
{
pt::ptree config;
pt::read_json(oauth2_file.string(), config);
return parse_oauth2_tokens(config);
}
catch (const std::exception &ex)
{
throw std::runtime_error(
fmt::format("{}, while reading expected JSON.", ex.what()));
}
}
return {};
}


int main(int argc, char *argv[]) {
if (argc != 2) {
Expand All @@ -563,11 +622,12 @@ int main(int argc, char *argv[]) {

fs::path test_directory = argv[1];
fs::path data_file = test_directory / "data.osm";
fs::path oauth_file = test_directory / "oauth.json";
fs::path oauth2_file = test_directory / "oauth2.json";
fs::path roles_file = test_directory / "roles.json";
std::vector<fs::path> test_cases;

user_roles_t user_roles;
oauth2_tokens oauth2_tokens;

try {
if (fs::is_directory(test_directory) == false) {
Expand All @@ -589,17 +649,8 @@ int main(int argc, char *argv[]) {
}
}

if (fs::is_regular_file(roles_file)) {
pt::ptree config;

try {
pt::read_json(roles_file.string(), config);
} catch (const std::exception &ex) {
throw std::runtime_error
(fmt::format("{}, while reading expected JSON.", ex.what()));
}
user_roles = get_user_roles(config);
}
user_roles = get_user_roles(roles_file);
oauth2_tokens = get_oauth2_tokens(oauth2_file);

} catch (const std::exception &e) {
std::cerr << "EXCEPTION: " << e.what() << std::endl;
Expand All @@ -615,7 +666,7 @@ int main(int argc, char *argv[]) {
vm.insert(std::make_pair(std::string("file"),
po::variable_value(data_file.native(), false)));

auto data_backend = make_staticxml_backend(user_roles);
auto data_backend = make_staticxml_backend(user_roles, oauth2_tokens);
auto factory = data_backend->create(vm);
null_rate_limiter limiter;
routes route;
Expand Down

0 comments on commit 9975486

Please sign in to comment.