From d99ba765aa42d87fd3fa8ba6fdb45b6455f665f7 Mon Sep 17 00:00:00 2001 From: keita Date: Sat, 23 Apr 2022 18:00:41 +0900 Subject: [PATCH] =?UTF-8?q?basic=E8=AA=8D=E8=A8=BC=E7=94=A8=E3=81=AE?= =?UTF-8?q?=E3=83=97=E3=83=AD=E3=83=90=E3=82=A4=E3=83=80=E3=81=A8=E3=83=99?= =?UTF-8?q?=E3=82=A2=E3=83=A9=E3=83=88=E3=83=BC=E3=82=AF=E3=83=B3=E3=82=92?= =?UTF-8?q?=E5=8F=96=E5=BE=97=E3=81=99=E3=82=8B=E3=81=9F=E3=82=81=E3=81=AE?= =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=83=89=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=BB=E3=82=B9=E3=82=92=E6=9C=89=E5=8A=B9?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cocoatweet/api/api.cc | 10 ++- src/cocoatweet/api/api.h | 3 + src/cocoatweet/api/interface/httpGet.cc | 6 ++ src/cocoatweet/api/interface/httpPost.cc | 6 ++ src/cocoatweet/api/oauth2/oauth2.cc | 16 ++++ src/cocoatweet/api/oauth2/oauth2.h | 26 +++++++ src/cocoatweet/api/oauth2/token.cc | 25 ++++++ src/cocoatweet/api/oauth2/token.h | 15 ++++ src/cocoatweet/authentication/authenticate.cc | 62 --------------- src/cocoatweet/authentication/authenticator.h | 1 + src/cocoatweet/authentication/basic.cc | 77 +++++++++++++++++++ src/cocoatweet/authentication/basic.h | 25 ++++++ src/cocoatweet/authentication/bearer.cc | 44 +++++++++++ src/cocoatweet/authentication/bearer.h | 22 ++++++ src/cocoatweet/authentication/key.h | 5 +- .../exception/credentialNotAllowedException.h | 12 +++ .../exception/missingRequiredParamException.h | 12 +++ 17 files changed, 300 insertions(+), 67 deletions(-) create mode 100644 src/cocoatweet/authentication/basic.cc create mode 100644 src/cocoatweet/authentication/basic.h create mode 100644 src/cocoatweet/exception/credentialNotAllowedException.h create mode 100644 src/cocoatweet/exception/missingRequiredParamException.h diff --git a/src/cocoatweet/api/api.cc b/src/cocoatweet/api/api.cc index 9a5bdcb..93aebd3 100644 --- a/src/cocoatweet/api/api.cc +++ b/src/cocoatweet/api/api.cc @@ -1,5 +1,7 @@ #include #include +#include +#include #include @@ -12,8 +14,8 @@ API::API(CocoaTweet::Authentication::Key _key) { void API::swapKey(const CocoaTweet::Authentication::Key _key){ if(_key.authType() == CocoaTweet::Authentication::Key::OAUTH10A){ oauth_ = std::make_shared(_key); - }else{ - + }else if(_key.authType() == CocoaTweet::Authentication::Key::OAUTH2){ + oauth_ = std::make_shared(_key); } user_ = Users::User(oauth_); status_ = Statuses::Status(oauth_); @@ -21,6 +23,7 @@ void API::swapKey(const CocoaTweet::Authentication::Key _key){ media_ = Medias::Media(oauth_); directMessage_ = DirectMessages::DirectMessage(oauth_); oauth1_ = OAuth1::OAuth(oauth_); + oauth2_ = OAuth2::OAuth2(oauth_); } // const std::string& API::generateBearerToken() const { @@ -49,4 +52,7 @@ DirectMessages::DirectMessage API::directMessage() const { OAuth1::OAuth API::oauth1() const { return oauth1_; } +OAuth2::OAuth2 API::oauth2() const { + return oauth2_; +} } // namespace CocoaTweet::API diff --git a/src/cocoatweet/api/api.h b/src/cocoatweet/api/api.h index 2a23787..85b5c02 100644 --- a/src/cocoatweet/api/api.h +++ b/src/cocoatweet/api/api.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace CocoaTweet::API { /// @brief Twitter API Entry Point @@ -32,6 +33,7 @@ public: DirectMessages::DirectMessage directMessage() const; OAuth1::OAuth oauth1() const; + OAuth2::OAuth2 oauth2() const; const std::string& generateBearerToken() const; void swapKey(const CocoaTweet::Authentication::Key _key); @@ -43,6 +45,7 @@ private: Medias::Media media_; DirectMessages::DirectMessage directMessage_; OAuth1::OAuth oauth1_; + OAuth2::OAuth2 oauth2_; std::shared_ptr oauth_; }; } // namespace CocoaTweet::API diff --git a/src/cocoatweet/api/interface/httpGet.cc b/src/cocoatweet/api/interface/httpGet.cc index bdab573..9ac4ffe 100644 --- a/src/cocoatweet/api/interface/httpGet.cc +++ b/src/cocoatweet/api/interface/httpGet.cc @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "nlohmann/json.hpp" #include #include @@ -128,6 +130,10 @@ void HttpGet::process(std::weak_ptr().c_str()); } else if (error.get() == 186) { throw CocoaTweet::Exception::TweetTooLongException(message.get().c_str()); + }else if(error.get() == 170){ + throw CocoaTweet::Exception::MissingRequiredParamException(message.get().c_str()); + }else if(error.get() == 220){ + throw CocoaTweet::Exception::CredentialNotAllowedException(message.get().c_str()); } else { } } diff --git a/src/cocoatweet/api/interface/httpPost.cc b/src/cocoatweet/api/interface/httpPost.cc index 3d2a36e..56104ab 100644 --- a/src/cocoatweet/api/interface/httpPost.cc +++ b/src/cocoatweet/api/interface/httpPost.cc @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "nlohmann/json.hpp" #include #include @@ -146,6 +148,10 @@ void HttpPost::process(std::weak_ptr().c_str()); } else if (error.get() == 186) { throw CocoaTweet::Exception::TweetTooLongException(message.get().c_str()); + }else if(error.get() == 170){ + throw CocoaTweet::Exception::MissingRequiredParamException(message.get().c_str()); + }else if(error.get() == 220){ + throw CocoaTweet::Exception::CredentialNotAllowedException(message.get().c_str()); } } diff --git a/src/cocoatweet/api/oauth2/oauth2.cc b/src/cocoatweet/api/oauth2/oauth2.cc index e69de29..1313f93 100644 --- a/src/cocoatweet/api/oauth2/oauth2.cc +++ b/src/cocoatweet/api/oauth2/oauth2.cc @@ -0,0 +1,16 @@ +#include +#include + +namespace CocoaTweet::API::OAuth2 { + OAuth2::OAuth2(std::shared_ptr _oauth){ + oauth_ = _oauth; + } + + const std::string OAuth2::token() const{ + auto key = oauth_.lock()->key(); + auto oauth = std::make_shared(key); + + CocoaTweet::API::OAuth2::Token token; + return token.process(oauth); + } +} // namespace CocoaTweet::API::Statuses diff --git a/src/cocoatweet/api/oauth2/oauth2.h b/src/cocoatweet/api/oauth2/oauth2.h index e69de29..fb497cf 100644 --- a/src/cocoatweet/api/oauth2/oauth2.h +++ b/src/cocoatweet/api/oauth2/oauth2.h @@ -0,0 +1,26 @@ +#ifndef COCOATWEET_API_OAUTH2_OAUTH2_H_ +#define COCOATWEET_API_OAUTH2_OAUTH2_H_ + +#include "cocoatweet/api/interface/groupInterface.h" +#include +#include +#include +#include + +namespace CocoaTweet::API::OAuth2 { +/// @brief class for using users/show endpoint +class OAuth2 : public groupInterface { +public: + /// @brief primary constructor + OAuth2() = default; + + /// @brief constructor which finally should to be called. + /// @param[in] std::shared_ptr : pointer to OAuth object + OAuth2(std::shared_ptr _oauth); + + const std::string token() const; + +}; +} // namespace CocoaTweet::API::Statuses + +#endif diff --git a/src/cocoatweet/api/oauth2/token.cc b/src/cocoatweet/api/oauth2/token.cc index e69de29..42bac58 100644 --- a/src/cocoatweet/api/oauth2/token.cc +++ b/src/cocoatweet/api/oauth2/token.cc @@ -0,0 +1,25 @@ +#include +#include "nlohmann/json.hpp" + + +namespace CocoaTweet::API::OAuth2{ + Token::Token(){ + contentType_ = "application/x-www-form-urlencoded"; + url_ = "https://api.twitter.com/oauth2/token"; + + bodyParam_.insert_or_assign("grant_type", "client_credentials"); + } + + + +const std::string Token::process(std::weak_ptr _oauth) { + auto basic = std::make_shared(_oauth.lock()->key()); + std::string bearer = ""; + HttpPost::process(basic, [&bearer](const std::string& _rcv) { + auto j = nlohmann::json::parse(_rcv); + bearer = j["access_token"]; + }); + return bearer; +} + +} \ No newline at end of file diff --git a/src/cocoatweet/api/oauth2/token.h b/src/cocoatweet/api/oauth2/token.h index e69de29..3a9ae76 100644 --- a/src/cocoatweet/api/oauth2/token.h +++ b/src/cocoatweet/api/oauth2/token.h @@ -0,0 +1,15 @@ +#ifndef COCOATWEET_API_OAUTH2_TOKEN_H +#define COCOATWEET_API_OAUTH2_TOKEN_H + +#include +#include + +namespace CocoaTweet::API::OAuth2{ + class Token: public CocoaTweet::API::Interface::HttpPost{ + public: + Token(); + const std::string process(std::weak_ptr _oauth); + }; +} + +#endif \ No newline at end of file diff --git a/src/cocoatweet/authentication/authenticate.cc b/src/cocoatweet/authentication/authenticate.cc index d748458..0239127 100644 --- a/src/cocoatweet/authentication/authenticate.cc +++ b/src/cocoatweet/authentication/authenticate.cc @@ -78,68 +78,6 @@ const std::string OAuth1::calculateAuthHeader(std::map return oauthHeader; } - -// const std::string& OAuth1::generateBearerToken() { -// auto signature = key_.consumerKey() + ":" + key_.consumerSecret(); -// auto k64Signature = base64(signature); -// auto authHeader = std::string("Authorization: Basic ") + k64Signature; -// auto contentType = -// std::string("Content-Type: application/x-www-form-urlencoded;charset=UTF-8"); -// auto url = std::string("https://api.twitter.com/oauth2/token"); -// auto requestBody = std::string("grant_type=client_credentials"); - -// // do post -// CURL* curl; -// CURLcode res; -// std::string rcv; -// long responseCode; -// curl = curl_easy_init(); -// if (curl) { -// curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); -// curl_easy_setopt(curl, CURLOPT_POST, 1); -// curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestBody.c_str()); -// curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, requestBody.length()); -// curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); -// curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlCallback_); -// curl_easy_setopt(curl, CURLOPT_WRITEDATA, (std::string*)&rcv); -// #ifndef NDEBUG -// std::cout << "requestBody : " << requestBody << std::endl; -// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); -// #endif -// // Headerを保持するcurl_slist*を初期化 -// struct curl_slist* headers = NULL; -// // Authorizationをヘッダに追加 -// headers = curl_slist_append(headers, authHeader.c_str()); -// headers = curl_slist_append(headers, contentType.c_str()); -// curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); -// res = curl_easy_perform(curl); -// curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); -// curl_easy_cleanup(curl); -// } -// if (res != CURLE_OK) { -// throw std::runtime_error(std::string("INTERNAL ERROR : curl(") + std::to_string(res) + ")"); -// exit(1); -// } - -// auto j = nlohmann::json::parse(rcv); -// if ((responseCode / 100) == 4) { -// auto error = j["errors"][0]["code"]; -// auto message = j["errors"][0]["message"]; -// if (j.count("error") != 0) { -// // この形式はエラーコードを持たないのでエラー種別が特定できない -// throw new CocoaTweet::Exception::Exception(j["error"]); -// } -// if (error.get() == 44) { -// throw CocoaTweet::Exception::InvalidParameterException( -// message.get().c_str()); -// } -// } - -// key_.bearerToken(j["access_token"]); -// authType_ = AuthType::Bearer; -// return key_.bearerToken(); -// } - const std::string OAuth1::nonce() const { std::random_device engine; std::string nonceTable = "abcdefghijklmnopqrstuvwxyz0123456789"; diff --git a/src/cocoatweet/authentication/authenticator.h b/src/cocoatweet/authentication/authenticator.h index 91b00dc..3581e0d 100644 --- a/src/cocoatweet/authentication/authenticator.h +++ b/src/cocoatweet/authentication/authenticator.h @@ -8,6 +8,7 @@ public: enum class AuthenticationMethod{ OAUTH10A, OAUTH2, + BASIC, PLAIN, NONE }; diff --git a/src/cocoatweet/authentication/basic.cc b/src/cocoatweet/authentication/basic.cc new file mode 100644 index 0000000..357aa0e --- /dev/null +++ b/src/cocoatweet/authentication/basic.cc @@ -0,0 +1,77 @@ +#include "basic.h" +#include "cocoatweet/util/util.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { +#include +#include +#include +#include +} + +#ifndef NDEBUG +#include +#endif + +namespace CocoaTweet::Authentication { +Basic::Basic() { + method_ = AuthenticationMethod::BASIC; +} + +Basic::Basic(const Key _key){ + key_ = _key; + method_ = AuthenticationMethod::BASIC; +} +const std::string Basic::calculateAuthHeader(std::map _bodyParam, + const std::string& _method, + const std::string& _url) { + + auto signature = key_.consumerKey() + ":" + key_.consumerSecret(); + auto k64Signature = base64(signature); + auto authHeader = std::string("Authorization: Basic ") + k64Signature; + + return authHeader; + +} + +const std::string Basic::base64(const std::string& _raw) { + auto base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::stringstream ss; + for (auto r : _raw) { + ss << std::bitset<8>(r); + } + + if (_raw.length() % 3 == 1) { + ss << "0000"; + } else if (_raw.length() % 3 == 2) { + ss << "00"; + } + + auto bin = ss.str(); + std::string base64 = ""; + for (auto i = 0; i < bin.length() / 6; i++) { + base64 += base64Table[std::stoi(bin.substr(i * 6, 6), nullptr, 2)]; + } + + if (base64.length() % 4 == 3) { + base64 += "="; + } else if (base64.length() % 4 == 2) { + base64 += "=="; + } else if (base64.length() % 4 == 1) { + base64 += "==="; + } + + return base64; +} + + +} // namespace CocoaTweet::Authentication diff --git a/src/cocoatweet/authentication/basic.h b/src/cocoatweet/authentication/basic.h new file mode 100644 index 0000000..1ac8f88 --- /dev/null +++ b/src/cocoatweet/authentication/basic.h @@ -0,0 +1,25 @@ +#ifndef COCOATWEET_AUTHENTICATION_BASIC_H_ +#define COCOATWEET_AUTHENTICATION_BASIC_H_ + +#include +#include +#include +#include "key.h" +#include + +namespace CocoaTweet::Authentication { +class Basic: public AuthenticatorBase { +public: + Basic(); + Basic(const Key _key); + + // const std::string& generateBearerToken(); + + const std::string calculateAuthHeader(std::map _bodyParam, + const std::string& _method, const std::string& _url); + const std::string base64(const std::string& _raw); + +}; +} // namespace CocoaTweet::Authentication + +#endif diff --git a/src/cocoatweet/authentication/bearer.cc b/src/cocoatweet/authentication/bearer.cc index e69de29..e52f227 100644 --- a/src/cocoatweet/authentication/bearer.cc +++ b/src/cocoatweet/authentication/bearer.cc @@ -0,0 +1,44 @@ +#include "bearer.h" +#include "cocoatweet/util/util.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { +#include +#include +#include +#include +} + +#ifndef NDEBUG +#include +#endif + +namespace CocoaTweet::Authentication { +Bearer::Bearer() { + method_ = AuthenticationMethod::OAUTH2; +} + +Bearer::Bearer(const Key _key){ + key_ = _key; + method_ = AuthenticationMethod::OAUTH2; +} +const std::string Bearer::calculateAuthHeader(std::map _bodyParam, + const std::string& _method, + const std::string& _url) { + + auto authHeader = std::string("Authorization: Bearer ") + key_.bearerToken(); + + return authHeader; + +} + +} // namespace CocoaTweet::Authentication diff --git a/src/cocoatweet/authentication/bearer.h b/src/cocoatweet/authentication/bearer.h index e69de29..ab7285f 100644 --- a/src/cocoatweet/authentication/bearer.h +++ b/src/cocoatweet/authentication/bearer.h @@ -0,0 +1,22 @@ +#ifndef COCOATWEET_AUTHENTICATION_BEARER_H_ +#define COCOATWEET_AUTHENTICATION_BEARER_H_ + +#include +#include +#include +#include "key.h" +#include + +namespace CocoaTweet::Authentication { +class Bearer: public AuthenticatorBase { +public: + Bearer(); + Bearer(const Key _key); + + + const std::string calculateAuthHeader(std::map _bodyParam, + const std::string& _method, const std::string& _url); +}; +} // namespace CocoaTweet::Authentication + +#endif diff --git a/src/cocoatweet/authentication/key.h b/src/cocoatweet/authentication/key.h index ef9e9ea..8d75b92 100644 --- a/src/cocoatweet/authentication/key.h +++ b/src/cocoatweet/authentication/key.h @@ -9,8 +9,7 @@ class Key { public: enum AUTH_TYPE{ OAUTH10A, - OAUTH2, - PLAIN + OAUTH2 }; private: @@ -70,7 +69,7 @@ public: const AUTH_TYPE authType() const { return authType_; } - + void authType(AUTH_TYPE _authType) { authType_ = _authType; } diff --git a/src/cocoatweet/exception/credentialNotAllowedException.h b/src/cocoatweet/exception/credentialNotAllowedException.h new file mode 100644 index 0000000..aabf8c7 --- /dev/null +++ b/src/cocoatweet/exception/credentialNotAllowedException.h @@ -0,0 +1,12 @@ +#ifndef COCOATWEET_EXCEPTION_CREDETIALNOTALLOWEDEXCEPTION_H_ +#define COCOATWEET_EXCEPTION_CREDETIALNOTALLOWEDEXCEPTION_H_ + +#include + +namespace CocoaTweet::Exception { +class CredentialNotAllowedException final : public Exception { + using Exception::Exception; +}; +} // namespace CocoaTweet::Exception + +#endif diff --git a/src/cocoatweet/exception/missingRequiredParamException.h b/src/cocoatweet/exception/missingRequiredParamException.h new file mode 100644 index 0000000..a2fffc8 --- /dev/null +++ b/src/cocoatweet/exception/missingRequiredParamException.h @@ -0,0 +1,12 @@ +#ifndef COCOATWEET_EXCEPTION_MISSINGREQUIREDPARAMEXCEPTION_H_ +#define COCOATWEET_EXCEPTION_MISSINGREQUIREDPARAMEXCEPTION_H_ + +#include + +namespace CocoaTweet::Exception { +class MissingRequiredParamException final : public Exception { + using Exception::Exception; +}; +} // namespace CocoaTweet::Exception + +#endif