17#include <rapidjson/document.h>
18#include <rapidjson/writer.h>
43const std::string_view
uriPrefix =
"audacity://link";
50 rapidjson::Document& document, std::string_view grantType, std::string_view
scope)
52 using namespace rapidjson;
55 "grant_type", StringRef(grantType.data(), grantType.size()),
56 document.GetAllocator());
63 Value(clientID.data(), clientID.size(), document.GetAllocator()),
64 document.GetAllocator());
68 Value(clientSecret.data(), clientSecret.size(), document.GetAllocator()),
69 document.GetAllocator());
72 "scope", StringRef(
scope.data(),
scope.size()), document.GetAllocator());
78 std::function<
void(std::string_view)> completedHandler,
AudiocomTrace trace,
94 std::function<
void(std::string_view)> completedHandler)
105 const auto argsStart = uri.find(
"?");
109 if (completedHandler)
110 completedHandler({});
115 auto args = uri.substr(argsStart + 1);
117 std::string_view token;
118 std::string_view username;
119 std::string_view password;
120 std::string_view authorizationCode;
122 while (!args.empty())
124 const auto nextArg = args.find(
'&');
126 const auto arg = args.substr(0, nextArg);
140 if (!authorizationCode.empty())
144 std::move(completedHandler));
146 else if (!token.empty())
151 else if (!username.empty() && !password.empty())
156 std::move(completedHandler));
160 if (completedHandler)
161 completedHandler({});
171 std::lock_guard<std::recursive_mutex> lock(
mMutex);
179 Publish({ {}, {}, trace,
false });
185 std::function<
void(std::string_view)> completedHandler)
187 using namespace rapidjson;
190 document.SetObject();
196 document.GetAllocator());
199 "password", StringRef(password.data(), password.size()),
200 document.GetAllocator());
202 rapidjson::StringBuffer buffer;
203 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
204 document.Accept(writer);
207 config, { buffer.GetString(), buffer.GetSize() }, trace,
208 std::move(completedHandler),
false);
213 std::function<
void(std::string_view)> completedHandler,
bool silent)
215 using namespace rapidjson;
218 document.SetObject();
223 "refresh_token", StringRef(token.data(), token.size()),
224 document.GetAllocator());
226 rapidjson::StringBuffer buffer;
227 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
228 document.Accept(writer);
231 config, { buffer.GetString(), buffer.GetSize() }, trace,
232 std::move(completedHandler), silent);
237 std::function<
void(std::string_view)> completedHandler,
bool silent)
239 std::lock_guard<std::recursive_mutex> lock(
mMutex);
243 std::move(completedHandler), silent);
247 const ServiceConfig& config, std::string_view authorizationCode,
248 AudiocomTrace trace, std::function<
void(std::string_view)> completedHandler)
250 using namespace rapidjson;
253 document.SetObject();
258 "code", StringRef(authorizationCode.data(), authorizationCode.size()),
259 document.GetAllocator());
264 "redirect_uri", StringRef(redirectURI.data(), redirectURI.size()),
265 document.GetAllocator());
267 rapidjson::StringBuffer buffer;
268 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
269 document.Accept(writer);
272 config, { buffer.GetString(), buffer.GetSize() }, trace,
273 std::move(completedHandler),
false);
283 std::lock_guard<std::recursive_mutex> lock(
mMutex);
289 std::lock_guard<std::recursive_mutex> lock(
mMutex);
299 std::function<
void(std::string_view)> completedHandler,
bool silent)
312 request, payload.data(), payload.size());
314 response->setRequestFinishedCallback(
315 [response,
this,
handler = std::move(completedHandler), silent,
317 const auto httpCode = response->getHTTPCode();
318 const auto body = response->readAll<std::string>();
334 rapidjson::Document document;
335 document.Parse(body.data(), body.size());
337 if (!document.IsObject())
346 const auto tokenType = document[
"token_type"].GetString();
347 const auto accessToken = document[
"access_token"].GetString();
348 const auto expiresIn = document[
"expires_in"].GetInt64();
349 const auto newRefreshToken = document[
"refresh_token"].GetString();
352 std::lock_guard<std::recursive_mutex> lock(
mMutex);
354 mAccessToken = std::string(tokenType) +
" " + accessToken;
356 Clock::now() + std::chrono::seconds(expiresIn);
360 [token = std::string(newRefreshToken)]()
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.
audacity::BasicSettings * gPrefs
Declare a class for constructing HTTP requests.
bool IsPrefixedInsensitive(const HayType &hay, const PrefixType &prefix)
bool IsPrefixed(const HayType &hay, const PrefixType &prefix)
Declare a function to decode an URL encode string.
CallbackReturn Publish(const AuthStateChangedMessage &message)
Send a message to connected callbacks.
Allows custom logic for preferences reset event.
bool Write(const T &value)
Write value to config and return true if successful.
void Invalidate() override
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.
virtual bool Flush() noexcept=0
Service responsible for OAuth authentication against the audio.com service.
bool HandleLinkURI(std::string_view uri, AudiocomTrace, std::function< void(std::string_view)> completedHandler)
Handle the OAuth callback.
bool HasRefreshToken() const
void AuthoriseRefreshToken(const ServiceConfig &config, std::string_view refreshToken, AudiocomTrace, std::function< void(std::string_view)> completedHandler, bool silent)
void SafePublish(const AuthStateChangedMessage &message)
void DoAuthorise(const ServiceConfig &config, std::string_view payload, AudiocomTrace, std::function< void(std::string_view)> completedHandler, bool silent)
void ValidateAuth(std::function< void(std::string_view)> completedHandler, AudiocomTrace, bool silent)
Attempt to authorize the user.
void AuthorisePassword(const ServiceConfig &config, std::string_view userName, std::string_view password, AudiocomTrace, std::function< void(std::string_view)> completedHandler)
void UnlinkAccount(AudiocomTrace)
Removes access and refresh token, notifies about the logout.
void AuthoriseCode(const ServiceConfig &config, std::string_view authorizationCode, AudiocomTrace, std::function< void(std::string_view)> completedHandler)
Clock::time_point mTokenExpirationTime
bool HasAccessToken() const
Indicates, that service has a valid access token, i. e. that the user is authorized.
std::recursive_mutex mMutex
std::string GetAccessToken() const
Return the current access token, if any.
Configuration for the audio.com.
std::string GetOAuthRedirectURL() const
OAuth2 redirect URL. Only used to satisfy the protocol.
std::string GetOAuthClientSecret() const
OAuth2 client secret.
std::string GetAPIUrl(std::string_view apiURI) const
Helper to construct the full URLs for the API.
std::string GetOAuthClientID() const
OAuth2 client ID.
void OnSettingResetBegin() override
Happens before preferences reset.
void OnSettingResetEnd() override
Happens after preferences reset.
static NetworkManager & GetInstance()
ResponsePtr doPost(const Request &request, const void *data, size_t size)
Request & setHeader(const std::string &name, std::string value)
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
constexpr size_t npos(-1)
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
AuthorizationHandler handler
static PreferencesResetHandler::Registration< OAuthServiceSettingsResetHandler > resetHandler
const std::string_view usernamePrefix
const std::string_view passwordPrefix
StringSetting refreshToken
const std::string_view tokenPrefix
const std::string_view authorizationCodePrefix
const std::string_view uriPrefix
void WriteCommonFields(rapidjson::Document &document, std::string_view grantType, std::string_view scope)
OAuthService & GetOAuthService()
Returns the instance of the OAuthService.
const ServiceConfig & GetServiceConfig()
Returns the instance of the ServiceConfig.
const std::string ApplicationJson
std::string ToUTF8(const std::wstring &wstr)
std::string UrlDecode(const std::string &url)
Performs single-time global handler registration.
Message that is sent when authorization state changes.