aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2017-09-13 22:15:49 +1200
committerGitHub <noreply@github.com>2017-09-13 22:15:49 +1200
commit8a45a056b7e0814526904e915c3886b29ba2833a (patch)
treedc821e2134f4ae2c9881ce8de006a29b33da289f
parente05f0b83a911c522123a5a2cd14d6c16bd2de027 (diff)
parent7530522cbca477cb822cb494ffe12480e5237934 (diff)
downloadtraccar-server-8a45a056b7e0814526904e915c3886b29ba2833a.tar.gz
traccar-server-8a45a056b7e0814526904e915c3886b29ba2833a.tar.bz2
traccar-server-8a45a056b7e0814526904e915c3886b29ba2833a.zip
Merge pull request #3522 from Abyss777/saved_commands
Implement Saved Commands
-rw-r--r--schema/changelog-3.15.xml64
-rw-r--r--src/org/traccar/Context.java12
-rw-r--r--src/org/traccar/api/BaseObjectResource.java9
-rw-r--r--src/org/traccar/api/resource/CommandResource.java43
-rw-r--r--src/org/traccar/api/resource/CommandTypeResource.java8
-rw-r--r--src/org/traccar/api/resource/DeviceResource.java2
-rw-r--r--src/org/traccar/api/resource/UserResource.java10
-rw-r--r--src/org/traccar/database/CommandsManager.java136
-rw-r--r--src/org/traccar/database/DataManager.java3
-rw-r--r--src/org/traccar/database/DeviceManager.java51
-rw-r--r--src/org/traccar/database/PermissionsManager.java56
-rw-r--r--src/org/traccar/model/Command.java18
-rw-r--r--src/org/traccar/model/Server.java10
-rw-r--r--src/org/traccar/model/User.java10
14 files changed, 351 insertions, 81 deletions
diff --git a/schema/changelog-3.15.xml b/schema/changelog-3.15.xml
index 37fd2e278..f6ed306dc 100644
--- a/schema/changelog-3.15.xml
+++ b/schema/changelog-3.15.xml
@@ -7,7 +7,7 @@
logicalFilePath="changelog-3.15">
<changeSet author="author" id="changelog-3.15">
-
+
<dropForeignKeyConstraint baseTableName="attribute_aliases" constraintName="fk_attribute_aliases_deviceid" />
<dropUniqueConstraint tableName="attribute_aliases" constraintName="uk_deviceid_attribute" />
@@ -21,5 +21,67 @@
<dropColumn tableName="users" columnName="speedunit" />
<dropColumn tableName="users" columnName="distanceunit" />
+ <createTable tableName="commands">
+ <column name="id" type="INT" autoIncrement="true">
+ <constraints primaryKey="true" />
+ </column>
+ <column name="description" type="VARCHAR(4000)">
+ <constraints nullable="false" />
+ </column>
+ <column name="type" type="VARCHAR(128)">
+ <constraints nullable="false" />
+ </column>
+ <column name="textchannel" type="BOOLEAN" defaultValueBoolean="false">
+ <constraints nullable="false" />
+ </column>
+ <column name="attributes" type="VARCHAR(4000)">
+ <constraints nullable="false" />
+ </column>
+ </createTable>
+
+ <createTable tableName="user_command">
+ <column name="userid" type="INT">
+ <constraints nullable="false" />
+ </column>
+ <column name="commandid" type="INT">
+ <constraints nullable="false" />
+ </column>
+ </createTable>
+
+ <addForeignKeyConstraint baseTableName="user_command" baseColumnNames="userid" constraintName="fk_user_command_userid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
+ <addForeignKeyConstraint baseTableName="user_command" baseColumnNames="commandid" constraintName="fk_user_command_commandid" referencedTableName="commands" referencedColumnNames="id" onDelete="CASCADE" />
+
+ <createTable tableName="group_command">
+ <column name="groupid" type="INT">
+ <constraints nullable="false" />
+ </column>
+ <column name="commandid" type="INT">
+ <constraints nullable="false" />
+ </column>
+ </createTable>
+
+ <addForeignKeyConstraint baseTableName="group_command" baseColumnNames="groupid" constraintName="fk_group_command_groupid" referencedTableName="groups" referencedColumnNames="id" onDelete="CASCADE" />
+ <addForeignKeyConstraint baseTableName="group_command" baseColumnNames="commandid" constraintName="fk_group_command_commandid" referencedTableName="commands" referencedColumnNames="id" onDelete="CASCADE" />
+
+ <createTable tableName="device_command">
+ <column name="deviceid" type="INT">
+ <constraints nullable="false" />
+ </column>
+ <column name="commandid" type="INT">
+ <constraints nullable="false" />
+ </column>
+ </createTable>
+
+ <addForeignKeyConstraint baseTableName="device_command" baseColumnNames="deviceid" constraintName="fk_device_command_deviceid" referencedTableName="devices" referencedColumnNames="id" onDelete="CASCADE" />
+ <addForeignKeyConstraint baseTableName="device_command" baseColumnNames="commandid" constraintName="fk_device_command_commandid" referencedTableName="commands" referencedColumnNames="id" onDelete="CASCADE" />
+
+ <addColumn tableName="servers">
+ <column name="limitcommands" type="BOOLEAN" defaultValueBoolean="false" />
+ </addColumn>
+
+ <addColumn tableName="users">
+ <column name="limitcommands" type="BOOLEAN" defaultValueBoolean="false" />
+ </addColumn>
+
</changeSet>
</databaseChangeLog>
diff --git a/src/org/traccar/Context.java b/src/org/traccar/Context.java
index 87d8257ee..210d52429 100644
--- a/src/org/traccar/Context.java
+++ b/src/org/traccar/Context.java
@@ -26,6 +26,7 @@ import java.util.Properties;
import org.apache.velocity.app.VelocityEngine;
import org.eclipse.jetty.util.URIUtil;
import org.traccar.database.CalendarManager;
+import org.traccar.database.CommandsManager;
import org.traccar.database.AttributesManager;
import org.traccar.database.BaseObjectManager;
import org.traccar.database.ConnectionManager;
@@ -56,6 +57,7 @@ import org.traccar.helper.Log;
import org.traccar.model.Attribute;
import org.traccar.model.BaseModel;
import org.traccar.model.Calendar;
+import org.traccar.model.Command;
import org.traccar.model.Device;
import org.traccar.model.Driver;
import org.traccar.model.Geofence;
@@ -213,6 +215,12 @@ public final class Context {
return driversManager;
}
+ private static CommandsManager commandsManager;
+
+ public static CommandsManager getCommandsManager() {
+ return commandsManager;
+ }
+
private static StatisticsManager statisticsManager;
public static StatisticsManager getStatisticsManager() {
@@ -392,6 +400,8 @@ public final class Context {
driversManager = new DriversManager(dataManager);
+ commandsManager = new CommandsManager(dataManager);
+
statisticsManager = new StatisticsManager();
if (config.getBoolean("sms.smpp.enable")) {
@@ -421,6 +431,8 @@ public final class Context {
return (BaseObjectManager<T>) geofenceManager;
} else if (clazz.equals(Driver.class)) {
return (BaseObjectManager<T>) driversManager;
+ } else if (clazz.equals(Command.class)) {
+ return (BaseObjectManager<T>) commandsManager;
}
return null;
}
diff --git a/src/org/traccar/api/BaseObjectResource.java b/src/org/traccar/api/BaseObjectResource.java
index b13dc2e71..f0f31a154 100644
--- a/src/org/traccar/api/BaseObjectResource.java
+++ b/src/org/traccar/api/BaseObjectResource.java
@@ -32,6 +32,7 @@ import org.traccar.database.ExtendedObjectManager;
import org.traccar.database.ManagableObjects;
import org.traccar.database.SimpleObjectManager;
import org.traccar.model.BaseModel;
+import org.traccar.model.Command;
import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.model.User;
@@ -51,7 +52,7 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
protected final Set<Long> getSimpleManagerItems(BaseObjectManager<T> manager, boolean all, long userId) {
Set<Long> result = null;
if (all) {
- if (Context.getPermissionsManager().isAdmin(getUserId())) {
+ if (Context.getPermissionsManager().getUserAdmin(getUserId())) {
result = manager.getAllItems();
} else {
Context.getPermissionsManager().checkManager(getUserId());
@@ -73,6 +74,8 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
if (baseClass.equals(Device.class)) {
Context.getPermissionsManager().checkDeviceReadonly(getUserId());
Context.getPermissionsManager().checkDeviceLimit(getUserId());
+ } else if (baseClass.equals(Command.class)) {
+ Context.getPermissionsManager().checkLimitCommands(getUserId());
}
BaseObjectManager<T> manager = Context.getManager(baseClass);
@@ -98,6 +101,8 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
} else if (baseClass.equals(User.class)) {
User before = Context.getPermissionsManager().getUser(entity.getId());
Context.getPermissionsManager().checkUserUpdate(getUserId(), before, (User) entity);
+ } else if (baseClass.equals(Command.class)) {
+ Context.getPermissionsManager().checkLimitCommands(getUserId());
}
Context.getPermissionsManager().checkPermission(baseClass, getUserId(), entity.getId());
@@ -118,6 +123,8 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
Context.getPermissionsManager().checkReadonly(getUserId());
if (baseClass.equals(Device.class)) {
Context.getPermissionsManager().checkDeviceReadonly(getUserId());
+ } else if (baseClass.equals(Command.class)) {
+ Context.getPermissionsManager().checkLimitCommands(getUserId());
}
Context.getPermissionsManager().checkPermission(baseClass, getUserId(), id);
diff --git a/src/org/traccar/api/resource/CommandResource.java b/src/org/traccar/api/resource/CommandResource.java
index 9ed92d3d5..6a258497f 100644
--- a/src/org/traccar/api/resource/CommandResource.java
+++ b/src/org/traccar/api/resource/CommandResource.java
@@ -16,26 +16,59 @@
package org.traccar.api.resource;
import org.traccar.Context;
-import org.traccar.api.BaseResource;
+import org.traccar.api.ExtendedObjectResource;
+import org.traccar.database.CommandsManager;
import org.traccar.model.Command;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.ws.rs.Consumes;
+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;
@Path("commands")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
-public class CommandResource extends BaseResource {
+public class CommandResource extends ExtendedObjectResource<Command> {
+
+ public CommandResource() {
+ super(Command.class);
+ }
+
+ @GET
+ @Path("send")
+ public Collection<Command> get(@QueryParam("deviceId") long deviceId) throws SQLException {
+ Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
+ CommandsManager commandsManager = Context.getCommandsManager();
+ Set<Long> result = new HashSet<>(commandsManager.getUserItems(getUserId()));
+ result.retainAll(commandsManager.getSupportedCommands(deviceId));
+ return commandsManager.getItems(result);
+ }
@POST
- public Response add(Command entity) throws Exception {
+ @Path("send")
+ public Response send(Command entity) throws Exception {
Context.getPermissionsManager().checkReadonly(getUserId());
- Context.getPermissionsManager().checkDevice(getUserId(), entity.getDeviceId());
- Context.getDeviceManager().sendCommand(entity);
+ long deviceId = entity.getDeviceId();
+ long id = entity.getId();
+ if (deviceId != 0 && id != 0) {
+ Context.getPermissionsManager().checkPermission(Command.class, getUserId(), id);
+ Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
+ Context.getPermissionsManager().checkUserDeviceCommand(getUserId(), deviceId, id);
+ Context.getCommandsManager().sendCommand(id, deviceId);
+ } else {
+ Context.getPermissionsManager().checkLimitCommands(getUserId());
+ Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
+ Context.getCommandsManager().sendCommand(entity);
+ }
return Response.ok(entity).build();
}
diff --git a/src/org/traccar/api/resource/CommandTypeResource.java b/src/org/traccar/api/resource/CommandTypeResource.java
index d5d220547..30f9300cb 100644
--- a/src/org/traccar/api/resource/CommandTypeResource.java
+++ b/src/org/traccar/api/resource/CommandTypeResource.java
@@ -36,8 +36,12 @@ public class CommandTypeResource extends BaseResource {
@GET
public Collection<CommandType> get(@QueryParam("deviceId") long deviceId,
@QueryParam("textChannel") boolean textChannel) {
- Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
- return Context.getDeviceManager().getCommandTypes(deviceId, textChannel);
+ if (deviceId != 0) {
+ Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
+ return Context.getCommandsManager().getCommandTypes(deviceId, textChannel);
+ } else {
+ return Context.getCommandsManager().getAllCommandTypes();
+ }
}
}
diff --git a/src/org/traccar/api/resource/DeviceResource.java b/src/org/traccar/api/resource/DeviceResource.java
index 1c2c653a4..1fae92dc7 100644
--- a/src/org/traccar/api/resource/DeviceResource.java
+++ b/src/org/traccar/api/resource/DeviceResource.java
@@ -53,7 +53,7 @@ public class DeviceResource extends BaseObjectResource<Device> {
DeviceManager deviceManager = Context.getDeviceManager();
Set<Long> result = null;
if (all) {
- if (Context.getPermissionsManager().isAdmin(getUserId())) {
+ if (Context.getPermissionsManager().getUserAdmin(getUserId())) {
result = deviceManager.getAllItems();
} else {
Context.getPermissionsManager().checkManager(getUserId());
diff --git a/src/org/traccar/api/resource/UserResource.java b/src/org/traccar/api/resource/UserResource.java
index b22e01216..0eb328ab5 100644
--- a/src/org/traccar/api/resource/UserResource.java
+++ b/src/org/traccar/api/resource/UserResource.java
@@ -48,13 +48,13 @@ public class UserResource extends BaseObjectResource<User> {
public Collection<User> get(@QueryParam("userId") long userId) throws SQLException {
UsersManager usersManager = Context.getUsersManager();
Set<Long> result = null;
- if (Context.getPermissionsManager().isAdmin(getUserId())) {
+ if (Context.getPermissionsManager().getUserAdmin(getUserId())) {
if (userId != 0) {
result = usersManager.getUserItems(userId);
} else {
result = usersManager.getAllItems();
}
- } else if (Context.getPermissionsManager().isManager(getUserId())) {
+ } else if (Context.getPermissionsManager().getUserManager(getUserId())) {
result = usersManager.getManagedItems(getUserId());
} else {
throw new SecurityException("Admin or manager access required");
@@ -66,9 +66,9 @@ public class UserResource extends BaseObjectResource<User> {
@PermitAll
@POST
public Response add(User entity) throws SQLException {
- if (!Context.getPermissionsManager().isAdmin(getUserId())) {
+ if (!Context.getPermissionsManager().getUserAdmin(getUserId())) {
Context.getPermissionsManager().checkUserUpdate(getUserId(), new User(), entity);
- if (Context.getPermissionsManager().isManager(getUserId())) {
+ if (Context.getPermissionsManager().getUserManager(getUserId())) {
Context.getPermissionsManager().checkUserLimit(getUserId());
} else {
Context.getPermissionsManager().checkRegistration(getUserId());
@@ -81,7 +81,7 @@ public class UserResource extends BaseObjectResource<User> {
}
}
Context.getUsersManager().addItem(entity);
- if (Context.getPermissionsManager().isManager(getUserId())) {
+ if (Context.getPermissionsManager().getUserManager(getUserId())) {
Context.getDataManager().linkObject(User.class, getUserId(), ManagedUser.class, entity.getId(), true);
}
Context.getUsersManager().refreshUserItems();
diff --git a/src/org/traccar/database/CommandsManager.java b/src/org/traccar/database/CommandsManager.java
new file mode 100644
index 000000000..deb802b29
--- /dev/null
+++ b/src/org/traccar/database/CommandsManager.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2017 Anton Tananaev (anton@traccar.org)
+ * Copyright 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.
+ * 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 org.traccar.database;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+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.Position;
+
+public class CommandsManager extends ExtendedObjectManager<Command> {
+
+ private boolean fallbackToText;
+
+ public CommandsManager(DataManager dataManager) {
+ super(dataManager, Command.class);
+ fallbackToText = Context.getConfig().getBoolean("command.fallbackToSms");
+ }
+
+ public boolean checkDeviceCommand(long deviceId, long commandId) {
+ return !getAllDeviceItems(deviceId).contains(commandId);
+ }
+
+ public void sendCommand(Command command) throws Exception {
+ sendCommand(command, command.getDeviceId(), fallbackToText);
+ }
+
+ public void sendCommand(long commandId, long deviceId) throws Exception {
+ sendCommand(getById(commandId), deviceId, false);
+ }
+
+ public void sendCommand(Command command, long deviceId, boolean fallbackToText) throws Exception {
+ if (command.getTextChannel()) {
+ Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId);
+ String phone = Context.getIdentityManager().getById(deviceId).getPhone();
+ if (lastPosition != null) {
+ BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol());
+ protocol.sendTextCommand(phone, command);
+ } else if (command.getType().equals(Command.TYPE_CUSTOM)) {
+ if (Context.getSmppManager() != null) {
+ Context.getSmppManager().sendMessageSync(phone, command.getString(Command.KEY_DATA), true);
+ } else {
+ throw new RuntimeException("SMPP client is not enabled");
+ }
+ } else {
+ throw new RuntimeException("Command " + command.getType() + " is not supported");
+ }
+ } else {
+ ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(deviceId);
+ if (activeDevice != null) {
+ activeDevice.sendCommand(command);
+ } else {
+ if (fallbackToText) {
+ command.setTextChannel(true);
+ sendCommand(command, deviceId, false);
+ } else {
+ throw new RuntimeException("Device is not online");
+ }
+ }
+ }
+ }
+
+ public Collection<Long> getSupportedCommands(long deviceId) {
+ List<Long> result = new ArrayList<>();
+ Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId);
+ boolean online = Context.getConnectionManager().getActiveDevice(deviceId) != null;
+ for (long commandId : getAllDeviceItems(deviceId)) {
+ Command command = getById(commandId);
+ if (command.getTextChannel() || online) {
+ if (lastPosition != null) {
+ BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol());
+ if (protocol.getSupportedTextCommands().contains(command.getType())
+ || online && protocol.getSupportedDataCommands().contains(command.getType())) {
+ result.add(commandId);
+ }
+ } else if (command.getType().equals(Command.TYPE_CUSTOM)) {
+ result.add(commandId);
+ }
+ }
+ }
+ return result;
+ }
+
+ public Collection<CommandType> getCommandTypes(long deviceId, boolean textChannel) {
+ List<CommandType> 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));
+ }
+ } else {
+ result.add(new CommandType(Command.TYPE_CUSTOM));
+ }
+ return result;
+ }
+
+ public Collection<CommandType> getAllCommandTypes() {
+ List<CommandType> 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()));
+ } catch (IllegalArgumentException | IllegalAccessException error) {
+ Log.warning(error);
+ }
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java
index 4535a9c38..261541b4d 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/org/traccar/database/DataManager.java
@@ -51,6 +51,7 @@ import org.traccar.model.ManagedUser;
import org.traccar.model.Permission;
import org.traccar.model.BaseModel;
import org.traccar.model.Calendar;
+import org.traccar.model.Command;
import org.traccar.model.Position;
import org.traccar.model.Server;
import org.traccar.model.Statistics;
@@ -390,6 +391,8 @@ public class DataManager {
return Attribute.class;
case "calendar":
return Calendar.class;
+ case "command":
+ return Command.class;
default:
throw new ClassNotFoundException();
}
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
index 2157e738d..1eb90b7eb 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/org/traccar/database/DeviceManager.java
@@ -16,7 +16,6 @@
package org.traccar.database;
import java.sql.SQLException;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
@@ -26,12 +25,9 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
-import org.traccar.BaseProtocol;
import org.traccar.Config;
import org.traccar.Context;
import org.traccar.helper.Log;
-import org.traccar.model.Command;
-import org.traccar.model.CommandType;
import org.traccar.model.Device;
import org.traccar.model.DeviceState;
import org.traccar.model.DeviceTotalDistance;
@@ -55,8 +51,6 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
private final Map<Long, DeviceState> deviceStates = new ConcurrentHashMap<>();
- private boolean fallbackToText;
-
public DeviceManager(DataManager dataManager) {
super(dataManager, Device.class);
this.config = Context.getConfig();
@@ -68,7 +62,6 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
dataRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000;
lookupGroupsAttribute = config.getBoolean("deviceManager.lookupGroupsAttribute");
- fallbackToText = config.getBoolean("command.fallbackToSms");
refreshLastPositions();
}
@@ -344,50 +337,6 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
}
- public void sendCommand(Command command) throws Exception {
- long deviceId = command.getDeviceId();
- if (command.getTextChannel()) {
- Position lastPosition = getLastPosition(deviceId);
- if (lastPosition != null) {
- BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol());
- protocol.sendTextCommand(getById(deviceId).getPhone(), command);
- } else if (command.getType().equals(Command.TYPE_CUSTOM)) {
- Context.getSmppManager().sendMessageSync(getById(deviceId).getPhone(),
- command.getString(Command.KEY_DATA), true);
- } else {
- throw new RuntimeException("Command " + command.getType() + " is not supported");
- }
- } else {
- ActiveDevice activeDevice = Context.getConnectionManager().getActiveDevice(deviceId);
- if (activeDevice != null) {
- activeDevice.sendCommand(command);
- } else {
- if (fallbackToText) {
- command.setTextChannel(true);
- sendCommand(command);
- } else {
- throw new RuntimeException("Device is not online");
- }
- }
- }
- }
-
- public Collection<CommandType> getCommandTypes(long deviceId, boolean textChannel) {
- List<CommandType> result = new ArrayList<>();
- Position lastPosition = Context.getDeviceManager().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));
- }
- } else {
- result.add(new CommandType(Command.TYPE_CUSTOM));
- }
- return result;
- }
-
public DeviceState getDeviceState(long deviceId) {
DeviceState deviceState = deviceStates.get(deviceId);
if (deviceState == null) {
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java
index 0708cc5c9..0d9c780a6 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/org/traccar/database/PermissionsManager.java
@@ -20,6 +20,7 @@ import org.traccar.helper.Log;
import org.traccar.model.Attribute;
import org.traccar.model.BaseModel;
import org.traccar.model.Calendar;
+import org.traccar.model.Command;
import org.traccar.model.Device;
import org.traccar.model.Driver;
import org.traccar.model.Geofence;
@@ -136,24 +137,24 @@ public class PermissionsManager {
}
}
- public boolean isAdmin(long userId) {
+ public boolean getUserAdmin(long userId) {
User user = getUser(userId);
return user != null && user.getAdmin();
}
public void checkAdmin(long userId) throws SecurityException {
- if (!isAdmin(userId)) {
+ if (!getUserAdmin(userId)) {
throw new SecurityException("Admin access required");
}
}
- public boolean isManager(long userId) {
+ public boolean getUserManager(long userId) {
User user = getUser(userId);
return user != null && user.getUserLimit() != 0;
}
public void checkManager(long userId) throws SecurityException {
- if (!isManager(userId)) {
+ if (!getUserManager(userId)) {
throw new SecurityException("Manager access required");
}
}
@@ -176,7 +177,7 @@ public class PermissionsManager {
int deviceLimit = getUser(userId).getDeviceLimit();
if (deviceLimit != -1) {
int deviceCount = 0;
- if (isManager(userId)) {
+ if (getUserManager(userId)) {
deviceCount = Context.getDeviceManager().getManagedItems(userId).size();
} else {
deviceCount = Context.getDeviceManager().getUserItems(userId).size();
@@ -187,28 +188,45 @@ public class PermissionsManager {
}
}
- public boolean isReadonly(long userId) {
+ public boolean getUserReadonly(long userId) {
User user = getUser(userId);
return user != null && user.getReadonly();
}
- public boolean isDeviceReadonly(long userId) {
+ public boolean getUserDeviceReadonly(long userId) {
User user = getUser(userId);
return user != null && user.getDeviceReadonly();
}
+ public boolean getUserLimitCommands(long userId) {
+ User user = getUser(userId);
+ return user != null && user.getLimitCommands();
+ }
+
public void checkReadonly(long userId) throws SecurityException {
- if (!isAdmin(userId) && (server.getReadonly() || isReadonly(userId))) {
+ if (!getUserAdmin(userId) && (server.getReadonly() || getUserReadonly(userId))) {
throw new SecurityException("Account is readonly");
}
}
public void checkDeviceReadonly(long userId) throws SecurityException {
- if (!isAdmin(userId) && (server.getDeviceReadonly() || isDeviceReadonly(userId))) {
+ if (!getUserAdmin(userId) && (server.getDeviceReadonly() || getUserDeviceReadonly(userId))) {
throw new SecurityException("Account is device readonly");
}
}
+ public void checkLimitCommands(long userId) throws SecurityException {
+ if (!getUserAdmin(userId) && (server.getLimitCommands() || getUserLimitCommands(userId))) {
+ throw new SecurityException("Account has limit sending commands");
+ }
+ }
+
+ public void checkUserDeviceCommand(long userId, long deviceId, long commandId) throws SecurityException {
+ if (!getUserAdmin(userId) && Context.getCommandsManager().checkDeviceCommand(deviceId, commandId)) {
+ throw new SecurityException("Command can not be sent to this device");
+ }
+ }
+
public void checkUserEnabled(long userId) throws SecurityException {
User user = getUser(userId);
if (user == null) {
@@ -240,20 +258,20 @@ public class PermissionsManager {
if (userId == after.getId()) {
checkAdmin(userId);
}
- if (!isAdmin(userId)) {
+ if (!getUserAdmin(userId)) {
checkManager(userId);
}
}
}
public void checkUser(long userId, long managedUserId) throws SecurityException {
- if (userId != managedUserId && !isAdmin(userId)) {
+ if (userId != managedUserId && !getUserAdmin(userId)) {
checkManager(userId, managedUserId);
}
}
public void checkGroup(long userId, long groupId) throws SecurityException {
- if (!getGroupPermissions(userId).contains(groupId) && !isAdmin(userId)) {
+ if (!getGroupPermissions(userId).contains(groupId) && !getUserAdmin(userId)) {
checkManager(userId);
for (long managedUserId : usersManager.getUserItems(userId)) {
if (getGroupPermissions(managedUserId).contains(groupId)) {
@@ -265,7 +283,7 @@ public class PermissionsManager {
}
public void checkDevice(long userId, long deviceId) throws SecurityException {
- if (!Context.getDeviceManager().getUserItems(userId).contains(deviceId) && !isAdmin(userId)) {
+ if (!Context.getDeviceManager().getUserItems(userId).contains(deviceId) && !getUserAdmin(userId)) {
checkManager(userId);
for (long managedUserId : usersManager.getUserItems(userId)) {
if (Context.getDeviceManager().getUserItems(managedUserId).contains(deviceId)) {
@@ -277,7 +295,7 @@ public class PermissionsManager {
}
public void checkRegistration(long userId) {
- if (!server.getRegistration() && !isAdmin(userId)) {
+ if (!server.getRegistration() && !getUserAdmin(userId)) {
throw new SecurityException("Registration disabled");
}
}
@@ -300,11 +318,13 @@ public class PermissionsManager {
manager = Context.getDriversManager();
} else if (object.equals(Calendar.class)) {
manager = Context.getCalendarManager();
+ } else if (object.equals(Command.class)) {
+ manager = Context.getCommandsManager();
} else {
throw new IllegalArgumentException("Unknown object type");
}
- if (manager != null && !manager.checkItemPermission(userId, objectId) && !isAdmin(userId)) {
+ if (manager != null && !manager.checkItemPermission(userId, objectId) && !getUserAdmin(userId)) {
checkManager(userId);
for (long managedUserId : usersManager.getManagedItems(userId)) {
if (manager.checkItemPermission(managedUserId, objectId)) {
@@ -322,6 +342,7 @@ public class PermissionsManager {
Context.getCalendarManager().refreshUserItems();
Context.getDriversManager().refreshUserItems();
Context.getAttributesManager().refreshUserItems();
+ Context.getCommandsManager().refreshUserItems();
if (Context.getNotificationManager() != null) {
Context.getNotificationManager().refresh();
}
@@ -333,6 +354,7 @@ public class PermissionsManager {
}
Context.getDriversManager().refreshExtendedPermissions();
Context.getAttributesManager().refreshExtendedPermissions();
+ Context.getCommandsManager().refreshExtendedPermissions();
}
public void refreshPermissions(Permission permission) {
@@ -351,6 +373,8 @@ public class PermissionsManager {
Context.getAttributesManager().refreshUserItems();
} else if (permission.getPropertyClass().equals(Calendar.class)) {
Context.getCalendarManager().refreshUserItems();
+ } else if (permission.getPropertyClass().equals(Command.class)) {
+ Context.getCommandsManager().refreshUserItems();
}
} else if (permission.getOwnerClass().equals(Device.class) || permission.getOwnerClass().equals(Group.class)) {
if (permission.getPropertyClass().equals(Geofence.class) && Context.getGeofenceManager() != null) {
@@ -359,6 +383,8 @@ public class PermissionsManager {
Context.getDriversManager().refreshExtendedPermissions();
} else if (permission.getPropertyClass().equals(Attribute.class)) {
Context.getAttributesManager().refreshExtendedPermissions();
+ } else if (permission.getPropertyClass().equals(Command.class)) {
+ Context.getCommandsManager().refreshExtendedPermissions();
}
}
}
diff --git a/src/org/traccar/model/Command.java b/src/org/traccar/model/Command.java
index 6a48b14e9..67134dc7d 100644
--- a/src/org/traccar/model/Command.java
+++ b/src/org/traccar/model/Command.java
@@ -15,6 +15,8 @@
*/
package org.traccar.model;
+import org.traccar.database.QueryIgnore;
+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -85,4 +87,20 @@ public class Command extends Message {
this.textChannel = textChannel;
}
+ @QueryIgnore
+ @Override
+ public long getDeviceId() {
+ return super.getDeviceId();
+ }
+
+ private String description;
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
}
diff --git a/src/org/traccar/model/Server.java b/src/org/traccar/model/Server.java
index bfe881479..072e85d55 100644
--- a/src/org/traccar/model/Server.java
+++ b/src/org/traccar/model/Server.java
@@ -147,4 +147,14 @@ public class Server extends ExtendedModel {
public void setCoordinateFormat(String coordinateFormat) {
this.coordinateFormat = coordinateFormat;
}
+
+ private boolean limitCommands;
+
+ public boolean getLimitCommands() {
+ return limitCommands;
+ }
+
+ public void setLimitCommands(boolean limitCommands) {
+ this.limitCommands = limitCommands;
+ }
}
diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java
index 043c23036..5d89dcfae 100644
--- a/src/org/traccar/model/User.java
+++ b/src/org/traccar/model/User.java
@@ -210,6 +210,16 @@ public class User extends ExtendedModel {
}
}
+ private boolean limitCommands;
+
+ public boolean getLimitCommands() {
+ return limitCommands;
+ }
+
+ public void setLimitCommands(boolean limitCommands) {
+ this.limitCommands = limitCommands;
+ }
+
@QueryIgnore
public String getPassword() {
return null;