diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2017-09-19 22:10:44 +1200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-19 22:10:44 +1200 |
commit | 6a40551d0e1d63fbb68f0401be73a4c64db4ca64 (patch) | |
tree | 36e5d835966f0a7d1d5563e24263b87734c86370 | |
parent | 561c616418918da4bb1d75c95347e25c23f72f6a (diff) | |
parent | 285f6feea43be782edc6233b709d47b146250361 (diff) | |
download | trackermap-server-6a40551d0e1d63fbb68f0401be73a4c64db4ca64.tar.gz trackermap-server-6a40551d0e1d63fbb68f0401be73a4c64db4ca64.tar.bz2 trackermap-server-6a40551d0e1d63fbb68f0401be73a4c64db4ca64.zip |
Merge pull request #3534 from Abyss777/extend_notifications
Implement per device Notifications
-rw-r--r-- | schema/changelog-3.15.xml | 50 | ||||
-rw-r--r-- | src/org/traccar/Context.java | 3 | ||||
-rw-r--r-- | src/org/traccar/api/BaseObjectResource.java | 2 | ||||
-rw-r--r-- | src/org/traccar/api/resource/CommandTypeResource.java | 4 | ||||
-rw-r--r-- | src/org/traccar/api/resource/NotificationResource.java | 34 | ||||
-rw-r--r-- | src/org/traccar/api/resource/UserResource.java | 3 | ||||
-rw-r--r-- | src/org/traccar/database/CommandsManager.java | 16 | ||||
-rw-r--r-- | src/org/traccar/database/DataManager.java | 3 | ||||
-rw-r--r-- | src/org/traccar/database/NotificationManager.java | 187 | ||||
-rw-r--r-- | src/org/traccar/database/PermissionsManager.java | 11 | ||||
-rw-r--r-- | src/org/traccar/model/Notification.java | 10 | ||||
-rw-r--r-- | src/org/traccar/model/Typed.java (renamed from src/org/traccar/model/CommandType.java) | 4 | ||||
-rw-r--r-- | swagger.json | 110 |
13 files changed, 233 insertions, 204 deletions
diff --git a/schema/changelog-3.15.xml b/schema/changelog-3.15.xml index f6ed306dc..9756fe696 100644 --- a/schema/changelog-3.15.xml +++ b/schema/changelog-3.15.xml @@ -83,5 +83,55 @@ <column name="limitcommands" type="BOOLEAN" defaultValueBoolean="false" /> </addColumn> + <addColumn tableName="notifications"> + <column name="always" type="BOOLEAN" defaultValueBoolean="false" valueBoolean="true"> + <constraints nullable="false" /> + </column> + </addColumn> + + <createTable tableName="user_notification"> + <column name="userid" type="INT"> + <constraints nullable="false" /> + </column> + <column name="notificationid" type="INT"> + <constraints nullable="false" /> + </column> + </createTable> + + <addForeignKeyConstraint baseTableName="user_notification" baseColumnNames="userid" constraintName="fk_user_notification_userid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" /> + + <sql> + INSERT INTO user_notification (notificationid, userid) SELECT id AS notificationid, userid FROM notifications; + </sql> + + <dropForeignKeyConstraint baseTableName="notifications" constraintName="fk_notifications_userid"/> + <dropColumn tableName="notifications" columnName="userid" /> + + <addForeignKeyConstraint baseTableName="user_notification" baseColumnNames="notificationid" constraintName="fk_user_notification_notificationid" referencedTableName="notifications" referencedColumnNames="id" onDelete="CASCADE" /> + + <createTable tableName="group_notification"> + <column name="groupid" type="INT"> + <constraints nullable="false" /> + </column> + <column name="notificationid" type="INT"> + <constraints nullable="false" /> + </column> + </createTable> + + <addForeignKeyConstraint baseTableName="group_notification" baseColumnNames="groupid" constraintName="fk_group_notification_groupid" referencedTableName="groups" referencedColumnNames="id" onDelete="CASCADE" /> + <addForeignKeyConstraint baseTableName="group_notification" baseColumnNames="notificationid" constraintName="fk_group_notification_notificationid" referencedTableName="notifications" referencedColumnNames="id" onDelete="CASCADE" /> + + <createTable tableName="device_notification"> + <column name="deviceid" type="INT"> + <constraints nullable="false" /> + </column> + <column name="notificationid" type="INT"> + <constraints nullable="false" /> + </column> + </createTable> + + <addForeignKeyConstraint baseTableName="device_notification" baseColumnNames="deviceid" constraintName="fk_device_notification_deviceid" referencedTableName="devices" referencedColumnNames="id" onDelete="CASCADE" /> + <addForeignKeyConstraint baseTableName="device_notification" baseColumnNames="notificationid" constraintName="fk_device_notification_notificationid" referencedTableName="notifications" referencedColumnNames="id" onDelete="CASCADE" /> + </changeSet> </databaseChangeLog> diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java index 210d52429..340eb742c 100644 --- a/src/org/traccar/Context.java +++ b/src/org/traccar/Context.java @@ -62,6 +62,7 @@ import org.traccar.model.Device; import org.traccar.model.Driver; import org.traccar.model.Geofence; import org.traccar.model.Group; +import org.traccar.model.Notification; import org.traccar.model.User; import org.traccar.geolocation.GoogleGeolocationProvider; import org.traccar.geolocation.GeolocationProvider; @@ -433,6 +434,8 @@ public final class Context { return (BaseObjectManager<T>) driversManager; } else if (clazz.equals(Command.class)) { return (BaseObjectManager<T>) commandsManager; + } else if (clazz.equals(Notification.class)) { + return (BaseObjectManager<T>) notificationManager; } return null; } diff --git a/src/org/traccar/api/BaseObjectResource.java b/src/org/traccar/api/BaseObjectResource.java index f0f31a154..634957a49 100644 --- a/src/org/traccar/api/BaseObjectResource.java +++ b/src/org/traccar/api/BaseObjectResource.java @@ -111,8 +111,6 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour if (baseClass.equals(Group.class) || baseClass.equals(Device.class)) { Context.getPermissionsManager().refreshDeviceAndGroupPermissions(); Context.getPermissionsManager().refreshAllExtendedPermissions(); - } else if (baseClass.equals(User.class) && Context.getNotificationManager() != null) { - Context.getNotificationManager().refresh(); } return Response.ok(entity).build(); } diff --git a/src/org/traccar/api/resource/CommandTypeResource.java b/src/org/traccar/api/resource/CommandTypeResource.java index 30f9300cb..0a904bd8a 100644 --- a/src/org/traccar/api/resource/CommandTypeResource.java +++ b/src/org/traccar/api/resource/CommandTypeResource.java @@ -18,7 +18,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; -import org.traccar.model.CommandType; +import org.traccar.model.Typed; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -34,7 +34,7 @@ import java.util.Collection; public class CommandTypeResource extends BaseResource { @GET - public Collection<CommandType> get(@QueryParam("deviceId") long deviceId, + public Collection<Typed> get(@QueryParam("deviceId") long deviceId, @QueryParam("textChannel") boolean textChannel) { if (deviceId != 0) { Context.getPermissionsManager().checkDevice(getUserId(), deviceId); diff --git a/src/org/traccar/api/resource/NotificationResource.java b/src/org/traccar/api/resource/NotificationResource.java index dee972607..540f02926 100644 --- a/src/org/traccar/api/resource/NotificationResource.java +++ b/src/org/traccar/api/resource/NotificationResource.java @@ -15,7 +15,6 @@ */ package org.traccar.api.resource; -import java.sql.SQLException; import java.util.Collection; import javax.mail.MessagingException; @@ -24,14 +23,14 @@ import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.traccar.Context; -import org.traccar.api.BaseResource; +import org.traccar.api.ExtendedObjectResource; import org.traccar.model.Event; import org.traccar.model.Notification; +import org.traccar.model.Typed; import org.traccar.notification.NotificationMail; import org.traccar.notification.NotificationSms; @@ -40,34 +39,23 @@ import com.cloudhopper.smpp.type.SmppChannelException; import com.cloudhopper.smpp.type.SmppTimeoutException; import com.cloudhopper.smpp.type.UnrecoverablePduException; -@Path("users/notifications") +@Path("notifications") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) -public class NotificationResource extends BaseResource { +public class NotificationResource extends ExtendedObjectResource<Notification> { - @GET - public Collection<Notification> get(@QueryParam("all") boolean all, - @QueryParam("userId") long userId) throws SQLException { - if (all) { - return Context.getNotificationManager().getAllNotifications(); - } - if (userId == 0) { - userId = getUserId(); - } - Context.getPermissionsManager().checkUser(getUserId(), userId); - return Context.getNotificationManager().getAllUserNotifications(userId); + public NotificationResource() { + super(Notification.class); } - @POST - public Response update(Notification entity) throws SQLException { - Context.getPermissionsManager().checkReadonly(getUserId()); - Context.getPermissionsManager().checkUser(getUserId(), entity.getUserId()); - Context.getNotificationManager().updateNotification(entity); - return Response.ok(entity).build(); + @GET + @Path("types") + public Collection<Typed> get() { + return Context.getNotificationManager().getAllNotificationTypes(); } - @Path("test") @POST + @Path("test") public Response testMessage() throws MessagingException, RecoverablePduException, UnrecoverablePduException, SmppTimeoutException, SmppChannelException, InterruptedException { NotificationMail.sendMailSync(getUserId(), new Event("test", 0), null); diff --git a/src/org/traccar/api/resource/UserResource.java b/src/org/traccar/api/resource/UserResource.java index 0eb328ab5..0f6f6edba 100644 --- a/src/org/traccar/api/resource/UserResource.java +++ b/src/org/traccar/api/resource/UserResource.java @@ -85,9 +85,6 @@ public class UserResource extends BaseObjectResource<User> { Context.getDataManager().linkObject(User.class, getUserId(), ManagedUser.class, entity.getId(), true); } Context.getUsersManager().refreshUserItems(); - if (Context.getNotificationManager() != null) { - Context.getNotificationManager().refresh(); - } return Response.ok(entity).build(); } diff --git a/src/org/traccar/database/CommandsManager.java b/src/org/traccar/database/CommandsManager.java index deb802b29..521a2e1d1 100644 --- a/src/org/traccar/database/CommandsManager.java +++ b/src/org/traccar/database/CommandsManager.java @@ -26,7 +26,7 @@ import org.traccar.BaseProtocol; import org.traccar.Context; import org.traccar.helper.Log; import org.traccar.model.Command; -import org.traccar.model.CommandType; +import org.traccar.model.Typed; import org.traccar.model.Position; public class CommandsManager extends ExtendedObjectManager<Command> { @@ -102,29 +102,29 @@ public class CommandsManager extends ExtendedObjectManager<Command> { return result; } - public Collection<CommandType> getCommandTypes(long deviceId, boolean textChannel) { - List<CommandType> result = new ArrayList<>(); + public Collection<Typed> getCommandTypes(long deviceId, boolean textChannel) { + List<Typed> result = new ArrayList<>(); Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId); if (lastPosition != null) { BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol()); Collection<String> commands; commands = textChannel ? protocol.getSupportedTextCommands() : protocol.getSupportedDataCommands(); for (String commandKey : commands) { - result.add(new CommandType(commandKey)); + result.add(new Typed(commandKey)); } } else { - result.add(new CommandType(Command.TYPE_CUSTOM)); + result.add(new Typed(Command.TYPE_CUSTOM)); } return result; } - public Collection<CommandType> getAllCommandTypes() { - List<CommandType> result = new ArrayList<>(); + public Collection<Typed> getAllCommandTypes() { + List<Typed> result = new ArrayList<>(); Field[] fields = Command.class.getDeclaredFields(); for (Field field : fields) { if (Modifier.isStatic(field.getModifiers()) && field.getName().startsWith("TYPE_")) { try { - result.add(new CommandType(field.get(null).toString())); + result.add(new Typed(field.get(null).toString())); } catch (IllegalArgumentException | IllegalAccessException error) { Log.warning(error); } diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 261541b4d..e88ff7f0d 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -48,6 +48,7 @@ import org.traccar.model.Event; import org.traccar.model.Geofence; import org.traccar.model.Group; import org.traccar.model.ManagedUser; +import org.traccar.model.Notification; import org.traccar.model.Permission; import org.traccar.model.BaseModel; import org.traccar.model.Calendar; @@ -393,6 +394,8 @@ public class DataManager { return Calendar.class; case "command": return Command.class; + case "notification": + return Notification.class; default: throw new ClassNotFoundException(); } diff --git a/src/org/traccar/database/NotificationManager.java b/src/org/traccar/database/NotificationManager.java index 98cae3499..73041a23f 100644 --- a/src/org/traccar/database/NotificationManager.java +++ b/src/org/traccar/database/NotificationManager.java @@ -1,5 +1,6 @@ /* * Copyright 2016 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,57 +19,70 @@ package org.traccar.database; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.sql.SQLException; -import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import org.traccar.Context; import org.traccar.helper.Log; import org.traccar.model.Event; import org.traccar.model.Notification; import org.traccar.model.Position; +import org.traccar.model.Typed; import org.traccar.notification.NotificationMail; import org.traccar.notification.NotificationSms; -public class NotificationManager { - - private final DataManager dataManager; - - private final Map<Long, Set<Notification>> userNotifications = new HashMap<>(); - - private final ReadWriteLock notificationsLock = new ReentrantReadWriteLock(); +public class NotificationManager extends ExtendedObjectManager<Notification> { public NotificationManager(DataManager dataManager) { - this.dataManager = dataManager; - refresh(); + super(dataManager, Notification.class); + } + + private Set<Long> getEffectiveNotifications(long userId, long deviceId) { + Set<Long> result = new HashSet<>(); + Set<Long> deviceNotifications = getAllDeviceItems(deviceId); + for (long itemId : getUserItems(userId)) { + if (getById(itemId).getAlways() || deviceNotifications.contains(itemId)) { + result.add(itemId); + } + } + return result; } public void updateEvent(Event event, Position position) { try { - dataManager.addObject(event); + getDataManager().addObject(event); } catch (SQLException error) { Log.warning(error); } - Set<Long> users = Context.getPermissionsManager().getDeviceUsers(event.getDeviceId()); + long deviceId = event.getDeviceId(); + Set<Long> users = Context.getPermissionsManager().getDeviceUsers(deviceId); for (long userId : users) { if (event.getGeofenceId() == 0 || Context.getGeofenceManager() != null && Context.getGeofenceManager().checkItemPermission(userId, event.getGeofenceId())) { - Notification notification = getUserNotificationByType(userId, event.getType()); - if (notification != null) { - if (notification.getWeb()) { - Context.getConnectionManager().updateEvent(userId, event); - } - if (notification.getMail()) { - NotificationMail.sendMailAsync(userId, event, position); + boolean sentWeb = false; + boolean sentMail = false; + boolean sentSms = Context.getSmppManager() == null; + for (long notificationId : getEffectiveNotifications(userId, deviceId)) { + Notification notification = getById(notificationId); + if (getById(notificationId).getType().equals(event.getType())) { + if (!sentWeb && notification.getWeb()) { + Context.getConnectionManager().updateEvent(userId, event); + sentWeb = true; + } + if (!sentMail && notification.getMail()) { + NotificationMail.sendMailAsync(userId, event, position); + sentMail = true; + } + if (!sentSms && notification.getSms()) { + NotificationSms.sendSmsAsync(userId, event, position); + sentSms = true; + } } - if (notification.getSms()) { - NotificationSms.sendSmsAsync(userId, event, position); + if (sentWeb && sentMail && sentSms) { + break; } } } @@ -84,135 +98,18 @@ public class NotificationManager { } } - private Set<Notification> getUserNotificationsUnsafe(long userId) { - if (!userNotifications.containsKey(userId)) { - userNotifications.put(userId, new HashSet<Notification>()); - } - return userNotifications.get(userId); - } - - public Set<Notification> getUserNotifications(long userId) { - notificationsLock.readLock().lock(); - try { - return getUserNotificationsUnsafe(userId); - } finally { - notificationsLock.readLock().unlock(); - } - } - - public final void refresh() { - if (dataManager != null) { - try { - notificationsLock.writeLock().lock(); - try { - userNotifications.clear(); - for (Notification notification : dataManager.getObjects(Notification.class)) { - getUserNotificationsUnsafe(notification.getUserId()).add(notification); - } - } finally { - notificationsLock.writeLock().unlock(); - } - } catch (SQLException error) { - Log.warning(error); - } - } - } - - public Notification getUserNotificationByType(long userId, String type) { - notificationsLock.readLock().lock(); - try { - for (Notification notification : getUserNotificationsUnsafe(userId)) { - if (notification.getType().equals(type)) { - return notification; - } - } - } finally { - notificationsLock.readLock().unlock(); - } - return null; - } - - public void updateNotification(Notification notification) { - Notification cachedNotification = getUserNotificationByType(notification.getUserId(), notification.getType()); - if (cachedNotification != null) { - if (cachedNotification.getWeb() != notification.getWeb() - || cachedNotification.getMail() != notification.getMail() - || cachedNotification.getSms() != notification.getSms()) { - if (!notification.getWeb() && !notification.getMail() && !notification.getSms()) { - try { - dataManager.removeObject(Notification.class, cachedNotification.getId()); - } catch (SQLException error) { - Log.warning(error); - } - notificationsLock.writeLock().lock(); - try { - getUserNotificationsUnsafe(notification.getUserId()).remove(cachedNotification); - } finally { - notificationsLock.writeLock().unlock(); - } - } else { - notificationsLock.writeLock().lock(); - try { - cachedNotification.setWeb(notification.getWeb()); - cachedNotification.setMail(notification.getMail()); - cachedNotification.setSms(notification.getSms()); - cachedNotification.setAttributes(notification.getAttributes()); - } finally { - notificationsLock.writeLock().unlock(); - } - try { - dataManager.updateObject(cachedNotification); - } catch (SQLException error) { - Log.warning(error); - } - } - } else { - notification.setId(cachedNotification.getId()); - } - } else if (notification.getWeb() || notification.getMail() || notification.getSms()) { - try { - dataManager.addObject(notification); - } catch (SQLException error) { - Log.warning(error); - } - notificationsLock.writeLock().lock(); - try { - getUserNotificationsUnsafe(notification.getUserId()).add(notification); - } finally { - notificationsLock.writeLock().unlock(); - } - } - } - - public Set<Notification> getAllNotifications() { - Set<Notification> notifications = new HashSet<>(); - long id = 1; + public Set<Typed> getAllNotificationTypes() { + Set<Typed> types = new HashSet<>(); Field[] fields = Event.class.getDeclaredFields(); for (Field field : fields) { if (Modifier.isStatic(field.getModifiers()) && field.getName().startsWith("TYPE_")) { try { - Notification notification = new Notification(); - notification.setType(field.get(null).toString()); - notification.setId(id++); - notifications.add(notification); + types.add(new Typed(field.get(null).toString())); } catch (IllegalArgumentException | IllegalAccessException error) { Log.warning(error); } } } - return notifications; + return types; } - - public Collection<Notification> getAllUserNotifications(long userId) { - Map<String, Notification> notifications = new HashMap<>(); - for (Notification notification : getAllNotifications()) { - notification.setUserId(userId); - notifications.put(notification.getType(), notification); - } - for (Notification notification : getUserNotifications(userId)) { - notifications.put(notification.getType(), notification); - } - return notifications.values(); - } - } diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 0d9c780a6..07b60ba58 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -26,6 +26,7 @@ import org.traccar.model.Driver; import org.traccar.model.Geofence; import org.traccar.model.Group; import org.traccar.model.ManagedUser; +import org.traccar.model.Notification; import org.traccar.model.Permission; import org.traccar.model.Server; import org.traccar.model.User; @@ -320,6 +321,8 @@ public class PermissionsManager { manager = Context.getCalendarManager(); } else if (object.equals(Command.class)) { manager = Context.getCommandsManager(); + } else if (object.equals(Notification.class)) { + manager = Context.getNotificationManager(); } else { throw new IllegalArgumentException("Unknown object type"); } @@ -344,7 +347,7 @@ public class PermissionsManager { Context.getAttributesManager().refreshUserItems(); Context.getCommandsManager().refreshUserItems(); if (Context.getNotificationManager() != null) { - Context.getNotificationManager().refresh(); + Context.getNotificationManager().refreshUserItems(); } } @@ -375,6 +378,9 @@ public class PermissionsManager { Context.getCalendarManager().refreshUserItems(); } else if (permission.getPropertyClass().equals(Command.class)) { Context.getCommandsManager().refreshUserItems(); + } else if (permission.getPropertyClass().equals(Notification.class) + && Context.getNotificationManager() != null) { + Context.getNotificationManager().refreshUserItems(); } } else if (permission.getOwnerClass().equals(Device.class) || permission.getOwnerClass().equals(Group.class)) { if (permission.getPropertyClass().equals(Geofence.class) && Context.getGeofenceManager() != null) { @@ -385,6 +391,9 @@ public class PermissionsManager { Context.getAttributesManager().refreshExtendedPermissions(); } else if (permission.getPropertyClass().equals(Command.class)) { Context.getCommandsManager().refreshExtendedPermissions(); + } else if (permission.getPropertyClass().equals(Notification.class) + && Context.getNotificationManager() != null) { + Context.getNotificationManager().refreshExtendedPermissions(); } } } diff --git a/src/org/traccar/model/Notification.java b/src/org/traccar/model/Notification.java index e7bb69903..9d6034fff 100644 --- a/src/org/traccar/model/Notification.java +++ b/src/org/traccar/model/Notification.java @@ -17,14 +17,14 @@ package org.traccar.model; public class Notification extends ExtendedModel { - private long userId; + private boolean always; - public long getUserId() { - return userId; + public boolean getAlways() { + return always; } - public void setUserId(long userId) { - this.userId = userId; + public void setAlways(boolean always) { + this.always = always; } private String type; diff --git a/src/org/traccar/model/CommandType.java b/src/org/traccar/model/Typed.java index 210316f71..313ec7bcd 100644 --- a/src/org/traccar/model/CommandType.java +++ b/src/org/traccar/model/Typed.java @@ -15,11 +15,11 @@ */ package org.traccar.model; -public class CommandType { +public class Typed { private String type; - public CommandType(String type) { + public Typed(String type) { this.type = type; } diff --git a/swagger.json b/swagger.json index 762ef3525..5f9abb9b8 100644 --- a/swagger.json +++ b/swagger.json @@ -627,19 +627,25 @@ } } }, - "/users/notifications": { + "/notifications": { "get": { - "summary": "Fetch a list of Notification types", - "description": "Without params, it returns a list of the user's enabled Notifications", + "summary": "Fetch a list of Notifications", + "description": "Without params, it returns a list of Notifications the user has access to", "parameters": [ { - "name": "all", - "in": "query", - "description": "To fetch a list of all available Notifications", - "type": "boolean" + "$ref": "#/parameters/all" }, { "$ref": "#/parameters/userId" + }, + { + "$ref": "#/parameters/deviceId" + }, + { + "$ref": "#/parameters/groupId" + }, + { + "$ref": "#/parameters/refresh" } ], "responses": { @@ -655,16 +661,32 @@ } }, "post": { - "summary": "Set or unset a Notification", + "summary": "Create a Notification", "parameters": [ { - "name": "body", - "in": "body", - "required": true, + "$ref": "#/parameters/Notification" + } + ], + "responses": { + "200": { + "description": "OK", "schema": { "$ref": "#/definitions/Notification" } } + } + } + }, + "/notifications/{id}": { + "put": { + "summary": "Update a Notification", + "parameters": [ + { + "$ref": "#/parameters/entityId" + }, + { + "$ref": "#/parameters/Notification" + } ], "responses": { "200": { @@ -674,6 +696,50 @@ } } } + }, + "delete": { + "summary": "Delete a Notification", + "parameters": [ + { + "$ref": "#/parameters/entityId" + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/notifications/types": { + "get": { + "summary": "Fetch a list of available Notification types", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/NotificationType" + } + } + } + } + } + }, + "/notifications/test": { + "post": { + "summary": "Send test notification to current user via Email and SMS", + "parameters": [], + "responses": { + "204": { + "description": "Successful sending" + }, + "400": { + "description": "Could happen if sending has failed" + } + } } }, "/commandtypes": { @@ -1604,8 +1670,8 @@ "type": { "type": "string" }, - "userId": { - "type": "integer" + "always": { + "type": "boolean" }, "web": { "type": "boolean" @@ -1613,9 +1679,19 @@ "mail": { "type": "boolean" }, + "sms": { + "type": "boolean" + }, "attributes": {} } }, + "NotificationType": { + "properties": { + "type": { + "type": "string" + } + } + }, "Event": { "properties": { "id": { @@ -1966,6 +2042,14 @@ "$ref": "#/definitions/Command" } }, + "Notification": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Notification" + } + }, "deviceIdArray": { "name": "deviceId", "in": "query", |