diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2017-09-13 22:15:49 +1200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-13 22:15:49 +1200 |
commit | 8a45a056b7e0814526904e915c3886b29ba2833a (patch) | |
tree | dc821e2134f4ae2c9881ce8de006a29b33da289f | |
parent | e05f0b83a911c522123a5a2cd14d6c16bd2de027 (diff) | |
parent | 7530522cbca477cb822cb494ffe12480e5237934 (diff) | |
download | traccar-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.xml | 64 | ||||
-rw-r--r-- | src/org/traccar/Context.java | 12 | ||||
-rw-r--r-- | src/org/traccar/api/BaseObjectResource.java | 9 | ||||
-rw-r--r-- | src/org/traccar/api/resource/CommandResource.java | 43 | ||||
-rw-r--r-- | src/org/traccar/api/resource/CommandTypeResource.java | 8 | ||||
-rw-r--r-- | src/org/traccar/api/resource/DeviceResource.java | 2 | ||||
-rw-r--r-- | src/org/traccar/api/resource/UserResource.java | 10 | ||||
-rw-r--r-- | src/org/traccar/database/CommandsManager.java | 136 | ||||
-rw-r--r-- | src/org/traccar/database/DataManager.java | 3 | ||||
-rw-r--r-- | src/org/traccar/database/DeviceManager.java | 51 | ||||
-rw-r--r-- | src/org/traccar/database/PermissionsManager.java | 56 | ||||
-rw-r--r-- | src/org/traccar/model/Command.java | 18 | ||||
-rw-r--r-- | src/org/traccar/model/Server.java | 10 | ||||
-rw-r--r-- | src/org/traccar/model/User.java | 10 |
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; |