You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2019/01/08 11:48:07 UTC

[GitHub] csantanapr closed pull request #92: APIKey changes

csantanapr closed pull request #92: APIKey changes
URL: https://github.com/apache/incubator-openwhisk-package-pushnotifications/pull/92
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index b96f1c3..89ef40e
--- a/README.md
+++ b/README.md
@@ -9,10 +9,9 @@ The package includes the following action and feed:
 
 | Entity | Type | Parameters | Description |
 | --- | --- | --- | --- |
-| `/whisk.system/pushnotifications` | package | appId, appSecret, admin_url  | Work with the Push Service |
+| `/whisk.system/pushnotifications` | package | appId, appSecret, apiKey, admin_url  | Work with the Push Service |
 | `/whisk.system/pushnotifications/sendMessage` | action | text, url, apiHost, deviceIds, platforms, userIds, tagNames, gcmCollapseKey, gcmCategory, gcmIcon, gcmDelayWhileIdle, gcmSync, gcmVisibility, gcmPayload, gcmPriority, gcmSound, gcmTimeToLive, gcmStyleType, gcmStyleTitle, gcmStyleUrl, gcmStyleText, gcmStyleLines, gcmLightsLedArgb, gcmLightsLedOnMs, gcmLightsLedOffMs, apnsBadge, apnsCategory, apnsIosActionKey, apnsPayload, apnsType, apnsSound, apnsTitleLocKey, apnsLocKey, apnsLaunchImage, apnsTitleLocArgs, apnsLocArgs, apnstitle, apnsSubtitle, apnsAttachmentUrl, fireFoxTitle, fireFoxIconUrl, fireFoxTimeToLive, fireFoxPayload, safariTitle, safariUrlArgs, safariAction, chromeTitle, chromeIconUrl, chromeTimeToLive, chromePayload, chromeAppExtTitle, chromeAppExtCollapseKey, chromeAppExtDelayWhileIdle, chromeAppExtIconUrl, chromeAppExtTimeToLive, chromeAppExtPayload | Send push notification to one or more specified devices |
-| `/whisk.system/pushnotifications/webhook` | feed | events | Fire trigger events on device activities (device registration, unregistration, subscription, or unsubscription) on the Push service |
-Creating a package binding with the `appId` and `appSecret` values is suggested. This way, you don't need to specify these credentials every time you invoke the actions in the package.
+| `/whisk.system/pushnotifications/webhook` | feed | events, admin_url, apiHost | Fire trigger events on device activities (device registration, unregistration, subscription, or unsubscription) on the Push service | Creating a package binding with the `appId` and `appSecret` or `apiKey` values is suggested. This way, you don't need to specify these credentials every time you invoke the actions in the package.
 
 ## Creating a Push package binding
 
@@ -20,6 +19,7 @@ While creating a Push Notifications package binding, you must specify the follow
 
 -  `appId`: The Bluemix app GUID.
 -  `appSecret`: The Bluemix push notification service appSecret.
+-  `apiKey`: The Bluemix push notification service apiKey.
 
 The following is an example of creating a package binding.
 
