17#include <rapidjson/document.h>
18#include <rapidjson/writer.h>
40const std::string_view
uriPrefix =
"audacity://link";
47 rapidjson::Document& document, std::string_view grantType, std::string_view
scope)
49 using namespace rapidjson;
52 "grant_type", StringRef(grantType.data(), grantType.size()),
53 document.GetAllocator());
58 "client_id", StringRef(clientID.data(), clientID.size()),
59 document.GetAllocator());
62 "client_secret", StringRef(
"shKqnY2sLTfRK7hztwzNEVxnmhJfOy1i"),
63 document.GetAllocator());
66 "scope", StringRef(
scope.data(),
scope.size()), document.GetAllocator());
69bool IsPrefixed(std::string_view hay, std::string_view prefix)
71 if (hay.length() < prefix.length())
75 prefix.begin(), prefix.end(), hay.begin(),
76 [](
auto a,
auto b) { return a == std::tolower(b); })
77 .first == prefix.end();
83 std::function<
void(std::string_view)> completedHandler)
96 std::string_view uri, std::function<
void(std::string_view)> completedHandler)
100 if (completedHandler)
101 completedHandler({});
107 const auto argsStart = uri.find(
"?");
111 if (completedHandler)
112 completedHandler({});
117 auto args = uri.substr(argsStart + 1);
119 std::string_view token;
120 std::string_view username;
121 std::string_view password;
122 std::string_view authorizationCode;
124 while (!args.empty())
126 const auto nextArg = args.find(
'&');
128 const auto arg = args.substr(0, nextArg);
142 if (!authorizationCode.empty())
147 else if (!token.empty())
152 else if (!username.empty() && !password.empty())
158 std::move(completedHandler));
162 if (completedHandler)
163 completedHandler({});
169 std::lock_guard<std::recursive_mutex> lock(
mMutex);
182 std::string_view password,
183 std::function<
void(std::string_view)> completedHandler)
185 using namespace rapidjson;
188 document.SetObject();
194 document.GetAllocator());
197 "password", StringRef(password.data(), password.size()),
198 document.GetAllocator());
200 rapidjson::StringBuffer buffer;
201 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
202 document.Accept(writer);
205 config, { buffer.GetString(), buffer.GetSize() },
206 std::move(completedHandler));
211 std::function<
void(std::string_view)> completedHandler)
213 using namespace rapidjson;
216 document.SetObject();
221 "refresh_token", StringRef(token.data(), token.size()),
222 document.GetAllocator());
224 rapidjson::StringBuffer buffer;
225 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
226 document.Accept(writer);
229 config, { buffer.GetString(), buffer.GetSize() },
230 std::move(completedHandler));
235 std::function<
void(std::string_view)> completedHandler)
237 std::lock_guard<std::recursive_mutex> lock(
mMutex);
241 std::move(completedHandler));
245 const ServiceConfig& config, std::string_view authorizationCode,
246 std::function<
void(std::string_view)> completedHandler)
248 using namespace rapidjson;
251 document.SetObject();
256 "code", StringRef(authorizationCode.data(), authorizationCode.size()),
257 document.GetAllocator());
262 "redirect_uri", StringRef(redirectURI.data(), redirectURI.size()),
263 document.GetAllocator());
265 rapidjson::StringBuffer buffer;
266 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
267 document.Accept(writer);
270 config, { buffer.GetString(), buffer.GetSize() },
271 std::move(completedHandler));
281 std::lock_guard<std::recursive_mutex> lock(
mMutex);
287 std::lock_guard<std::recursive_mutex> lock(
mMutex);
297 std::function<
void(std::string_view)> completedHandler)
310 request, payload.data(), payload.size());
312 response->setRequestFinishedCallback(
313 [response,
this,
handler = std::move(completedHandler)](
auto)
315 const auto httpCode = response->getHTTPCode();
316 const auto body = response->readAll<std::string>();
332 rapidjson::Document document;
333 document.Parse(body.data(), body.size());
335 if (!document.IsObject())
344 const auto tokenType = document[
"token_type"].GetString();
345 const auto accessToken = document[
"access_token"].GetString();
346 const auto expiresIn = document[
"expires_in"].GetInt64();
347 const auto newRefreshToken = document[
"refresh_token"].GetString();
350 std::lock_guard<std::recursive_mutex> lock(
mMutex);
352 mAccessToken = std::string(tokenType) +
" " + accessToken;
354 Clock::now() + std::chrono::seconds(expiresIn);
358 [token = std::string(newRefreshToken)]()
static AudioUnitEffectsModule::Factory::SubstituteInUnique< AudioUnitEffect > scope
Toolkit-neutral facade for basic user interface services.
Declare functions to perform UTF-8 to std::wstring conversions.
Declare an interface for HTTP response.
Declare a class for performing HTTP requests.
Declare a class for constructing HTTP requests.
Declare a function to decode an URL encode string.
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
CallbackReturn Publish(const AuthStateChangedMessage &message)
Send a message to connected callbacks.
bool Write(const T &value)
Write value to config and return true if successful.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
Specialization of Setting for strings.
Request & setHeader(const std::string &name, std::string value)
Service responsible for OAuth authentication against the audio.com service.
void AuthoriseCode(const ServiceConfig &config, std::string_view authorizationCode, std::function< void(std::string_view)> completedHandler)
std::string GetAccessToken() const
Return the current access token, if any.
void AuthoriseRefreshToken(const ServiceConfig &config, std::string_view refreshToken, std::function< void(std::string_view)> completedHandler)
void DoAuthorise(const ServiceConfig &config, std::string_view payload, std::function< void(std::string_view)> completedHandler)
void UnlinkAccount()
Removes access and refresh token, notifies about the logout.
bool HasRefreshToken() const
void HandleLinkURI(std::string_view uri, std::function< void(std::string_view)> completedHandler)
Handle the OAuth callback.
std::recursive_mutex mMutex
Clock::time_point mTokenExpirationTime
void SafePublish(const AuthStateChangedMessage &message)
void AuthorisePassword(const ServiceConfig &config, std::string_view userName, std::string_view password, std::function< void(std::string_view)> completedHandler)
bool HasAccessToken() const
Indicates, that service has a valid access token, i. e. that the user is authorized.
void ValidateAuth(std::function< void(std::string_view)> completedHandler)
Attempt to authorize the user.
Configuration for the audio.com.
std::string_view GetOAuthRedirectURL() const
OAuth2 redirect URL. Only used to satisfy the protocol.
std::string GetAPIUrl(std::string_view apiURI) const
Helper to construct the full URLs for the API.
std::string_view GetOAuthClientID() const
OAuth2 client ID.
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
constexpr size_t npos(-1)
FrameStatistics & GetInstance() noexcept
const std::string ApplicationJson
std::string ToUTF8(const std::wstring &wstr)
std::string UrlDecode(const std::string &url)
AuthorizationHandler handler
const std::string_view tokenPrefix
const std::string_view uriPrefix
const std::string_view usernamePrefix
StringSetting refreshToken
void WriteCommonFields(rapidjson::Document &document, std::string_view grantType, std::string_view scope)
const std::string_view authorizationCodePrefix
bool IsPrefixed(std::string_view hay, std::string_view prefix)
const std::string_view passwordPrefix
const ServiceConfig & GetServiceConfig()
Returns the instance of the ServiceConfig.
OAuthService & GetOAuthService()
Returns the instance of the OAuthService.
Message that is sent when authorization state changes.