[gnome-maps/wip/osm-edit: 3/3] osmEdit: WIP, implement OAuth-autorized calls for updating



commit 0885a60719bb844b7ffa7c16b8b3b7b44bca2a0d
Author: Marcus Lundblad <ml update uu se>
Date:   Mon Nov 23 22:56:09 2015 +0100

    osmEdit: WIP, implement OAuth-autorized calls for updating

 src/osmConnection.js |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/osmEdit.js       |    2 +-
 2 files changed, 144 insertions(+), 1 deletions(-)
---
diff --git a/src/osmConnection.js b/src/osmConnection.js
index 9ea289d..26dac65 100644
--- a/src/osmConnection.js
+++ b/src/osmConnection.js
@@ -52,8 +52,13 @@ const OSMConnection = new Lang.Class({
 
     _init: function(params) {
         this._session = new Soup.Session();
+        /* OAuth proxy used for enrolling access tokens */
         this._oauthProxy = Rest.OAuthProxy.new(CONSUMER_KEY, CONSUMER_SECRET,
                                                OAUTH_ENDPOINT_URL, false);
+        /* OAuth proxy used for making OSM uploads */
+        this._callProxy = Rest.OAuthProxy.new(CONSUMER_KEY, CONSUMER_SECRET,
+                                              BASE_URL + '/' + API_VERSION,
+                                              false);
 
         /* TODO: stopgap to supply username/password
            to use with HTTP basic auth, should be
@@ -123,12 +128,53 @@ const OSMConnection = new Lang.Class({
     },
 
     openChangeset: function(comment, callback) {
+        /* we assume that this would only be called if there's already been an
+           OAuth access token enrolled, so, if the currently instanciated
+           proxy instance doesn't have a token set, we could safely count on
+           it being present in the keyring */
+        if (this._oauthProxy.get_token() === null) {
+            Secret.password_lookup(SECRET_SCHEMA, {}, null,
+                                   function(source, result) {
+                                        this._onPasswordLookedUp(result,
+                                                                 comment,
+                                                                 callback);
+                                   }.bind(this));
+        } else {
+            this._doOpenChangeset(comment, callback);
+        }
+    },
+
+    _onPasswordLookedUp: function(result, comment, callback) {
+        let password = Secret.password_lookup_finish(result);
+
+        if (password) {
+            let token = password.split(':')[0];
+            let secret = password.split(':')[1];
+
+            this._callProxy.token = token;
+            this._callProxy.token_secret = secret;
+            this._doOpenChangeset(comment, callback);
+        } else {
+            callback(false, null, null);
+        }
+    },
+
+    _doOpenChangeset: function(comment, callback) {
         let changeset =
             Maps.OSMChangeset.new(comment, 'gnome-maps ' + pkg.version);
         let xml = changeset.serialize();
 
         Utils.debug('about open changeset:\n' + xml + '\n');
 
+        let call = Maps.OSMOAuthProxyCall.new(this._callProxy, xml);
+        call.set_method('PUT');
+        call.set_function('/changeset/create');
+
+        call.invoke_async(null, (function(call, res, userdata) {
+                    this._onChangesetOpened(call, callback);
+                                }).bind(this));
+
+        /*
         let url = this._getOpenChangesetUrl();
         let uri = new Soup.URI(url);
         let msg = new Soup.Message({ method: 'PUT', uri: uri });
@@ -144,6 +190,22 @@ const OSMConnection = new Lang.Class({
                 GLib.ascii_strtoull (message.response_body.data, '', 10);
             callback(true, message.status_code, changesetId);
         }));
+        */
+    },
+
+    _onChangesetOpened: function(call, callback) {
+        Utils.debug('status: ' + call.get_status_code());
+
+        if (call.get_status_code() !== Soup.Status.OK) {
+            callback(false, call.get_status_code(), null);
+            return;
+        }
+
+        let changesetId = GLib.ascii_strtoull(call.get_payload(), '', 10);
+
+        Utils.debug('opened changeset: ' + changesetId);
+
+        callback(true, call.get_status_code(), changesetId);
     },
 
     uploadObject: function(object, type, changeset, callback) {
@@ -153,9 +215,19 @@ const OSMConnection = new Lang.Class({
 
         Utils.debug('about to upload object:\n' + xml + '\n');
 
+        let call = Maps.OSMOAuthProxyCall.new(this._callProxy, xml);
+        call.set_method('PUT');
+        call.set_function(this._getCreateOrUpdateFunction(object, type));
+
+        call.invoke_async(null, (function(call, res, userdata) {
+                    this._onObjectUploaded(call, callback);
+                                }).bind(this));
+
+        /*
         let url = this._getCreateOrUpdateUrl(object, type);
         let uri = new Soup.URI(url);
         let msg = new Soup.Message({ method: 'PUT', uri: uri });
+        msg.request_headers.append('Authorization', authorizationHeader);
         msg.set_request('text/xml', Soup.MemoryUse.COPY, xml, xml.length);
 
         this._session.queue_message(msg, (function(obj, message) {
@@ -166,6 +238,16 @@ const OSMConnection = new Lang.Class({
 
             callback(true, message.status_code, message.response_body.data);
         }));
+        */
+    },
+
+    _onObjectUploaded: function(call, callback) {
+        if (call.get_status_code() !== Soup.Status.OK) {
+            callback(false, call.get_status_code(), null);
+            return;
+        }
+
+        callback(true, call.get_status_code(), call.get_payload());
     },
 
     deleteObject: function(object, type, changeset, callback) {
@@ -174,12 +256,22 @@ const OSMConnection = new Lang.Class({
 
         Utils.debug('about to delete object:\n' + xml + '\n');
 
+        let call = Maps.OSMOAuthProxyCall.new(this._callProxy, xml);
+        call.set_method('DELETE');
+        call.set_function(this._getDeleteFunction(object, type));
+
+        call.invoke_async(null, (function(call, res, userdata) {
+                    this._onObjectDeleted(call, callback);
+                                }).bind(this));
+
+        /*
         let url = this._getDeleteUrl(object, type);
         let uri = new Soup.URI(url);
         let msg = new Soup.Message({ method: 'DELETE', uri: uri });
 
         Utils.debug('calling delete URL: ' + url);
 
+        msg.request_headers.append('Authorization', authorizationHeader);
         msg.set_request('text/xml', Soup.MemoryUse.COPY, xml, xml.length);
 
         this._session.queue_message(msg, (function(obj, message) {
@@ -190,12 +282,32 @@ const OSMConnection = new Lang.Class({
 
             callback(true, message.status_code, message.response_body.data);
         }));
+        */
+    },
+
+    _onObjectDeleted: function(call, callback) {
+        if (call.get_status_code() !== Soup.Status.OK) {
+            callback(false, call.get_status_code(), null);
+            return;
+        }
+
+        callback(true, call.get_status_code(), call.get_payload());
     },
 
     closeChangeset: function(changesetId, callback) {
+        let call = this._callProxy.new_call();
+        call.set_method('PUT');
+        call.set_function(this._getCloseChangesetFunction(changesetId));
+
+        call.invoke_async(null, (function(call, res, userdata) {
+                    this._onChangesetClosed(call, callback);
+                                }).bind(this));
+
+        /*
         let url = this._getCloseChangesetUrl(changesetId);
         let uri = new Soup.URI(url);
         let msg = new Soup.Message({ method: 'PUT', uri: uri });
+        msg.request_headers.append('Authorization', authorizationHeader);
 
         this._session.queue_message(msg, (function(obj, message) {
             if (message.status_code !== Soup.Status.OK) {
@@ -205,6 +317,16 @@ const OSMConnection = new Lang.Class({
 
             callback(true, message.status_code);
         }));
+        */
+    },
+
+    _onChangesetClosed: function(call, callback) {
+        if (call.get_status_code() !== Soup.Status.OK) {
+            callback(false, call.get_status_code(), null);
+            return;
+        }
+
+        callback(true, call.get_status_code(), call.get_payload());
     },
 
     _getOpenChangesetUrl: function() {
@@ -216,6 +338,10 @@ const OSMConnection = new Lang.Class({
             changesetId + '/close';
     },
 
+    _getCloseChangesetFunction: function(changesetId) {
+        return '/changeset/' + changesetId + '/close';
+    },
+
     _getCreateOrUpdateUrl: function(object, type) {
         if (object.id) {
             let id = object.id;
@@ -233,6 +359,13 @@ const OSMConnection = new Lang.Class({
         }
     },
 
+    _getCreateOrUpdateFunction: function(object, type) {
+        if (object.id)
+            return type + '/' + object.id;
+        else
+            return type + '/create';
+    },
+
     _getDeleteUrl: function(object, type) {
         let id = object.id;
 
@@ -247,6 +380,10 @@ const OSMConnection = new Lang.Class({
         return this._getBaseUrl() + '/' + API_VERSION + '/' + type + '/' + id;
     },
 
+    _getDeleteFunction: function(object, type) {
+        return type + '/' + id;
+    },
+
     _authenticate: function(session, msg, auth, retrying, user_data) {
         Utils.debug('authenticate triggered');
         if (retrying)
@@ -422,6 +559,12 @@ const OSMConnection = new Lang.Class({
     },
 
     signOut: function() {
+        /* clear token on call proxy, so it will use a new token if the user
+           signs in again (with a new access token) during this running
+           session */
+        this._callProxy.token = null;
+        this._callProxy.token_secret = null;
+
         Secret.password_clear(SECRET_SCHEMA, {}, null,
             this._onPasswordCleared.bind(this));
     },
diff --git a/src/osmEdit.js b/src/osmEdit.js
index 6821009..b13d884 100644
--- a/src/osmEdit.js
+++ b/src/osmEdit.js
@@ -83,7 +83,7 @@ const OSMEdit = new Lang.Class({
     _onChangesetOpened: function(success, status, changesetId, object, type,
                                  action, callback) {
         if (success) {
-            let osmType = this._getOSMTypeName(type);
+            let osmType = Utils.osmTypeToString(type);
             action(object, osmType, changesetId, callback);
         } else {
             callback(false, status);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]