From 997548648e218d954823dddd0f1a2d49f4d507f0 Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Thu, 21 Dec 2023 19:51:03 +0100 Subject: [PATCH] Switch redactions test case to OAuth 2.0 --- .../cgimap/backend/staticxml/staticxml.hpp | 13 ++- src/backend/staticxml/staticxml.cpp | 42 +++++++--- .../changeset_download_moderator.case | 4 +- .../node_history_moderator.case | 2 +- .../node_version_moderator.case | 2 +- test/redactions.testcore/nodes_moderator.case | 2 +- test/redactions.testcore/oauth.json | 11 --- test/redactions.testcore/oauth2.json | 10 +++ .../relation_history_moderator.case | 2 +- .../relation_version_moderator.case | 2 +- .../relations_moderator.case | 2 +- .../way_history_moderator.case | 2 +- .../way_version_moderator.case | 2 +- test/redactions.testcore/ways_moderator.case | 2 +- test/test_core.cpp | 79 +++++++++++++++---- 15 files changed, 127 insertions(+), 50 deletions(-) delete mode 100644 test/redactions.testcore/oauth.json create mode 100644 test/redactions.testcore/oauth2.json diff --git a/include/cgimap/backend/staticxml/staticxml.hpp b/include/cgimap/backend/staticxml/staticxml.hpp index ff6b61d49..2db914bbe 100644 --- a/include/cgimap/backend/staticxml/staticxml.hpp +++ b/include/cgimap/backend/staticxml/staticxml.hpp @@ -12,10 +12,21 @@ #include "cgimap/backend.hpp" +#include #include +struct oauth2_token_detail_t +{ + bool expired; + bool revoked; + bool api_write; + osm_user_id_t user_id; +}; + +using oauth2_tokens = std::map; + using user_roles_t = std::map >; -std::unique_ptr make_staticxml_backend(user_roles_t = {}); +std::unique_ptr make_staticxml_backend(user_roles_t = {}, oauth2_tokens = {}); #endif /* STATICXML_BACKEND_HPP */ diff --git a/src/backend/staticxml/staticxml.cpp b/src/backend/staticxml/staticxml.cpp index 0e5aca25e..e300f36fd 100644 --- a/src/backend/staticxml/staticxml.cpp +++ b/src/backend/staticxml/staticxml.cpp @@ -312,13 +312,14 @@ inline void write_element(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; @@ -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; @@ -751,6 +762,7 @@ struct static_data_selection : public data_selection { std::set 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 <> @@ -769,16 +781,17 @@ const std::map &static_data_selection::map_of() } 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 make_selection(Transaction_Owner_Base&) const override { - return std::make_unique(*m_database, m_user_roles); + return std::make_unique(*m_database, m_user_roles, m_oauth2_tokens); } std::unique_ptr get_default_transaction() override { @@ -788,15 +801,17 @@ struct factory : public data_selection::factory { private: std::unique_ptr 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()->required(), "file to load static OSM XML from."); m_user_roles = user_roles; + m_oauth2_tokens = oauth2_tokens; } ~staticxml_backend() override = default; @@ -806,7 +821,7 @@ struct staticxml_backend : public backend { std::unique_ptr create(const po::variables_map &opts) override { std::string file = opts["file"].as(); - return std::make_unique(file, m_user_roles); + return std::make_unique(file, m_user_roles, m_oauth2_tokens); } std::unique_ptr create_data_update(const po::variables_map &) override { @@ -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 make_staticxml_backend(user_roles_t user_roles) { - return std::make_unique(user_roles); +std::unique_ptr make_staticxml_backend(user_roles_t user_roles, oauth2_tokens oauth2_tokens) { + return std::make_unique(user_roles, oauth2_tokens); } diff --git a/test/redactions.testcore/changeset_download_moderator.case b/test/redactions.testcore/changeset_download_moderator.case index 15619b145..d781427cb 100644 --- a/test/redactions.testcore/changeset_download_moderator.case +++ b/test/redactions.testcore/changeset_download_moderator.case @@ -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: --- diff --git a/test/redactions.testcore/node_history_moderator.case b/test/redactions.testcore/node_history_moderator.case index 636ca4fd1..a730cb8fd 100644 --- a/test/redactions.testcore/node_history_moderator.case +++ b/test/redactions.testcore/node_history_moderator.case @@ -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 diff --git a/test/redactions.testcore/node_version_moderator.case b/test/redactions.testcore/node_version_moderator.case index 0b873ac0e..68c9ad492 100644 --- a/test/redactions.testcore/node_version_moderator.case +++ b/test/redactions.testcore/node_version_moderator.case @@ -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 diff --git a/test/redactions.testcore/nodes_moderator.case b/test/redactions.testcore/nodes_moderator.case index 7dc948250..4f1e0eb9a 100644 --- a/test/redactions.testcore/nodes_moderator.case +++ b/test/redactions.testcore/nodes_moderator.case @@ -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 diff --git a/test/redactions.testcore/oauth.json b/test/redactions.testcore/oauth.json deleted file mode 100644 index bef74175e..000000000 --- a/test/redactions.testcore/oauth.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "consumers": { - "heqfjrcolc": "yrpxruiwcq" - }, - "tokens": { - "scgncknxqr": { - "secret": "xvvffpkvrk", - "user_id": 2 - } - } -} diff --git a/test/redactions.testcore/oauth2.json b/test/redactions.testcore/oauth2.json new file mode 100644 index 000000000..4b7adae4a --- /dev/null +++ b/test/redactions.testcore/oauth2.json @@ -0,0 +1,10 @@ +{ + "tokens": { + "1yi2RI2WhIVMLoLaDLg0nrPJPU4WQSIX4Hh_jxfRRxI": { + "expired": false, + "revoked": false, + "api_write": false, + "user_id": 2 + } + } +} diff --git a/test/redactions.testcore/relation_history_moderator.case b/test/redactions.testcore/relation_history_moderator.case index 70494a495..d0e7e53a4 100644 --- a/test/redactions.testcore/relation_history_moderator.case +++ b/test/redactions.testcore/relation_history_moderator.case @@ -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 diff --git a/test/redactions.testcore/relation_version_moderator.case b/test/redactions.testcore/relation_version_moderator.case index 9acb4831b..bda700f82 100644 --- a/test/redactions.testcore/relation_version_moderator.case +++ b/test/redactions.testcore/relation_version_moderator.case @@ -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 diff --git a/test/redactions.testcore/relations_moderator.case b/test/redactions.testcore/relations_moderator.case index 9a546bb69..b00be84f0 100644 --- a/test/redactions.testcore/relations_moderator.case +++ b/test/redactions.testcore/relations_moderator.case @@ -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 diff --git a/test/redactions.testcore/way_history_moderator.case b/test/redactions.testcore/way_history_moderator.case index 54b31be2e..f178681ae 100644 --- a/test/redactions.testcore/way_history_moderator.case +++ b/test/redactions.testcore/way_history_moderator.case @@ -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 diff --git a/test/redactions.testcore/way_version_moderator.case b/test/redactions.testcore/way_version_moderator.case index 6e9238118..cf726ae9d 100644 --- a/test/redactions.testcore/way_version_moderator.case +++ b/test/redactions.testcore/way_version_moderator.case @@ -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 diff --git a/test/redactions.testcore/ways_moderator.case b/test/redactions.testcore/ways_moderator.case index 2292e4054..5c909152e 100644 --- a/test/redactions.testcore/ways_moderator.case +++ b/test/redactions.testcore/ways_moderator.case @@ -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 diff --git a/test/test_core.cpp b/test/test_core.cpp index b5bbcd7d4..7ca60f866 100644 --- a/test/test_core.cpp +++ b/test/test_core.cpp @@ -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"); @@ -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("api_write", false); + detail.expired = entry.second.get("expired", true); + detail.revoked = entry.second.get("revoked", true); + detail.user_id = entry.second.get("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) { @@ -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 test_cases; user_roles_t user_roles; + oauth2_tokens oauth2_tokens; try { if (fs::is_directory(test_directory) == false) { @@ -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; @@ -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;