@@ -29,13 +29,18 @@ The following is an example of creating a package binding.
 
 3. Configure the [Push Notification application](https://console.ng.bluemix.net/docs/services/mobilepush/index.html).
 
-  Be sure to remember the `App GUID` and the `App Secret` of the Bluemix app you created.
+  Be sure to remember the `App GUID` and the `App Secret` or `API Key`  of the Bluemix app you created.
 
 4. Create a package binding with the `/whisk.system/pushnotifications`.
 
   ```
   wsk package bind /whisk.system/pushnotifications myPush -p appId myAppID -p appSecret myAppSecret
   ```
+  OR
+
+  ```
+  wsk package bind /whisk.system/pushnotifications myPush -p appId myAppID -p apiKey myApiKey
+  ```
 
 5. Verify that the package binding exists.
 
@@ -54,7 +59,7 @@ The `/whisk.system/pushnotifications/sendMessage` action sends push notification
 
 - `text`: The notification message to be shown to the user. For example: `-p text "Hi ,OpenWhisk send a notification"`.
 - `url`: An optional URL that can be sent along with the alert. For example: `-p url "https:\\www.w3.ibm.com"`.
-- `apiHost`: An optional string that specifies the API host.  The default is 'mobile.ng.bluemix.net'.  For example: `-p apiHost "mobile.eu-gb.bluemix.net"`.
+- `apiHost`: An optional string that specifies the API host.  The default is 'imfpush.ng.bluemix.net'.  For example: `-p apiHost "imfpush.eu-gb.bluemix.net"`.
 - `deviceIds` The list of specified devices. For example: `-p deviceIds "[\"deviceID1\"]"`.
 - `platforms` Send notification to the devices of the specified platforms. 'A' for apple (iOS) devices and 'G' for google (Android) devices. For example `-p platforms ["A"]`.
 - `userIds` - Send notification to the devices of the specified users. For example: `-p userIds "[\"testUser\"]"`
@@ -160,6 +165,8 @@ The parameters are as follows:
 
 - `appId:` The Bluemix app GUID.
 - `appSecret:` The Bluemix push notification service appSecret.
+- `apiKey`: The Bluemix push notification service apiKey.
+- `apiHost`: An optional string that specifies the API host.  The default is 'imfpush.ng.bluemix.net'.  For example: `-p apiHost "imfpush.eu-gb.bluemix.net"`.
 - `events:` Supported events are `onDeviceRegister`, `onDeviceUnregister`, `onDeviceUpdate`, `onSubscribe`, `onUnsubscribe`.To get notified for all events use the wildcard character `*`.
 
 The following is an example of creating a trigger that will be fired each time there is a new device registered with the Push Notifications service application.
diff --git a/packages/actions/sendMessage.js b/packages/actions/sendMessage.js
old mode 100644
new mode 100755
index 4ee1584..02897a3
--- a/packages/actions/sendMessage.js
+++ b/packages/actions/sendMessage.js
@@ -20,8 +20,9 @@
 *
 *  @param {string} appGuid - appGuid to create webhook
 *  @param {string} appSecret - appSecret of the application
+*  @param {string} apiKey - apiKey of the application
 *  @param {string} url - An optional URL that can be sent along with the alert. Eg : -p url "https:\\www.mycompany.com".
-*  @param {string} apiHost - An optional string that specifies the API host.  The default is 'mobile.ng.bluemix.net'.  Eg : -p apiHost "mobile.eu-gb.bluemix.net".
+*  @param {string} apiHost - An optional string that specifies the API host.  The default is 'imfpush.ng.bluemix.net'.  Eg : -p apiHost "imfpush.eu-gb.bluemix.net".
 *  @param {object} text - The notification message to be shown to the user. Eg: -p text "Hi ,OpenWhisk send a notification"
 *  @param {string} deviceIds - Send notification to the list of specified devices. Eg: -p deviceIds "["deviceID1"]"
 *  @param {object} platforms - Send notification to the devices of the specified platforms. 'A' for apple (iOS) devices and 'G' for google (Android) devices. Eg: -p platforms ["A"]
@@ -87,18 +88,30 @@
 module.paths.push('/usr/lib/node_modules');
 var https = require('https');
 var url = require('url');
+var request = require('request');
 
 function main(params) {
 
   if (!params.appId && !params.appGuid) {
     return Promise.reject('appId / appGUID of the application is required.');
   }
-  if (!params.appSecret) {
-    return Promise.reject('appSecret of the application is required.');
+  if (!params.appSecret && !params.apiKey) {
+    return Promise.reject('appSecret / apiKey of the application is required.');
   }
 
   var appId = params.appGuid || params.appId;
   var appSecret = params.appSecret;
+  var apiKey = params.apiKey;
+
+  var apiHost;
+  if (params.apiHost) {
+    apiHost = params.apiHost;
+  } else if (params.admin_url) {
+    var adminURL = url.parse(params.admin_url).protocol === null ? `https:${params.admin_url}` : params.admin_url;
+    apiHost = url.parse(adminURL).host;
+  } else {
+    apiHost = 'imfpush.ng.bluemix.net';
+  }
 
   // message section settings
   var messageUrl = params.url;
@@ -297,7 +310,7 @@ function main(params) {
   }
 
   var gcmStyle = {};
-  if(gcmStyleType){
+  if (gcmStyleType) {
     gcmStyle.type = gcmStyleType;
   }
   if (gcmStyleTitle) {
@@ -317,7 +330,7 @@ function main(params) {
   }
 
   var gcmLights = {};
-  if(gcmLightsLedArgb){
+  if (gcmLightsLedArgb) {
     gcmLights.ledArgb = gcmLightsLedArgb;
   }
   if (gcmLightsLedOnMs) {
@@ -339,7 +352,7 @@ function main(params) {
 
   // create FireFox settings section
   var firefoxWeb = {};
-  if (fireFoxTitle){
+  if (fireFoxTitle) {
     firefoxWeb.title = fireFoxTitle;
   }
   if (fireFoxIconUrl) {
@@ -361,7 +374,7 @@ function main(params) {
 
   // create Safari settings section
   var safariWeb = {};
-  if (safariTitle){
+  if (safariTitle) {
     safariWeb.title = safariTitle;
   }
   if (safariUrlArgs) {
@@ -379,7 +392,7 @@ function main(params) {
 
   // create Chrome settings section
   var chromeWeb = {};
-  if (chromeTitle){
+  if (chromeTitle) {
     chromeWeb.title = chromeTitle;
   }
   if (chromeIconUrl) {
@@ -401,7 +414,7 @@ function main(params) {
 
   // create Chrome Apps & Extensions settings section
   var chromeAppExt = {};
-  if (chromeAppExtTitle){
+  if (chromeAppExtTitle) {
     chromeAppExt.title = chromeAppExtTitle;
   }
   if (chromeAppExtCollapseKey) {
@@ -427,35 +440,57 @@ function main(params) {
   }
 
   var bodyData = JSON.stringify(sendMessage);
-  var request = require('request');
-  var apiHost;
-  if (params.apiHost) {
-    apiHost = params.apiHost;
-  }
-  else if (params.admin_url) {
-    var adminURL = url.parse(params.admin_url).protocol === null ? `https:${params.admin_url}` : params.admin_url;
-    apiHost = url.parse(adminURL).host;
-  }
-  else {
-    apiHost = 'mobile.ng.bluemix.net';
+
+  var headersJson;
+
+  if (!appSecret) {
+
+    return new Promise(function (resolve, reject) {
+      getAuthToken(apiKey, apiHost).then(function (response) {
+        if (response.hasToken) {
+          headersJson = {
+            'Authorization': "Bearer " + response.apiToken,
+            'Accept': 'application/json',
+            'Content-Type': 'application/json'
+          };
+          sendPush(appId, apiHost, headersJson, bodyData).then(function (response) {
+            resolve(response);
+          }).catch(function (e) {
+            reject(e);
+          });
+        } else {
+          reject({
+            error: "Not able to get a valid iam token"
+          });
+        }
+      });
+    });
+  } else {
+    headersJson = {
+      'appSecret': appSecret,
+      'Accept': 'application/json',
+      'Content-Type': 'application/json'
+    };
+    return sendPush(appId, apiHost, headersJson, bodyData);
   }
+}
+
+function sendPush(appId, apiHost, headersJson, bodyData) {
 
   var promise = new Promise(function (resolve, reject) {
     request({
       method: 'post',
       uri: `https://${apiHost}/imfpush/v1/apps/${appId}/messages`,
-      headers: {
-        'appSecret': appSecret,
-        'Accept': 'application/json',
-        'Content-Type': 'application/json'
-      },
+      headers: headersJson,
       body: bodyData
     }, function (error, response, body) {
-      if (error) {
-        reject(error);
-      }
-      var j = JSON.parse(body);
-      resolve(j);
+      
+      if (error || ( response.statusCode < 200 || response.statusCode > 300)) {
+        reject(body);
+      } else {
+        var jsonBody = JSON.parse(body);
+        resolve(jsonBody);
+      }      
     });
   });
   return promise;
@@ -471,3 +506,45 @@ function isEmpty(obj) {
 
   return true;
 }
+
+function getAuthToken(apiKeyId, iamRegion) {
+
+  return new Promise(function (resolve, reject) {
+    iamRegion = iamRegion.substring(iamRegion.indexOf('.') + 1);
+    var iamUri = "https://iam." + iamRegion + "/identity/token"
+    var iamHeaders = {
+      "Content-Type": "application/x-www-form-urlencoded",
+      "Accept": "application/json"
+    };
+    var options = {
+      uri: iamUri,
+      method: "POST",
+      headers: iamHeaders,
+      form: {
+        grant_type: 'urn:ibm:params:oauth:grant-type:apikey',
+        apikey: apiKeyId
+      }
+    };
+    request(options, function (error, response, body) {
+      if (error) {
+        reject({
+          hasToken: false,
+          token: ""
+        });
+      } else {
+        if (response.statusCode == 200) {
+          var responseJson = JSON.parse(body);
+          resolve({
+            hasToken: true,
+            apiToken: responseJson["access_token"]
+          });
+        } else {
+          reject({
+            hasToken: false,
+            token: ""
+          });
+        }
+      }
+    });
+  });
+}
\ No newline at end of file
diff --git a/packages/feeds/webhook.js b/packages/feeds/webhook.js
old mode 100644
new mode 100755
index cddd427..15d7b0e
--- a/packages/feeds/webhook.js
+++ b/packages/feeds/webhook.js
@@ -20,9 +20,13 @@
  *
  *  @param {string} appGuid - appGuid to create webhook
  *  @param {string} appSecret - appSecret of the application
+ *  @param {string} apiKey - apiKey of the application
  *  @param {string} events - list of the events the webhook should fire on
  *  @return {object} whisk async
  */
+module.paths.push('/usr/lib/node_modules');
+var https = require('https');
+var url = require('url');
 var request = require('request');
 
 function main(params) {
@@ -34,57 +38,178 @@ function main(params) {
     var endpoint = 'openwhisk.ng.bluemix.net';
     // URL of the whisk system. The calls of push service will go here.
     var whiskCallbackUrl = 'https://' + process.env.__OW_API_KEY + "@" + endpoint + '/api/v1/namespaces/' + namespace + '/triggers/' + trigger;
+
+
+    if (!params.appId && !params.appGuid) {
+        return Promise.reject('appId / appGUID of the application is required.');
+    }
+    if (!params.appSecret && !params.apiKey) {
+        return Promise.reject('appSecret / apiKey of the application is required.');
+    }
+
     var appId = params.appGuid || params.appId;
     var appSecret = params.appSecret;
+    var apiKey = params.apiKey;
+
+    var apiHost;
+    if (params.apiHost) {
+        apiHost = params.apiHost;
+    } else if (params.admin_url) {
+        var adminURL = url.parse(params.admin_url).protocol === null ? `https:${params.admin_url}` : params.admin_url;
+        apiHost = url.parse(adminURL).host;
+    } else {
+        apiHost = 'imfpush.ng.bluemix.net';
+    }
+
     // The URL to create the webhook on push service
-    var registrationEndpoint = 'https://mobile.ng.bluemix.net/imfpush/v1/apps/' + appId + '/webhooks';
+    var registrationEndpoint = 'https://' + apiHost + '/imfpush/v1/apps/' + appId + '/webhooks';
     var lifecycleEvent = (params.lifecycleEvent || 'CREATE').trim().toUpperCase();
+
     if (lifecycleEvent === 'CREATE' || lifecycleEvent === 'UPDATE') {
 
         var events = params.events;
         var body = {
-            name:trigger,
+            name: trigger,
             url: whiskCallbackUrl,
             eventTypes: events
         };
-        var options = {
-            method: 'POST',
-            url: registrationEndpoint,
-            body: JSON.stringify(body),
-            headers: {
-                'appSecret': appSecret,
-                'Content-Type': 'application/json'
-            }
-        };
-        var promise = new Promise(function(resolve, reject) {
-            request(options, function (error, response, body) {
-                if (error) {
-                    reject(error);
+
+        if (!appSecret) {
+
+            return new Promise(function (resolve, reject) {
+                getAuthToken(apiKey, apiHost).then(function (response) {
+                    if (response.hasToken) {
+                        var options = {
+                            method: 'POST',
+                            url: registrationEndpoint,
+                            body: JSON.stringify(body),
+                            headers: {
+                                'Authorization': "Bearer " + response.apiToken,
+                                'Content-Type': 'application/json'
+                            }
+                        };
+                        sendWebhook(options).then(function (response) {
+                            resolve(response);
+                        }).catch(function (e) {
+                            reject(e);
+                        });
+                    } else {
+                        reject({
+                            error: "Not able to get a valid iam token"
+                        });
+                    }
+                });
+            });
+        } else {
+            var options = {
+                method: 'POST',
+                url: registrationEndpoint,
+                body: JSON.stringify(body),
+                headers: {
+                    'appSecret': appSecret,
+                    'Content-Type': 'application/json'
                 }
-                resolve({response: body});
+            };
+            return sendWebhook(options);
+        }
+    } else if (lifecycleEvent === 'DELETE') {
+
+
+        if (!appSecret) {
+
+            return new Promise(function (resolve, reject) {
+                getAuthToken(apiKey, apiHost).then(function (response) {
+                    if (response.hasToken) {
+                        var options = {
+                            method: 'DELETE',
+                            url: registrationEndpoint,
+                            headers: {
+                                'Authorization': "Bearer " + response.apiToken
+                            }
+                        };
+                        sendWebhook(options).then(function (response) {
+                            resolve(response);
+                        }).catch(function (e) {
+                            reject(e);
+                        });
+                    } else {
+                        reject({
+                            error: "Not able to get a valid iam token"
+                        });
+                    }
+                });
+            });
+
+        } else {
+
+            var options = {
+                method: 'DELETE',
+                url: registrationEndpoint,
+                headers: {
+                    'appSecret': appSecret
+                }
+            };
+            return sendWebhook(options);
+        }
+    }
+}
+
+function sendWebhook(options) {
+
+    var promise = new Promise(function (resolve, reject) {
+        request(options, function (error, response, body) {
+            if (error) {
+                reject(error);
+            }
+            resolve({
+                response: body
             });
         });
+    });
+    return promise;
 
-        return promise;
-    } else if (lifecycleEvent === 'DELETE') {
+}
+
+function getAuthToken(apiKeyId, iamRegion) {
+
+    return new Promise(function (resolve, reject) {
+        iamRegion = iamRegion.substring(iamRegion.indexOf('.') + 1);
+        var iamUri = "https://iam." + iamRegion + "/identity/token"
+        var iamHeaders = {
+            "Content-Type": "application/x-www-form-urlencoded",
+            "Accept": "application/json"
+        };
         var options = {
-            method: 'DELETE',
-            url: registrationEndpoint,
-            headers: {
-                'appSecret': appSecret
+            uri: iamUri,
+            method: "POST",
+            headers: iamHeaders,
+            form: {
+                grant_type: 'urn:ibm:params:oauth:grant-type:apikey',
+                apikey: apiKeyId
             }
         };
-        var promise = new Promise(function(resolve, reject) {
-            request(options, function (error, response, body) {
-                if (error) {
-                    reject(error);
+        request(options, function (error, response, body) {
+            if (error) {
+                reject({
+                    hasToken: false,
+                    token: ""
+                });
+            } else {
+                if (response.statusCode == 200) {
+                    var responseJson = JSON.parse(body);
+                    resolve({
+                        hasToken: true,
+                        apiToken: responseJson["access_token"]
+                    });
+                } else {
+                    reject({
+                        hasToken: false,
+                        token: ""
+                    });
                 }
-                resolve({response: body});
-            });
+            }
         });
-
-        return promise;
-    }
+    });
 }
 
 function parseQName(qname) {
@@ -100,4 +225,4 @@ function parseQName(qname) {
         parsed.name = qname;
     }
     return parsed;
-}
+}
\ No newline at end of file


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services