Add sender identifier to configuration Allow a client to retrieve the FCM sender id, so it can generate a token for this server. Change-Id: If27a89dc34bb6ffab0b057a7ef58cbdd9f676a4c Signed-off-by: Jorge Ruesga <j.ruesga.criado@gmail.com>
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java index f240abc..7117d03 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/ApiModule.java
@@ -16,6 +16,7 @@ package com.ruesga.gerrit.plugins.fcm; import static com.google.gerrit.server.account.AccountResource.ACCOUNT_KIND; +import static com.google.gerrit.server.config.ConfigResource.CONFIG_KIND; import static com.ruesga.gerrit.plugins.fcm.server.DeviceResource.DEVICE_KIND; import static com.ruesga.gerrit.plugins.fcm.server.TokenResource.TOKEN_KIND; @@ -52,6 +53,7 @@ import com.ruesga.gerrit.plugins.fcm.handlers.TopicEditedEventHandler; import com.ruesga.gerrit.plugins.fcm.server.DeleteToken; import com.ruesga.gerrit.plugins.fcm.server.Devices; +import com.ruesga.gerrit.plugins.fcm.server.GetCloudNotificationsConfigInfo; import com.ruesga.gerrit.plugins.fcm.server.GetToken; import com.ruesga.gerrit.plugins.fcm.server.PostToken; import com.ruesga.gerrit.plugins.fcm.server.Tokens; @@ -60,6 +62,7 @@ public class ApiModule extends RestApiModule { + public static final String CONFIG_ENTRY_POINT = "cloud-notifications"; public static final String DEVICES_ENTRY_POINT = "devices"; public static final String TOKEN_ENTRY_POINT = "tokens"; @@ -100,6 +103,8 @@ // Configure the Rest API DynamicMap.mapOf(binder(), DEVICE_KIND); DynamicMap.mapOf(binder(), TOKEN_KIND); + get(CONFIG_KIND, CONFIG_ENTRY_POINT).to( + GetCloudNotificationsConfigInfo.class); child(ACCOUNT_KIND, DEVICES_ENTRY_POINT).to(Devices.class); child(DEVICE_KIND, TOKEN_ENTRY_POINT).to(Tokens.class); get(TOKEN_KIND).to(GetToken.class);
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/Configuration.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/Configuration.java index e952af3..da01faa 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/Configuration.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/Configuration.java
@@ -36,10 +36,12 @@ public static final String PROP_DATABASE_PATH = "databasePath"; public static final String PROP_SERVER_URL = "serverUrl"; public static final String PROP_SERVER_TOKEN = "serverToken"; + public static final String PROP_SERVER_SENDER_ID = "serverSenderId"; public final String databasePath; public final String serverToken; public final String serverUrl; + public final String serverSenderId; @Inject public Configuration( @@ -48,6 +50,7 @@ PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName); this.databasePath = cfg.getString(PROP_DATABASE_PATH); this.serverToken = cfg.getString(PROP_SERVER_TOKEN); + this.serverSenderId = cfg.getString(PROP_SERVER_SENDER_ID); String serverUrl = cfg.getString(PROP_SERVER_URL); if (serverUrl == null || serverUrl.isEmpty()) { serverUrl = Configuration.DEFAULT_SERVER_URL; @@ -60,6 +63,7 @@ } public boolean isEnabled() { - return this.serverToken != null && !this.serverToken.isEmpty(); + return (this.serverToken != null && !this.serverToken.isEmpty()) && + (this.serverSenderId != null && !this.serverSenderId.isEmpty()); } }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/InitStep.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/InitStep.java index cffe676..f133a61 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/InitStep.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/InitStep.java
@@ -47,8 +47,8 @@ String serverUrl = ui.readString( Configuration.DEFAULT_SERVER_URL, "Firebase Server Url"); - String serverToken = ui.readString( - "", "Firebase Server Token"); + String serverToken = ui.readString("", "Firebase Server Token"); + String serverSenderId = ui.readString("", "Firebase Server Sender Id"); String databasePath = ui.readString( "", "Database path (leave empty for default)"); @@ -56,13 +56,19 @@ serverUrl = Configuration.DEFAULT_SERVER_URL; } cfg.setString("plugin", pluginName, - Configuration.PROP_SERVER_TOKEN, serverUrl); + Configuration.PROP_SERVER_URL, serverUrl); if (serverToken != null && serverToken.isEmpty()) { cfg.unset("plugin", pluginName, Configuration.PROP_SERVER_TOKEN); } else { cfg.setString("plugin", pluginName, Configuration.PROP_SERVER_TOKEN, serverToken); } + if (serverSenderId != null && serverSenderId.isEmpty()) { + cfg.unset("plugin", pluginName, Configuration.PROP_SERVER_SENDER_ID); + } else { + cfg.setString("plugin", pluginName, + Configuration.PROP_SERVER_SENDER_ID, serverSenderId); + } if (databasePath != null && databasePath.isEmpty()) { cfg.unset("plugin", pluginName, Configuration.PROP_DATABASE_PATH); } else {
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationsConfigInfo.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationsConfigInfo.java new file mode 100644 index 0000000..79da843 --- /dev/null +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/rest/CloudNotificationsConfigInfo.java
@@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Jorge Ruesga + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ruesga.gerrit.plugins.fcm.rest; + +import com.google.gson.annotations.SerializedName; + +public class CloudNotificationsConfigInfo { + /** + * The Firebase Cloud server sender id. + */ + @SerializedName("senderId") public String senderId; +}
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeleteToken.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeleteToken.java index b52cba3..7eee061 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeleteToken.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/DeleteToken.java
@@ -16,8 +16,10 @@ package com.ruesga.gerrit.plugins.fcm.server; import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestModifyView; +import com.ruesga.gerrit.plugins.fcm.Configuration; import com.ruesga.gerrit.plugins.fcm.DatabaseManager; import com.ruesga.gerrit.plugins.fcm.server.DeleteToken.Input; import com.google.gerrit.server.CurrentUser; @@ -33,19 +35,27 @@ private final Provider<CurrentUser> self; private final DatabaseManager db; + private final Configuration config; @Inject public DeleteToken( Provider<CurrentUser> self, - DatabaseManager db) { + DatabaseManager db, + Configuration config) { super(); this.self = self; this.db = db; + this.config = config; } @Override public Response<?> apply(TokenResource rsrc, Input input) - throws BadRequestException { + throws BadRequestException, ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + // Request are only valid from the current authenticated user if (self.get() == null || self.get() != rsrc.getUser()) { throw new BadRequestException("invalid account!");
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetCloudNotificationsConfigInfo.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetCloudNotificationsConfigInfo.java new file mode 100644 index 0000000..5d40037 --- /dev/null +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetCloudNotificationsConfigInfo.java
@@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Jorge Ruesga + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ruesga.gerrit.plugins.fcm.server; + +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; +import com.google.gerrit.extensions.restapi.RestReadView; +import com.google.gerrit.server.config.ConfigResource; +import com.ruesga.gerrit.plugins.fcm.Configuration; +import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationsConfigInfo; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +@Singleton +public class GetCloudNotificationsConfigInfo + implements RestReadView<ConfigResource> { + + private final Configuration config; + + @Inject + public GetCloudNotificationsConfigInfo(Configuration config) { + super(); + this.config = config; + } + + @Override + public CloudNotificationsConfigInfo apply(ConfigResource rsrc) + throws ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + + CloudNotificationsConfigInfo info = new CloudNotificationsConfigInfo(); + info.senderId = this.config.serverSenderId; + return info; + } +}
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetDevice.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetDevice.java index e4113e6..00a7fce 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetDevice.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetDevice.java
@@ -18,6 +18,7 @@ import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.RestReadView; +import com.ruesga.gerrit.plugins.fcm.Configuration; import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationInfo; import com.google.gerrit.server.CurrentUser; import com.google.inject.Inject; @@ -28,16 +29,26 @@ public class GetDevice implements RestReadView<DeviceResource> { private final Provider<CurrentUser> self; + private final Configuration config; @Inject - public GetDevice(Provider<CurrentUser> self) { + public GetDevice( + Provider<CurrentUser> self, + Configuration config) { super(); this.self = self; + this.config = config; } @Override public CloudNotificationInfo apply(DeviceResource rsrc) throws BadRequestException, ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + + // Request are only valid from the current authenticated user if (self.get() == null || self.get() != rsrc.getUser()) { throw new BadRequestException("invalid account!"); }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetToken.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetToken.java index 0f9883c..d12613a 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetToken.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/GetToken.java
@@ -18,6 +18,7 @@ import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.RestReadView; +import com.ruesga.gerrit.plugins.fcm.Configuration; import com.ruesga.gerrit.plugins.fcm.DatabaseManager; import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationInfo; import com.google.gerrit.server.CurrentUser; @@ -30,19 +31,28 @@ private final Provider<CurrentUser> self; private final DatabaseManager db; + private final Configuration config; @Inject public GetToken( Provider<CurrentUser> self, - DatabaseManager db) { + DatabaseManager db, + Configuration config) { super(); this.self = self; this.db = db; + this.config = config; } @Override public CloudNotificationInfo apply(TokenResource rsrc) throws BadRequestException, ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + + // Request are only valid from the current authenticated user if (self.get() == null || self.get() != rsrc.getUser()) { throw new BadRequestException("invalid account!"); }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListDevices.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListDevices.java index aca2b6b..4715715 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListDevices.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListDevices.java
@@ -18,26 +18,39 @@ import java.util.List; import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.account.AccountResource; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; +import com.ruesga.gerrit.plugins.fcm.Configuration; @Singleton public class ListDevices implements RestReadView<AccountResource> { + private final Provider<CurrentUser> self; + private final Configuration config; @Inject - public ListDevices(Provider<CurrentUser> self) { + public ListDevices( + Provider<CurrentUser> self, + Configuration config) { super(); this.self = self; + this.config = config; } @Override public List<DeviceResource> apply(AccountResource rsrc) - throws BadRequestException { + throws BadRequestException, ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + + // Request are only valid from the current authenticated user if (self.get() == null || self.get() != rsrc.getUser()) { throw new BadRequestException("invalid account!"); }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListTokens.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListTokens.java index 159f8aa..af9012a 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListTokens.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/ListTokens.java
@@ -18,11 +18,13 @@ import java.util.List; import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.server.CurrentUser; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; +import com.ruesga.gerrit.plugins.fcm.Configuration; import com.ruesga.gerrit.plugins.fcm.DatabaseManager; import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationInfo; @@ -31,19 +33,28 @@ private final Provider<CurrentUser> self; private final DatabaseManager db; + private final Configuration config; @Inject public ListTokens( Provider<CurrentUser> self, - DatabaseManager db) { + DatabaseManager db, + Configuration config) { super(); this.self = self; this.db = db; + this.config = config; } @Override public List<CloudNotificationInfo> apply(DeviceResource rsrc) - throws BadRequestException { + throws BadRequestException, ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + + // Request are only valid from the current authenticated user if (self.get() == null || self.get() != rsrc.getUser()) { throw new BadRequestException("invalid account!"); }
diff --git a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/PostToken.java b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/PostToken.java index b2492a0..5349a81 100644 --- a/src/main/java/com/ruesga/gerrit/plugins/fcm/server/PostToken.java +++ b/src/main/java/com/ruesga/gerrit/plugins/fcm/server/PostToken.java
@@ -21,7 +21,9 @@ import java.util.TimeZone; import com.google.gerrit.extensions.restapi.BadRequestException; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.RestModifyView; +import com.ruesga.gerrit.plugins.fcm.Configuration; import com.ruesga.gerrit.plugins.fcm.DatabaseManager; import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationInfo; import com.ruesga.gerrit.plugins.fcm.rest.CloudNotificationInput; @@ -37,14 +39,17 @@ private final Provider<CurrentUser> self; private final DatabaseManager db; private final SimpleDateFormat formatter; + private final Configuration config; @Inject public PostToken( Provider<CurrentUser> self, - DatabaseManager db) { + DatabaseManager db, + Configuration config) { super(); this.self = self; this.db = db; + this.config = config; formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); formatter.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -53,7 +58,12 @@ @Override public CloudNotificationInfo apply( DeviceResource rsrc, CloudNotificationInput input) - throws BadRequestException { + throws BadRequestException, ResourceNotFoundException { + // Check if plugin is configured + if (!config.isEnabled()) { + throw new ResourceNotFoundException("not configured!"); + } + // Request are only valid from the current authenticated user if (self.get() == null || self.get() != rsrc.getUser()) { throw new BadRequestException("invalid account!");
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md index 619f0df..1c7e053 100644 --- a/src/main/resources/Documentation/about.md +++ b/src/main/resources/Documentation/about.md
@@ -4,5 +4,5 @@ This is a Gerrit's plugin to send notifications using Firebase Cloud Messaging to devices previously registered. -Checkout the document fcm.md in this same folder, for an explanation about -how it works. +Checkout the document api.md in this same folder, for an explanation about +the new api entrypoints.
diff --git a/src/main/resources/Documentation/fcm.md b/src/main/resources/Documentation/api.md similarity index 84% rename from src/main/resources/Documentation/fcm.md rename to src/main/resources/Documentation/api.md index dce5199..eb838ce 100644 --- a/src/main/resources/Documentation/fcm.md +++ b/src/main/resources/Documentation/api.md
@@ -6,13 +6,37 @@ A client application can unregistered a device (and stop receiving notifications) from the Gerrit instance using the *Unregister Cloud Notification* method. -Client applications must use a combintion of fcm device identifier + a unique local account token, so they can register to listen notification for different accounts on this Gerrit instance. Token must +Client applications must use a combination of fcm device identifier + a unique local account token, so they can register to listen notification for different accounts on this Gerrit instance. Token must REST API -------- -This plugin addes new methods to the /accounts Gerrit REST Api entry point to allow a device to register/unregister to receive event notification in this gerrit instance. +This plugin adds new methods to the /accounts Gerrit REST Api entry point to allow a device to register/unregister to receive event notification in this Gerrit instance. + +*** + +**Get Cloud Notifications Config** + +`'GET /config/server/cloud-notifications'` + +Retrieve the cloud notifications server configuration of the Gerrit server instance. + +*Request* +This method returns a *CloudNotificationsConfigInfo* entity (see below). + + GET /config/server/cloud-notifications + +*Response* + + HTTP1.1 200 OK + Content-Disposition: attachment + Content-Type: application/json; charset=UTF-8 + + )]}' + { + "senderId": "322112333" + } *** @@ -20,7 +44,7 @@ `'GET /accounts/{account-id}/devices/{device-id}/tokens'` -Retrieves a list of registered tokens by a device hold by the Gerrit server instance. +Retrieve a list of registered tokens by a device hold by the Gerrit server instance. *Request* This request requires an authenticated call and only returns information if account-id is the authenticated account. This method returns a list of *CloudNotificationInfo* entities (see below). @@ -50,7 +74,7 @@ `'GET /accounts/{account-id}/devices/{device-id}/tokens/{token}'` -Retrieves a registered device information hold by the Gerrit server instance. +Retrieve a registered device information hold by the Gerrit server instance. *Request* This request requires an authenticated call and only returns information if account-id is the authenticated account. This method returns a *CloudNotificationInfo* entity (see below). @@ -128,6 +152,14 @@ *** +**CloudNotificationsConfigInfo** + +Entity with information about the cloud notifications server configuration. + +`senderId: The Firebase Cloud Messaging server identifier.` + +*** + **CloudNotificationInfo** Entity with information about a registered device.
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index f807f6f..52d6f83 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -12,20 +12,25 @@ ``` [plugin "cloud-notifications"] - serverUrl = https://fcm.googleapis.com/fcm/send serverToken = <SERVER_API_KEY> + serverSenderId = <SERVER_SENDER_ID> + serverUrl = <https://fcm.googleapis.com/fcm/send> databasePath = <DATABASE_LOCATION_PATH> ``` Plugin parameters -------------------- -* serverUrl: The Firebase Cloud Messaging backend url. -Default: https://fcm.googleapis.com/fcm/send - * serverToken: Your Firebase Cloud Messaging server token. You can grab it from your Firebase project console, in Configuration > Cloud Messaging > Server key +* serverSenderId: Your Firebase Cloud Messaging server sender identifier. +You can grab it from your Firebase project console, in Configuration > Cloud +Messaging > Server Id + +* serverUrl: The Firebase Cloud Messaging backend url. +Default: https://fcm.googleapis.com/fcm/send + * databasePath: The path to where to store the plugin database. Leave empty to use the default path ($gerrit/data/cloud-notifications/cloud-notifications.h2.db)