mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
CLOUD: Add OneDrive refresh_token support
It might be not that easy to restart the request after new token received, though.
This commit is contained in:
@@ -38,50 +38,111 @@ namespace OneDrive {
|
||||
Common::String OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth
|
||||
Common::String OneDriveStorage::SECRET; //TODO: hide these secrets somehow
|
||||
|
||||
static void saveAccessTokenCallback(void *ptr) {
|
||||
Common::JSONValue *json = (Common::JSONValue *)ptr;
|
||||
if (json) {
|
||||
debug("saveAccessTokenCallback:");
|
||||
debug("%s", json->stringify(true).c_str());
|
||||
OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId, Common::String refreshToken):
|
||||
_token(accessToken), _uid(userId), _refreshToken(refreshToken) {}
|
||||
|
||||
//TODO: do something about refresh token
|
||||
Common::JSONObject result = json->asObject();
|
||||
if (!result.contains("access_token") || !result.contains("user_id")) {
|
||||
warning("Bad response, no token/user_id passed");
|
||||
} else {
|
||||
OneDriveStorage::addStorage(result.getVal("access_token")->asString(), result.getVal("user_id")->asString());
|
||||
ConfMan.removeKey("onedrive_code", "cloud");
|
||||
debug("Done! You can use OneDrive now! Look:");
|
||||
g_system->getCloudManager()->syncSaves();
|
||||
}
|
||||
OneDriveStorage::OneDriveStorage(Common::String code) {
|
||||
getAccessToken(new Common::Callback<OneDriveStorage, bool>(this, &OneDriveStorage::codeFlowComplete), code);
|
||||
}
|
||||
|
||||
delete json;
|
||||
} else {
|
||||
debug("saveAccessTokenCallback: got NULL instead of JSON!");
|
||||
OneDriveStorage::~OneDriveStorage() {}
|
||||
|
||||
void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) {
|
||||
bool codeFlow = (code != "");
|
||||
|
||||
if (!codeFlow && _refreshToken == "") {
|
||||
warning("OneDriveStorage: no refresh token available to get new access token.");
|
||||
if (callback) (*callback)(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Common::BaseCallback<> *innerCallback = new Common::CallbackBridge<OneDriveStorage, bool>(this, &OneDriveStorage::tokenRefreshed, callback);
|
||||
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf");
|
||||
if (codeFlow) {
|
||||
request->addPostField("code=" + code);
|
||||
request->addPostField("grant_type=authorization_code");
|
||||
} else {
|
||||
request->addPostField("refresh_token=" + _refreshToken);
|
||||
request->addPostField("grant_type=refresh_token");
|
||||
}
|
||||
request->addPostField("client_id=" + KEY);
|
||||
request->addPostField("client_secret=" + SECRET);
|
||||
request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F");
|
||||
ConnMan.addRequest(request);
|
||||
}
|
||||
|
||||
OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
void OneDriveStorage::tokenRefreshed(BoolCallback callback, void *jsonPointer) {
|
||||
Common::JSONValue *json = (Common::JSONValue *)jsonPointer;
|
||||
if (!json) {
|
||||
warning("OneDriveStorage: got NULL instead of JSON");
|
||||
if (callback) (*callback)(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Common::JSONObject result = json->asObject();
|
||||
if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) {
|
||||
warning("Bad response, no token or user_id passed");
|
||||
debug("%s", json->stringify().c_str());
|
||||
if (callback) (*callback)(false);
|
||||
} else {
|
||||
_token = result.getVal("access_token")->asString();
|
||||
_uid = result.getVal("user_id")->asString();
|
||||
_refreshToken = result.getVal("refresh_token")->asString();
|
||||
g_system->getCloudManager()->save(); //ask CloudManager to save our new refreshToken
|
||||
if (callback) (*callback)(true);
|
||||
}
|
||||
delete json;
|
||||
}
|
||||
|
||||
OneDriveStorage::~OneDriveStorage() {
|
||||
curl_global_cleanup();
|
||||
void OneDriveStorage::codeFlowComplete(bool success) {
|
||||
if (!success) {
|
||||
warning("OneDriveStorage: failed to get access token through code flow");
|
||||
return;
|
||||
}
|
||||
|
||||
g_system->getCloudManager()->addStorage(this);
|
||||
ConfMan.removeKey("onedrive_code", "cloud");
|
||||
debug("Done! You can use OneDrive now! Look:");
|
||||
g_system->getCloudManager()->syncSaves();
|
||||
}
|
||||
|
||||
void OneDriveStorage::saveConfig(Common::String keyPrefix) {
|
||||
ConfMan.set(keyPrefix + "type", "OneDrive", "cloud");
|
||||
ConfMan.set(keyPrefix + "access_token", _token, "cloud");
|
||||
ConfMan.set(keyPrefix + "user_id", _uid, "cloud");
|
||||
ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud");
|
||||
}
|
||||
|
||||
void OneDriveStorage::printJsonTokenReceived(bool success) {
|
||||
if (success) syncSaves(0); //try again
|
||||
}
|
||||
|
||||
void OneDriveStorage::printJson(void *jsonPointer) {
|
||||
Common::JSONValue *json = (Common::JSONValue *)jsonPointer;
|
||||
if (!json) {
|
||||
warning("printJson: NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
Common::JSONObject result = json->asObject();
|
||||
if (result.contains("error")) {
|
||||
//Common::JSONObject error = result.getVal("error")->asObject();
|
||||
debug("bad token, trying again...");
|
||||
getAccessToken(new Common::Callback<OneDriveStorage, bool>(this, &OneDriveStorage::printJsonTokenReceived));
|
||||
delete json;
|
||||
return;
|
||||
}
|
||||
|
||||
debug("%s", json->stringify().c_str());
|
||||
delete json;
|
||||
}
|
||||
|
||||
void OneDriveStorage::syncSaves(BoolCallback callback) {
|
||||
//this is not the real syncSaves() implementation
|
||||
}
|
||||
|
||||
void OneDriveStorage::addStorage(Common::String token, Common::String uid) {
|
||||
Storage *storage = new OneDriveStorage(token, uid);
|
||||
g_system->getCloudManager()->addStorage(storage);
|
||||
//this is not the real syncSaves() implementation
|
||||
Common::BaseCallback<> *innerCallback = new Common::Callback<OneDriveStorage>(this, &OneDriveStorage::printJson);
|
||||
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/");
|
||||
request->addHeader("Authorization: bearer " + _token);
|
||||
ConnMan.addRequest(request);
|
||||
}
|
||||
|
||||
OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {
|
||||
@@ -98,9 +159,15 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ConfMan.hasKey(keyPrefix + "refresh_token", "cloud")) {
|
||||
warning("No refresh_token found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud");
|
||||
Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud");
|
||||
return new OneDriveStorage(accessToken, userId);
|
||||
Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", "cloud");
|
||||
return new OneDriveStorage(accessToken, userId, refreshToken);
|
||||
}
|
||||
|
||||
Common::String OneDriveStorage::getAuthLink() {
|
||||
@@ -109,7 +176,7 @@ Common::String OneDriveStorage::getAuthLink() {
|
||||
url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting
|
||||
//url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening
|
||||
url += "&client_id=" + KEY;
|
||||
url += "&scope=onedrive.appfolder"; //TODO
|
||||
url += "&scope=onedrive.appfolder%20offline_access"; //TODO
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -124,7 +191,7 @@ void OneDriveStorage::authThroughConsole() {
|
||||
|
||||
if (ConfMan.hasKey("onedrive_code", "cloud")) {
|
||||
//phase 2: get access_token using specified code
|
||||
getAccessToken(ConfMan.get("onedrive_code", "cloud"));
|
||||
new OneDriveStorage(ConfMan.get("onedrive_code", "cloud"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -135,17 +202,5 @@ void OneDriveStorage::authThroughConsole() {
|
||||
debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n");
|
||||
}
|
||||
|
||||
void OneDriveStorage::getAccessToken(Common::String code) {
|
||||
Common::BaseCallback<> *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback);
|
||||
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://login.live.com/oauth20_token.srf");
|
||||
//Content-Type: application/x-www-form-urlencoded
|
||||
request->addPostField("code=" + code);
|
||||
request->addPostField("grant_type=authorization_code");
|
||||
request->addPostField("client_id=" + KEY);
|
||||
request->addPostField("client_secret=" + SECRET);
|
||||
request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F");
|
||||
ConnMan.addRequest(request);
|
||||
}
|
||||
|
||||
} //end of namespace OneDrive
|
||||
} //end of namespace Cloud
|
||||
|
||||
@@ -32,13 +32,28 @@ namespace OneDrive {
|
||||
class OneDriveStorage: public Cloud::Storage {
|
||||
static Common::String KEY, SECRET;
|
||||
|
||||
Common::String _token, _uid;
|
||||
Common::String _token, _uid, _refreshToken;
|
||||
|
||||
/** This private constructor is called from loadFromConfig(). */
|
||||
OneDriveStorage(Common::String token, Common::String uid);
|
||||
OneDriveStorage(Common::String token, Common::String uid, Common::String refreshToken);
|
||||
|
||||
static void getAccessToken(Common::String code);
|
||||
/**
|
||||
* This private constructor is called from authThroughConsole() (phase 2).
|
||||
* It uses OAuth code flow to get tokens.
|
||||
*/
|
||||
OneDriveStorage(Common::String code);
|
||||
|
||||
/**
|
||||
* Gets new access_token. If <code> passed is "", refresh_token is used.
|
||||
* Use "" in order to refresh token and pass a callback, so you could
|
||||
* continue your work when new token is available.
|
||||
*/
|
||||
void getAccessToken(BoolCallback callback, Common::String code = "");
|
||||
void tokenRefreshed(BoolCallback callback, void *jsonPointer);
|
||||
void codeFlowComplete(bool success);
|
||||
|
||||
void printJson(void *jsonPointer);
|
||||
void printJsonTokenReceived(bool success);
|
||||
public:
|
||||
virtual ~OneDriveStorage();
|
||||
|
||||
@@ -91,11 +106,6 @@ public:
|
||||
/** Returns whether there are any requests running. */
|
||||
virtual bool isWorking() { return false; } //TODO
|
||||
|
||||
/**
|
||||
* Add OneDriveStorage with given token and uid into Cloud::Manager.
|
||||
*/
|
||||
static void addStorage(Common::String token, Common::String uid);
|
||||
|
||||
/**
|
||||
* Load token and user id from configs and return OneDriveStorage for those.
|
||||
* @return pointer to the newly created OneDriveStorage or 0 if some problem occured.
|
||||
|
||||
@@ -46,8 +46,10 @@ NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, C
|
||||
curl_easy_setopt(_easy, CURLOPT_URL, url);
|
||||
curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L);
|
||||
curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList);
|
||||
curl_easy_setopt(_easy, CURLOPT_POSTFIELDSIZE, postFields.size());
|
||||
curl_easy_setopt(_easy, CURLOPT_COPYPOSTFIELDS, postFields.c_str());
|
||||
if (postFields.size() != 0) {
|
||||
curl_easy_setopt(_easy, CURLOPT_POSTFIELDSIZE, postFields.size());
|
||||
curl_easy_setopt(_easy, CURLOPT_COPYPOSTFIELDS, postFields.c_str());
|
||||
}
|
||||
ConnMan.registerEasyHandle(_easy);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user