From e00fbfa466b17e94f59e6ff8fefb83f08999b3ec Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Thu, 20 Jul 2017 17:12:29 +0500 Subject: Rename Identifiable and Extensible to BaseModel and ExtendedModel --- src/org/traccar/model/User.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/org/traccar/model/User.java') diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index 366ced503..6e6a079c2 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -21,7 +21,7 @@ import org.traccar.helper.Hashing; import java.util.Date; import java.util.TimeZone; -public class User extends Extensible { +public class User extends ExtendedModel { private String name; -- cgit v1.2.3 From ae76cbf971bfc9e47ef21e87606dacc7c0e3ddc6 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Mon, 31 Jul 2017 14:08:36 +0500 Subject: Implement SQL requests construction --- schema/changelog-3.14.xml | 4 +- setup/default.xml | 406 +-------------------- src/org/traccar/Config.java | 4 + src/org/traccar/api/resource/EventResource.java | 2 +- src/org/traccar/api/resource/PositionResource.java | 2 +- src/org/traccar/database/DataManager.java | 210 ++++++++--- src/org/traccar/database/QueryAdditional.java | 27 ++ src/org/traccar/database/StatisticsManager.java | 2 +- src/org/traccar/model/Device.java | 7 + src/org/traccar/model/Position.java | 9 + src/org/traccar/model/Server.java | 2 + src/org/traccar/model/User.java | 6 + test/org/traccar/database/DataManagerTest.java | 79 ++++ 13 files changed, 299 insertions(+), 461 deletions(-) create mode 100644 src/org/traccar/database/QueryAdditional.java create mode 100644 test/org/traccar/database/DataManagerTest.java (limited to 'src/org/traccar/model/User.java') diff --git a/schema/changelog-3.14.xml b/schema/changelog-3.14.xml index 7965bc020..f6cda4c1f 100644 --- a/schema/changelog-3.14.xml +++ b/schema/changelog-3.14.xml @@ -61,5 +61,7 @@ + + - \ No newline at end of file + diff --git a/setup/default.xml b/setup/default.xml index f0f9ef4a3..ea8c32fbd 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -29,163 +29,16 @@ true ./schema/changelog-master.xml - - - SELECT * FROM server - - - - UPDATE server SET - registration = :registration, - readonly = :readonly, - deviceReadonly = :deviceReadonly, - map = :map, - bingKey = :bingKey, - mapUrl = :mapUrl, - distanceUnit = :distanceUnit, - speedUnit = :speedUnit, - latitude = :latitude, - longitude = :longitude, - zoom = :zoom, - twelveHourFormat = :twelveHourFormat, - coordinateFormat = :coordinateFormat, - forceSettings = :forceSettings, - timezone = :timezone, - attributes = :attributes - WHERE id = :id - - + SELECT * FROM users WHERE email = :email - - SELECT * FROM users - - - - INSERT INTO users (name, email, phone, hashedPassword, salt, readonly, admin, map, distanceUnit, speedUnit, latitude, longitude, zoom, twelveHourFormat, coordinateFormat, disabled, expirationTime, deviceLimit, userLimit, deviceReadonly, token, timezone, attributes) - VALUES (:name, :email, :phone, :hashedPassword, :salt, :readonly, :admin, :map, :distanceUnit, :speedUnit, :latitude, :longitude, :zoom, :twelveHourFormat, :coordinateFormat, :disabled, :expirationTime, :deviceLimit, :userLimit, :deviceReadonly, :token, :timezone, :attributes) - - - - UPDATE users SET - name = :name, - email = :email, - phone = :phone, - readonly = :readonly, - admin = :admin, - map = :map, - distanceUnit = :distanceUnit, - speedUnit = :speedUnit, - latitude = :latitude, - longitude = :longitude, - zoom = :zoom, - twelveHourFormat = :twelveHourFormat, - coordinateFormat = :coordinateFormat, - disabled = :disabled, - expirationTime = :expirationTime, - deviceLimit = :deviceLimit, - userLimit = :userLimit, - deviceReadonly = :deviceReadonly, - token = :token, - timezone = :timezone, - attributes = :attributes - WHERE id = :id - - - - UPDATE users SET hashedPassword = :hashedPassword, salt = :salt WHERE id = :id - - - - DELETE FROM users WHERE id = :id - - - - SELECT userId, deviceId FROM user_device - - - - SELECT userId, groupId FROM user_group - - - - SELECT * FROM devices - - - - INSERT INTO devices (name, uniqueId, groupId, attributes, phone, model, contact, category) - VALUES (:name, :uniqueId, :groupId, :attributes, :phone, :model, :contact, :category) - - - - UPDATE devices SET - name = :name, - uniqueId = :uniqueId, - groupId = :groupId, - attributes = :attributes, - phone = :phone, - model = :model, - contact = :contact, - category = :category - WHERE id = :id - - - - UPDATE devices SET lastUpdate = :lastUpdate WHERE id = :id - - - - DELETE FROM devices WHERE id = :id - - - - INSERT INTO user_device (userId, deviceId) VALUES (:userId, :deviceId) - - - - DELETE FROM user_device WHERE userId = :userId AND deviceId = :deviceId - - - - SELECT * FROM groups - - - - INSERT INTO groups (name, groupId, attributes) VALUES (:name, :groupId, :attributes) - - - - UPDATE groups SET name = :name, groupId = :groupId, attributes = :attributes WHERE id = :id - - - - DELETE FROM groups WHERE id = :id - - - - INSERT INTO user_group (userId, groupId) VALUES (:userId, :groupId) - - - - DELETE FROM user_group WHERE userId = :userId AND groupId = :groupId - - SELECT * FROM positions WHERE deviceId = :deviceId AND fixTime BETWEEN :from AND :to ORDER BY fixTime - - SELECT * FROM positions WHERE id = :id - - - - INSERT INTO positions (deviceId, protocol, serverTime, deviceTime, fixTime, valid, latitude, longitude, altitude, speed, course, address, attributes, accuracy, network) - VALUES (:deviceId, :protocol, :now, :deviceTime, :fixTime, :valid, :latitude, :longitude, :altitude, :speed, :course, :address, :attributes, :accuracy, :network) - - SELECT positions.* FROM positions INNER JOIN devices ON positions.id = devices.positionid; @@ -194,102 +47,10 @@ UPDATE devices SET positionId = :id WHERE id = :deviceId - - SELECT * FROM events WHERE id = :id - - - - INSERT INTO events (type, serverTime, deviceId, positionId, geofenceId, attributes) - VALUES (:type, :serverTime, :deviceId, :positionId, :geofenceId, :attributes) - - SELECT * FROM events WHERE deviceId = :deviceId AND serverTime BETWEEN :from AND :to ORDER BY serverTime - - SELECT * FROM geofences - - - - INSERT INTO geofences (name, description, calendarid, area, attributes) - VALUES (:name, :description, :calendarid, :area, :attributes) - - - - UPDATE geofences SET - name = :name, - description = :description, - calendarid = :calendarid, - area = :area, - attributes = :attributes - WHERE id = :id - - - - DELETE FROM geofences WHERE id = :id - - - - SELECT userId, geofenceId FROM user_geofence - - - - INSERT INTO user_geofence (userId, geofenceId) VALUES (:userId, :geofenceId) - - - - DELETE FROM user_geofence WHERE userId = :userId AND geofenceId = :geofenceId - - - - SELECT groupId, geofenceId FROM group_geofence - - - - INSERT INTO group_geofence (groupId, geofenceId) VALUES (:groupId, :geofenceId) - - - - DELETE FROM group_geofence WHERE groupId = :groupId AND geofenceId = :geofenceId - - - - SELECT deviceId, geofenceId FROM device_geofence - - - - INSERT INTO device_geofence (deviceId, geofenceId) VALUES (:deviceId, :geofenceId) - - - - DELETE FROM device_geofence WHERE deviceId = :deviceId AND geofenceId = :geofenceId - - - - SELECT * FROM notifications - - - - INSERT INTO notifications (userId, type, web, mail, sms, attributes) - VALUES (:userId, :type, :web, :mail, :sms, :attributes) - - - - UPDATE notifications SET - userId = :userId, - type = :type, - web = :web, - mail = :mail, - sms = :sms, - attributes = :attributes - WHERE id = :id - - - - DELETE FROM notifications WHERE id = :id - - DELETE FROM positions WHERE serverTime < :serverTime AND id NOT IN (SELECT positionId FROM devices) @@ -323,171 +84,6 @@ SELECT * FROM statistics WHERE captureTime BETWEEN :from AND :to ORDER BY captureTime - - INSERT INTO statistics (captureTime, activeUsers, activeDevices, requests, messagesReceived, messagesStored, mailSent, smsSent, geocoderRequests, geolocationRequests, attributes) - VALUES (:captureTime, :activeUsers, :activeDevices, :requests, :messagesReceived, :messagesStored, :mailSent, :smsSent, :geocoderRequests, :geolocationRequests, :attributes) - - - - SELECT * FROM calendars - - - - INSERT INTO calendars (name, data, attributes) - VALUES (:name, :data, :attributes) - - - - UPDATE calendars SET - name = :name, - data = :data, - attributes = :attributes - WHERE id = :id - - - - DELETE FROM calendars WHERE id = :id - - - - SELECT userId, calendarId FROM user_calendar - - - - INSERT INTO user_calendar (userId, calendarId) VALUES (:userId, :calendarId) - - - - DELETE FROM user_calendar WHERE userId = :userId AND calendarId = :calendarId - - - - SELECT userId, managedUserId FROM user_user - - - - INSERT INTO user_user (userId, managedUserId) VALUES (:userId, :managedUserId) - - - - DELETE FROM user_user WHERE userId = :userId AND managedUserId = :managedUserId - - - - SELECT * FROM attributes - - - - INSERT INTO attributes (description, type, attribute, expression) - VALUES (:description, :type, :attribute, :expression) - - - - UPDATE attributes SET - description = :description, - type = :type, - attribute = :attribute, - expression = :expression - WHERE id = :id - - - - DELETE FROM attributes WHERE id = :id - - - - SELECT userId, attributeId FROM user_attribute - - - - INSERT INTO user_attribute (userId, attributeId) VALUES (:userId, :attributeId) - - - - DELETE FROM user_attribute WHERE userId = :userId AND attributeId = :attributeId - - - - SELECT groupId, attributeId FROM group_attribute - - - - INSERT INTO group_attribute (groupId, attributeId) VALUES (:groupId, :attributeId) - - - - DELETE FROM group_attribute WHERE groupId = :groupId AND attributeId = :attributeId - - - - SELECT deviceId, attributeId FROM device_attribute - - - - INSERT INTO device_attribute (deviceId, attributeId) VALUES (:deviceId, :attributeId) - - - - DELETE FROM device_attribute WHERE deviceId = :deviceId AND attributeId = :attributeId - - - - SELECT * FROM drivers - - - - INSERT INTO drivers (name, uniqueId, attributes) - VALUES (:name, :uniqueId, :attributes) - - - - UPDATE drivers SET - name = :name, - uniqueId = :uniqueId, - attributes = :attributes - WHERE id = :id - - - - DELETE FROM drivers WHERE id = :id - - - - SELECT userId, driverId FROM user_driver - - - - INSERT INTO user_driver (userId, driverId) VALUES (:userId, :driverId) - - - - DELETE FROM user_driver WHERE userId = :userId AND driverId = :driverId - - - - SELECT groupId, driverId FROM group_driver - - - - INSERT INTO group_driver (groupId, driverId) VALUES (:groupId, :driverId) - - - - DELETE FROM group_driver WHERE groupId = :groupId AND driverId = :driverId - - - - SELECT deviceId, driverId FROM device_driver - - - - INSERT INTO device_driver (deviceId, driverId) VALUES (:deviceId, :driverId) - - - - DELETE FROM device_driver WHERE deviceId = :deviceId AND driverId = :driverId - - 5001 diff --git a/src/org/traccar/Config.java b/src/org/traccar/Config.java index 0bc3cafaa..a0f3f8c2e 100644 --- a/src/org/traccar/Config.java +++ b/src/org/traccar/Config.java @@ -96,4 +96,8 @@ public class Config { return key.replaceAll("\\.", "_").replaceAll("(\\p{Lu})", "_$1").toUpperCase(); } + public void setString(String key, String value) { + properties.putIfAbsent(key, value); + } + } diff --git a/src/org/traccar/api/resource/EventResource.java b/src/org/traccar/api/resource/EventResource.java index b7fda6f73..a7cf9edbd 100644 --- a/src/org/traccar/api/resource/EventResource.java +++ b/src/org/traccar/api/resource/EventResource.java @@ -23,7 +23,7 @@ public class EventResource extends BaseResource { @Path("{id}") @GET public Event get(@PathParam("id") long id) throws SQLException { - Event event = Context.getDataManager().getEvent(id); + Event event = Context.getDataManager().getObject(Event.class, id); Context.getPermissionsManager().checkDevice(getUserId(), event.getDeviceId()); if (event.getGeofenceId() != 0) { Context.getPermissionsManager().checkPermission(Geofence.class, getUserId(), event.getGeofenceId()); diff --git a/src/org/traccar/api/resource/PositionResource.java b/src/org/traccar/api/resource/PositionResource.java index 6dab51744..c031b842f 100644 --- a/src/org/traccar/api/resource/PositionResource.java +++ b/src/org/traccar/api/resource/PositionResource.java @@ -54,7 +54,7 @@ public class PositionResource extends BaseResource { if (!positionIds.isEmpty()) { ArrayList positions = new ArrayList<>(); for (Long positionId : positionIds) { - Position position = Context.getDataManager().getPosition(positionId); + Position position = Context.getDataManager().getObject(Position.class, positionId); Context.getPermissionsManager().checkDevice(getUserId(), position.getDeviceId()); positions.add(position); } diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 07ad0be44..a753c311b 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -21,8 +21,11 @@ import java.net.URL; import java.net.URLClassLoader; import java.sql.SQLException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.HashSet; +import java.util.Set; import javax.naming.InitialContext; import javax.sql.DataSource; @@ -58,6 +61,12 @@ import com.zaxxer.hikari.HikariDataSource; public class DataManager { + public static final String ACTION_SELECT_ALL = "selectAll"; + public static final String ACTION_SELECT = "select"; + public static final String ACTION_INSERT = "insert"; + public static final String ACTION_UPDATE = "update"; + public static final String ACTION_DELETE = "delete"; + private final Config config; private DataSource dataSource; @@ -115,6 +124,73 @@ public class DataManager { } } + public static String constructObjectQuery(String action, Class clazz, boolean additional) { + switch (action) { + case ACTION_INSERT: + case ACTION_UPDATE: + StringBuilder result = new StringBuilder(); + StringBuilder fields = new StringBuilder(); + StringBuilder values = new StringBuilder(); + + Set methods = new HashSet<>(Arrays.asList(clazz.getMethods())); + methods.removeAll(Arrays.asList(Object.class.getMethods())); + methods.removeAll(Arrays.asList(BaseModel.class.getMethods())); + for (Method method : methods) { + if (method.getName().startsWith("get") && method.getParameterTypes().length == 0 + && (additional ? method.isAnnotationPresent(QueryAdditional.class) + : !method.isAnnotationPresent(QueryIgnore.class) + && !method.isAnnotationPresent(QueryAdditional.class))) { + String name = method.getName().substring(3, 4).toLowerCase() + + method.getName().substring(4); + if (action.equals(ACTION_INSERT)) { + fields.append(name).append(", "); + values.append(":").append(name).append(", "); + } else { + fields.append(name).append(" = :").append(name).append(",\n"); + } + } + } + fields.setLength(fields.length() - 2); + if (action.equals(ACTION_INSERT)) { + values.setLength(values.length() - 2); + result.append("INSERT INTO ").append(getObjectsTableName(clazz)).append(" ("); + result.append(fields).append(")\n"); + result.append("VALUES (").append(values).append(")"); + } else { + result.append("UPDATE ").append(getObjectsTableName(clazz)).append(" SET\n"); + result.append(fields); + result.append("\nWHERE id = :id"); + } + return result.toString(); + case ACTION_SELECT_ALL: + return "SELECT * FROM " + getObjectsTableName(clazz); + case ACTION_SELECT: + return "SELECT * FROM " + getObjectsTableName(clazz) + " WHERE id = :id"; + case ACTION_DELETE: + return "DELETE FROM " + getObjectsTableName(clazz) + " WHERE id = :id"; + default: + throw new IllegalArgumentException("Unknown action"); + } + } + + public static String constructPermissionQuery(String action, Class owner, Class property) { + switch (action) { + case ACTION_SELECT_ALL: + return "SELECT " + makeNameId(owner) + ", " + makeNameId(property) + " FROM " + + getPermissionsTableName(owner, property); + case ACTION_INSERT: + return "INSERT INTO " + getPermissionsTableName(owner, property) + + " (" + makeNameId(owner) + ", " + makeNameId(property) + ") VALUES (:" + + makeNameId(owner) + ", :" + makeNameId(property) + ")"; + case ACTION_DELETE: + return "DELETE FROM " + getPermissionsTableName(owner, property) + + " WHERE " + makeNameId(owner) + " = :" + makeNameId(owner) + + " AND " + makeNameId(property) + " = :" + makeNameId(property); + default: + throw new IllegalArgumentException("Unknown action"); + } + } + private String getQuery(String key) { String query = config.getString(key); if (query == null) { @@ -123,6 +199,59 @@ public class DataManager { return query; } + public String getQuery(String action, Class clazz) { + return getQuery(action, clazz, false); + } + + public String getQuery(String action, Class clazz, boolean additional) { + String queryName; + if (action.equals(ACTION_SELECT_ALL)) { + queryName = "database.select" + clazz.getSimpleName() + "s"; + } else { + queryName = "database." + action.toLowerCase() + clazz.getSimpleName(); + } + String query = config.getString(queryName); + if (query == null) { + query = constructObjectQuery(action, clazz, additional); + config.setString(queryName, query); + } + + return query; + } + + public String getQuery(String action, Class owner, Class property) { + String queryName; + if (action.equals(ACTION_SELECT_ALL)) { + queryName = "database.select" + owner.getSimpleName() + property.getSimpleName() + "s"; + } else if (action.equals(ACTION_INSERT)) { + queryName = "database.link" + owner.getSimpleName() + property.getSimpleName(); + } else { + queryName = "database.unlink" + owner.getSimpleName() + property.getSimpleName(); + } + String query = config.getString(queryName); + if (query == null) { + query = constructPermissionQuery(action, owner, property.equals(User.class) ? ManagedUser.class : property); + config.setString(queryName, query); + } + + return query; + } + + private static String getPermissionsTableName(Class owner, Class property) { + String ownerName = owner.getSimpleName(); + String propertyName = property.getSimpleName(); + if (propertyName.equals("ManagedUser")) { + propertyName = "User"; + } + return ownerName.substring(0, 1).toLowerCase() + ownerName.substring(1) + "_" + + propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); + } + + private static String getObjectsTableName(Class clazz) { + String name = clazz.getSimpleName(); + return name.substring(0, 1).toLowerCase() + name.substring(1) + "s"; + } + private void initDatabaseSchema() throws SQLException, LiquibaseException { if (config.hasKey("database.changelog")) { @@ -155,19 +284,8 @@ public class DataManager { } } - public void updateUser(User user) throws SQLException { - QueryBuilder.create(dataSource, getQuery("database.updateUser")) - .setObject(user) - .executeUpdate(); - if (user.getHashedPassword() != null) { - QueryBuilder.create(dataSource, getQuery("database.updateUserPassword")) - .setObject(user) - .executeUpdate(); - } - } - public void updateDeviceStatus(Device device) throws SQLException { - QueryBuilder.create(dataSource, getQuery("database.updateDeviceStatus")) + QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, Device.class, true)) .setObject(device) .executeUpdate(); } @@ -180,16 +298,10 @@ public class DataManager { .executeQuery(Position.class); } - public Position getPosition(long positionId) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectPosition")) - .setLong("id", positionId) - .executeQuerySingle(Position.class); - } - public void addPosition(Position position) throws SQLException { - position.setId(QueryBuilder.create(dataSource, getQuery("database.insertPosition"), true) - .setDate("now", new Date()) + position.setId(QueryBuilder.create(dataSource, getQuery(ACTION_INSERT, Position.class), true) .setObject(position) + .setDate("serverTime", new Date()) .executeUpdate()); } @@ -220,16 +332,10 @@ public class DataManager { } public Server getServer() throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectServers")) + return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, Server.class)) .executeQuerySingle(Server.class); } - public Event getEvent(long eventId) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectEvent")) - .setLong("id", eventId) - .executeQuerySingle(Event.class); - } - public Collection getEvents(long deviceId, Date from, Date to) throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.selectEvents")) .setLong("deviceId", deviceId) @@ -268,12 +374,6 @@ public class DataManager { .executeQuery(Statistics.class); } - public void addStatistics(Statistics statistics) throws SQLException { - statistics.setId(QueryBuilder.create(dataSource, getQuery("database.insertStatistics"), true) - .setObject(statistics) - .executeUpdate()); - } - public static Class getClassByName(String name) throws ClassNotFoundException { switch (name.toLowerCase().replace("id", "")) { case "device": @@ -302,44 +402,50 @@ public class DataManager { return name.substring(0, 1).toLowerCase() + name.substring(1) + (name.indexOf("Id") == -1 ? "Id" : ""); } + public Collection getPermissions(Class owner, Class property) + throws SQLException, ClassNotFoundException { + return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property)) + .executePermissionsQuery(); + } + public void linkObject(Class owner, long ownerId, Class property, long propertyId, boolean link) throws SQLException { - String query = "database." + (link ? "link" : "unlink") + owner.getSimpleName() + property.getSimpleName(); - QueryBuilder queryBuilder = QueryBuilder.create(dataSource, getQuery(query)); - - queryBuilder.setLong(makeNameId(owner), ownerId); - queryBuilder.setLong(makeNameId(property), propertyId); - queryBuilder.executeUpdate(); + QueryBuilder.create(dataSource, getQuery(link ? ACTION_INSERT : ACTION_DELETE, owner, property)) + .setLong(makeNameId(owner), ownerId) + .setLong(makeNameId(property), propertyId) + .executeUpdate(); } - public Collection getObjects(Class clazz) throws SQLException { - String query = "database.select" + clazz.getSimpleName() + "s"; - return QueryBuilder.create(dataSource, getQuery(query)).executeQuery(clazz); + public T getObject(Class clazz, long entityId) throws SQLException { + return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT, clazz)) + .setLong("id", entityId) + .executeQuerySingle(clazz); } - public Collection getPermissions(Class owner, - Class property) throws SQLException, ClassNotFoundException { - String query = "database.select" + owner.getSimpleName() + property.getSimpleName() + "s"; - return QueryBuilder.create(dataSource, getQuery(query)).executePermissionsQuery(); + public Collection getObjects(Class clazz) throws SQLException { + return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, clazz)) + .executeQuery(clazz); } public void addObject(BaseModel entity) throws SQLException { - String query = "database.insert" + entity.getClass().getSimpleName(); - entity.setId(QueryBuilder.create(dataSource, getQuery(query), true) + entity.setId(QueryBuilder.create(dataSource, getQuery(ACTION_INSERT, entity.getClass()), true) .setObject(entity) .executeUpdate()); } public void updateObject(BaseModel entity) throws SQLException { - String query = "database.update" + entity.getClass().getSimpleName(); - QueryBuilder.create(dataSource, getQuery(query)) + QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, entity.getClass())) .setObject(entity) .executeUpdate(); + if (entity instanceof User && ((User) entity).getHashedPassword() != null) { + QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, User.class, true)) + .setObject(entity) + .executeUpdate(); + } } public void removeObject(Class clazz, long entityId) throws SQLException { - String query = "database.delete" + clazz.getSimpleName(); - QueryBuilder.create(dataSource, getQuery(query)) + QueryBuilder.create(dataSource, getQuery(ACTION_DELETE, clazz)) .setLong("id", entityId) .executeUpdate(); } diff --git a/src/org/traccar/database/QueryAdditional.java b/src/org/traccar/database/QueryAdditional.java new file mode 100644 index 000000000..7a42c1875 --- /dev/null +++ b/src/org/traccar/database/QueryAdditional.java @@ -0,0 +1,27 @@ +/* + * 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.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface QueryAdditional { +} diff --git a/src/org/traccar/database/StatisticsManager.java b/src/org/traccar/database/StatisticsManager.java index 5b42416ad..06a3e7b35 100644 --- a/src/org/traccar/database/StatisticsManager.java +++ b/src/org/traccar/database/StatisticsManager.java @@ -61,7 +61,7 @@ public class StatisticsManager { statistics.setGeolocationRequests(geolocationRequests); try { - Context.getDataManager().addStatistics(statistics); + Context.getDataManager().addObject(statistics); } catch (SQLException e) { Log.warning(e); } diff --git a/src/org/traccar/model/Device.java b/src/org/traccar/model/Device.java index 6a13c2b77..cd5dd12c4 100644 --- a/src/org/traccar/model/Device.java +++ b/src/org/traccar/model/Device.java @@ -18,6 +18,9 @@ package org.traccar.model; import java.util.Date; import java.util.List; +import org.traccar.database.QueryAdditional; +import org.traccar.database.QueryIgnore; + public class Device extends ExtendedModel { private String name; @@ -46,6 +49,7 @@ public class Device extends ExtendedModel { private String status; + @QueryIgnore public String getStatus() { return status != null ? status : STATUS_OFFLINE; } @@ -56,6 +60,7 @@ public class Device extends ExtendedModel { private Date lastUpdate; + @QueryAdditional public Date getLastUpdate() { if (lastUpdate != null) { return new Date(lastUpdate.getTime()); @@ -74,6 +79,7 @@ public class Device extends ExtendedModel { private long positionId; + @QueryIgnore public long getPositionId() { return positionId; } @@ -94,6 +100,7 @@ public class Device extends ExtendedModel { private List geofenceIds; + @QueryIgnore public List getGeofenceIds() { return geofenceIds; } diff --git a/src/org/traccar/model/Position.java b/src/org/traccar/model/Position.java index 4412b012c..66a6f91ce 100644 --- a/src/org/traccar/model/Position.java +++ b/src/org/traccar/model/Position.java @@ -17,6 +17,8 @@ package org.traccar.model; import java.util.Date; +import org.traccar.database.QueryIgnore; + public class Position extends Message { public static final String KEY_ORIGINAL = "raw"; @@ -196,6 +198,7 @@ public class Position extends Message { private boolean outdated; + @QueryIgnore public boolean getOutdated() { return outdated; } @@ -294,4 +297,10 @@ public class Position extends Message { this.network = network; } + @Override + @QueryIgnore + public String getType() { + return super.getType(); + } + } diff --git a/src/org/traccar/model/Server.java b/src/org/traccar/model/Server.java index cd5b0624e..246be0b4f 100644 --- a/src/org/traccar/model/Server.java +++ b/src/org/traccar/model/Server.java @@ -17,10 +17,12 @@ package org.traccar.model; import java.util.TimeZone; +import org.traccar.database.QueryIgnore; import org.traccar.helper.Log; public class Server extends ExtendedModel { + @QueryIgnore public String getVersion() { return Log.getAppVersion(); } diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index 6e6a079c2..72b53ee5d 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -16,6 +16,9 @@ package org.traccar.model; import com.fasterxml.jackson.annotation.JsonIgnore; + +import org.traccar.database.QueryAdditional; +import org.traccar.database.QueryIgnore; import org.traccar.helper.Hashing; import java.util.Date; @@ -228,6 +231,7 @@ public class User extends ExtendedModel { } } + @QueryIgnore public String getPassword() { return null; } @@ -243,6 +247,7 @@ public class User extends ExtendedModel { private String hashedPassword; @JsonIgnore + @QueryAdditional public String getHashedPassword() { return hashedPassword; } @@ -254,6 +259,7 @@ public class User extends ExtendedModel { private String salt; @JsonIgnore + @QueryAdditional public String getSalt() { return salt; } diff --git a/test/org/traccar/database/DataManagerTest.java b/test/org/traccar/database/DataManagerTest.java new file mode 100644 index 000000000..3383c3d22 --- /dev/null +++ b/test/org/traccar/database/DataManagerTest.java @@ -0,0 +1,79 @@ +package org.traccar.database; + +import org.junit.Assert; +import org.junit.Test; +import org.traccar.model.Attribute; +import org.traccar.model.Device; +import org.traccar.model.Driver; +import org.traccar.model.Geofence; +import org.traccar.model.Group; +import org.traccar.model.ManagedUser; +import org.traccar.model.Position; +import org.traccar.model.User; + +public class DataManagerTest { + + @Test + public void constructObjectQuery() { + Assert.assertEquals("SELECT * FROM users", + DataManager.constructObjectQuery(DataManager.ACTION_SELECT_ALL, User.class, false)); + Assert.assertEquals("DELETE FROM groups WHERE id = :id", + DataManager.constructObjectQuery(DataManager.ACTION_DELETE, Group.class, false)); + Assert.assertEquals("SELECT * FROM positions WHERE id = :id", + DataManager.constructObjectQuery(DataManager.ACTION_SELECT, Position.class, false)); + + String insertDevice = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Device.class, false); + Assert.assertFalse(insertDevice.contains("class")); + Assert.assertFalse(insertDevice.contains("id")); + Assert.assertFalse(insertDevice.contains("status")); + Assert.assertFalse(insertDevice.contains("lastUpdate")); + Assert.assertFalse(insertDevice.contains("geofenceIds")); + + String updateDeviceStatus = DataManager.constructObjectQuery("update", Device.class, true); + Assert.assertTrue(updateDeviceStatus.contains("lastUpdate")); + + String updateUser = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, false); + Assert.assertFalse(updateUser.contains("class")); + Assert.assertFalse(updateUser.contains("password")); + Assert.assertFalse(updateUser.contains("salt")); + + String updateUserPassword = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, true); + Assert.assertFalse(updateUserPassword.contains("name")); + Assert.assertTrue(updateUserPassword.contains("hashedPassword")); + Assert.assertTrue(updateUserPassword.contains("salt")); + + String insertPosition = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Position.class, false); + Assert.assertFalse(insertPosition.contains("type")); + Assert.assertFalse(insertPosition.contains("outdated")); + + } + + @Test + public void constructPermissionsQuery() { + Assert.assertEquals("SELECT userId, deviceId FROM user_device", + DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, Device.class)); + + Assert.assertEquals("SELECT userId, managedUserId FROM user_user", + DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, ManagedUser.class)); + + Assert.assertEquals("SELECT deviceId, driverId FROM device_driver", + DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Device.class, Driver.class)); + + Assert.assertEquals("SELECT groupId, geofenceId FROM group_geofence", + DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Group.class, Geofence.class)); + + Assert.assertEquals("INSERT INTO user_device (userId, deviceId) VALUES (:userId, :deviceId)", + DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, User.class, Device.class)); + + Assert.assertEquals("DELETE FROM user_user WHERE userId = :userId AND managedUserId = :managedUserId", + DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, User.class, ManagedUser.class)); + + Assert.assertEquals("INSERT INTO device_geofence (deviceId, geofenceId) VALUES (:deviceId, :geofenceId)", + DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, Device.class, Geofence.class)); + + Assert.assertEquals("DELETE FROM group_attribute WHERE groupId = :groupId AND attributeId = :attributeId", + DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, Group.class, Attribute.class)); + + } + +} -- cgit v1.2.3 From 01de09dcdf4a746bac66e1f700f8c6eb2c96c6ae Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Mon, 31 Jul 2017 17:31:42 +0500 Subject: - Rename QueryAdditional to QueryExtended - Use Introspector.decapitalize - Replace new lines with spaces - Fixed indentation - Fixed extended query name --- src/org/traccar/database/DataManager.java | 45 ++++++++++++++------------- src/org/traccar/database/QueryAdditional.java | 27 ---------------- src/org/traccar/database/QueryExtended.java | 27 ++++++++++++++++ src/org/traccar/model/Device.java | 4 +-- src/org/traccar/model/User.java | 6 ++-- 5 files changed, 55 insertions(+), 54 deletions(-) delete mode 100644 src/org/traccar/database/QueryAdditional.java create mode 100644 src/org/traccar/database/QueryExtended.java (limited to 'src/org/traccar/model/User.java') diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index a753c311b..3d89cc3d1 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -15,6 +15,7 @@ */ package org.traccar.database; +import java.beans.Introspector; import java.io.File; import java.lang.reflect.Method; import java.net.URL; @@ -124,7 +125,7 @@ public class DataManager { } } - public static String constructObjectQuery(String action, Class clazz, boolean additional) { + public static String constructObjectQuery(String action, Class clazz, boolean extended) { switch (action) { case ACTION_INSERT: case ACTION_UPDATE: @@ -136,17 +137,20 @@ public class DataManager { methods.removeAll(Arrays.asList(Object.class.getMethods())); methods.removeAll(Arrays.asList(BaseModel.class.getMethods())); for (Method method : methods) { - if (method.getName().startsWith("get") && method.getParameterTypes().length == 0 - && (additional ? method.isAnnotationPresent(QueryAdditional.class) - : !method.isAnnotationPresent(QueryIgnore.class) - && !method.isAnnotationPresent(QueryAdditional.class))) { - String name = method.getName().substring(3, 4).toLowerCase() - + method.getName().substring(4); + boolean skip; + if (extended) { + skip = !method.isAnnotationPresent(QueryExtended.class); + } else { + skip = method.isAnnotationPresent(QueryIgnore.class) + || method.isAnnotationPresent(QueryExtended.class); + } + if (!skip && method.getName().startsWith("get") && method.getParameterTypes().length == 0) { + String name = Introspector.decapitalize(method.getName().substring(3)); if (action.equals(ACTION_INSERT)) { fields.append(name).append(", "); values.append(":").append(name).append(", "); } else { - fields.append(name).append(" = :").append(name).append(",\n"); + fields.append(name).append(" = :").append(name).append(", "); } } } @@ -154,12 +158,12 @@ public class DataManager { if (action.equals(ACTION_INSERT)) { values.setLength(values.length() - 2); result.append("INSERT INTO ").append(getObjectsTableName(clazz)).append(" ("); - result.append(fields).append(")\n"); + result.append(fields).append(") "); result.append("VALUES (").append(values).append(")"); } else { - result.append("UPDATE ").append(getObjectsTableName(clazz)).append(" SET\n"); + result.append("UPDATE ").append(getObjectsTableName(clazz)).append(" SET "); result.append(fields); - result.append("\nWHERE id = :id"); + result.append(" WHERE id = :id"); } return result.toString(); case ACTION_SELECT_ALL: @@ -170,7 +174,7 @@ public class DataManager { return "DELETE FROM " + getObjectsTableName(clazz) + " WHERE id = :id"; default: throw new IllegalArgumentException("Unknown action"); - } + } } public static String constructPermissionQuery(String action, Class owner, Class property) { @@ -188,7 +192,7 @@ public class DataManager { + " AND " + makeNameId(property) + " = :" + makeNameId(property); default: throw new IllegalArgumentException("Unknown action"); - } + } } private String getQuery(String key) { @@ -203,16 +207,16 @@ public class DataManager { return getQuery(action, clazz, false); } - public String getQuery(String action, Class clazz, boolean additional) { + public String getQuery(String action, Class clazz, boolean extended) { String queryName; if (action.equals(ACTION_SELECT_ALL)) { queryName = "database.select" + clazz.getSimpleName() + "s"; } else { - queryName = "database." + action.toLowerCase() + clazz.getSimpleName(); + queryName = "database." + action.toLowerCase() + clazz.getSimpleName() + (extended ? "Extended" : ""); } String query = config.getString(queryName); if (query == null) { - query = constructObjectQuery(action, clazz, additional); + query = constructObjectQuery(action, clazz, extended); config.setString(queryName, query); } @@ -238,18 +242,15 @@ public class DataManager { } private static String getPermissionsTableName(Class owner, Class property) { - String ownerName = owner.getSimpleName(); String propertyName = property.getSimpleName(); if (propertyName.equals("ManagedUser")) { propertyName = "User"; } - return ownerName.substring(0, 1).toLowerCase() + ownerName.substring(1) + "_" - + propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); + return Introspector.decapitalize(owner.getSimpleName()) + "_" + Introspector.decapitalize(propertyName); } private static String getObjectsTableName(Class clazz) { - String name = clazz.getSimpleName(); - return name.substring(0, 1).toLowerCase() + name.substring(1) + "s"; + return Introspector.decapitalize(clazz.getSimpleName()) + "s"; } private void initDatabaseSchema() throws SQLException, LiquibaseException { @@ -399,7 +400,7 @@ public class DataManager { public static String makeNameId(Class clazz) { String name = clazz.getSimpleName(); - return name.substring(0, 1).toLowerCase() + name.substring(1) + (name.indexOf("Id") == -1 ? "Id" : ""); + return Introspector.decapitalize(name) + (name.indexOf("Id") == -1 ? "Id" : ""); } public Collection getPermissions(Class owner, Class property) diff --git a/src/org/traccar/database/QueryAdditional.java b/src/org/traccar/database/QueryAdditional.java deleted file mode 100644 index 7a42c1875..000000000 --- a/src/org/traccar/database/QueryAdditional.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface QueryAdditional { -} diff --git a/src/org/traccar/database/QueryExtended.java b/src/org/traccar/database/QueryExtended.java new file mode 100644 index 000000000..07bc2c211 --- /dev/null +++ b/src/org/traccar/database/QueryExtended.java @@ -0,0 +1,27 @@ +/* + * 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.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface QueryExtended { +} diff --git a/src/org/traccar/model/Device.java b/src/org/traccar/model/Device.java index cd5dd12c4..c8a28404c 100644 --- a/src/org/traccar/model/Device.java +++ b/src/org/traccar/model/Device.java @@ -18,7 +18,7 @@ package org.traccar.model; import java.util.Date; import java.util.List; -import org.traccar.database.QueryAdditional; +import org.traccar.database.QueryExtended; import org.traccar.database.QueryIgnore; public class Device extends ExtendedModel { @@ -60,7 +60,7 @@ public class Device extends ExtendedModel { private Date lastUpdate; - @QueryAdditional + @QueryExtended public Date getLastUpdate() { if (lastUpdate != null) { return new Date(lastUpdate.getTime()); diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index 72b53ee5d..b71666f87 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -17,7 +17,7 @@ package org.traccar.model; import com.fasterxml.jackson.annotation.JsonIgnore; -import org.traccar.database.QueryAdditional; +import org.traccar.database.QueryExtended; import org.traccar.database.QueryIgnore; import org.traccar.helper.Hashing; @@ -247,7 +247,7 @@ public class User extends ExtendedModel { private String hashedPassword; @JsonIgnore - @QueryAdditional + @QueryExtended public String getHashedPassword() { return hashedPassword; } @@ -259,7 +259,7 @@ public class User extends ExtendedModel { private String salt; @JsonIgnore - @QueryAdditional + @QueryExtended public String getSalt() { return salt; } -- cgit v1.2.3 From 5f0d1137eb8402060bd655c58addf6c2646b2bce Mon Sep 17 00:00:00 2001 From: tsmgeek Date: Mon, 14 Aug 2017 22:38:59 +0100 Subject: Trim email address --- src/org/traccar/model/User.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/org/traccar/model/User.java') diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index b71666f87..3557521ab 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -43,7 +43,7 @@ public class User extends ExtendedModel { } public void setEmail(String email) { - this.email = email; + this.email = email.trim(); } private String phone; -- cgit v1.2.3 From fe5e6f7e1aaa01dfe8d61af46c3b818f8c566a25 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Wed, 6 Sep 2017 13:43:51 +0500 Subject: Move units to attributes and add volume units --- schema/changelog-3.15.xml | 8 ++++++ src/org/traccar/database/PermissionsManager.java | 22 ++------------ src/org/traccar/model/Server.java | 32 --------------------- src/org/traccar/model/User.java | 30 ------------------- .../notification/NotificationFormatter.java | 4 ++- src/org/traccar/reports/ReportUtils.java | 11 +++++-- templates/export/stops.xlsx | Bin 12855 -> 12870 bytes templates/export/summary.xlsx | Bin 8735 -> 12564 bytes templates/export/trips.xlsx | Bin 13239 -> 13154 bytes templates/mail/deviceOverspeed.vm | 4 +-- templates/sms/deviceOverspeed.vm | 4 +-- 11 files changed, 26 insertions(+), 89 deletions(-) (limited to 'src/org/traccar/model/User.java') diff --git a/schema/changelog-3.15.xml b/schema/changelog-3.15.xml index a2d944abb..37fd2e278 100644 --- a/schema/changelog-3.15.xml +++ b/schema/changelog-3.15.xml @@ -13,5 +13,13 @@ + + + + + + + + diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 3b03c1900..0708cc5c9 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -29,7 +29,6 @@ import org.traccar.model.Permission; import org.traccar.model.Server; import org.traccar.model.User; -import java.lang.reflect.Method; import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; @@ -382,25 +381,10 @@ public class PermissionsManager { return null; } - public Object lookupPreference(long userId, String key, Object defaultValue) { - String methodName = "get" + key.substring(0, 1).toUpperCase() + key.substring(1); + public Object lookupAttribute(long userId, String key, Object defaultValue) { Object preference; - Object serverPreference = null; - Object userPreference = null; - try { - Method method = null; - method = User.class.getMethod(methodName, (Class[]) null); - if (method != null) { - userPreference = method.invoke(getUser(userId), (Object[]) null); - } - method = null; - method = Server.class.getMethod(methodName, (Class[]) null); - if (method != null) { - serverPreference = method.invoke(server, (Object[]) null); - } - } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException exception) { - return defaultValue; - } + Object serverPreference = server.getAttributes().get(key); + Object userPreference = getUser(userId).getAttributes().get(key); if (server.getForceSettings()) { preference = serverPreference != null ? serverPreference : userPreference; } else { diff --git a/src/org/traccar/model/Server.java b/src/org/traccar/model/Server.java index 246be0b4f..bfe881479 100644 --- a/src/org/traccar/model/Server.java +++ b/src/org/traccar/model/Server.java @@ -15,8 +15,6 @@ */ package org.traccar.model; -import java.util.TimeZone; - import org.traccar.database.QueryIgnore; import org.traccar.helper.Log; @@ -90,26 +88,6 @@ public class Server extends ExtendedModel { this.mapUrl = mapUrl; } - private String distanceUnit; - - public String getDistanceUnit() { - return distanceUnit; - } - - public void setDistanceUnit(String distanceUnit) { - this.distanceUnit = distanceUnit; - } - - private String speedUnit; - - public String getSpeedUnit() { - return speedUnit; - } - - public void setSpeedUnit(String speedUnit) { - this.speedUnit = speedUnit; - } - private double latitude; public double getLatitude() { @@ -169,14 +147,4 @@ public class Server extends ExtendedModel { public void setCoordinateFormat(String coordinateFormat) { this.coordinateFormat = coordinateFormat; } - - private String timezone; - - public void setTimezone(String timezone) { - this.timezone = timezone != null ? TimeZone.getTimeZone(timezone).getID() : null; - } - - public String getTimezone() { - return timezone; - } } diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java index 3557521ab..043c23036 100644 --- a/src/org/traccar/model/User.java +++ b/src/org/traccar/model/User.java @@ -22,7 +22,6 @@ import org.traccar.database.QueryIgnore; import org.traccar.helper.Hashing; import java.util.Date; -import java.util.TimeZone; public class User extends ExtendedModel { @@ -86,26 +85,6 @@ public class User extends ExtendedModel { this.map = map; } - private String distanceUnit; - - public String getDistanceUnit() { - return distanceUnit; - } - - public void setDistanceUnit(String distanceUnit) { - this.distanceUnit = distanceUnit; - } - - private String speedUnit; - - public String getSpeedUnit() { - return speedUnit; - } - - public void setSpeedUnit(String speedUnit) { - this.speedUnit = speedUnit; - } - private double latitude; public double getLatitude() { @@ -272,13 +251,4 @@ public class User extends ExtendedModel { return Hashing.validatePassword(password, hashedPassword, salt); } - private String timezone; - - public void setTimezone(String timezone) { - this.timezone = timezone != null ? TimeZone.getTimeZone(timezone).getID() : null; - } - - public String getTimezone() { - return timezone; - } } diff --git a/src/org/traccar/notification/NotificationFormatter.java b/src/org/traccar/notification/NotificationFormatter.java index 33fd2cdc7..8da819430 100644 --- a/src/org/traccar/notification/NotificationFormatter.java +++ b/src/org/traccar/notification/NotificationFormatter.java @@ -48,7 +48,9 @@ public final class NotificationFormatter { velocityContext.put("event", event); if (position != null) { velocityContext.put("position", position); - velocityContext.put("speedUnits", ReportUtils.getSpeedUnit(userId)); + velocityContext.put("speedUnit", ReportUtils.getSpeedUnit(userId)); + velocityContext.put("distanceUnit", ReportUtils.getDistanceUnit(userId)); + velocityContext.put("volumeUnit", ReportUtils.getVolumeUnit(userId)); } if (event.getGeofenceId() != 0) { velocityContext.put("geofence", Context.getGeofenceManager().getById(event.getGeofenceId())); diff --git a/src/org/traccar/reports/ReportUtils.java b/src/org/traccar/reports/ReportUtils.java index 74cdaf9b5..5f718feac 100644 --- a/src/org/traccar/reports/ReportUtils.java +++ b/src/org/traccar/reports/ReportUtils.java @@ -62,15 +62,19 @@ public final class ReportUtils { } public static String getDistanceUnit(long userId) { - return (String) Context.getPermissionsManager().lookupPreference(userId, "distanceUnit", "km"); + return (String) Context.getPermissionsManager().lookupAttribute(userId, "distanceUnit", "km"); } public static String getSpeedUnit(long userId) { - return (String) Context.getPermissionsManager().lookupPreference(userId, "speedUnit", "kn"); + return (String) Context.getPermissionsManager().lookupAttribute(userId, "speedUnit", "kn"); + } + + public static String getVolumeUnit(long userId) { + return (String) Context.getPermissionsManager().lookupAttribute(userId, "volumeUnit", "ltr"); } public static TimeZone getTimezone(long userId) { - String timezone = (String) Context.getPermissionsManager().lookupPreference(userId, "timezone", null); + String timezone = (String) Context.getPermissionsManager().lookupAttribute(userId, "timezone", null); return timezone != null ? TimeZone.getTimeZone(timezone) : TimeZone.getDefault(); } @@ -137,6 +141,7 @@ public final class ReportUtils { org.jxls.common.Context jxlsContext = PoiTransformer.createInitialContext(); jxlsContext.putVar("distanceUnit", getDistanceUnit(userId)); jxlsContext.putVar("speedUnit", getSpeedUnit(userId)); + jxlsContext.putVar("volumeUnit", getVolumeUnit(userId)); jxlsContext.putVar("webUrl", Context.getVelocityEngine().getProperty("web.url")); jxlsContext.putVar("dateTool", new DateTool()); jxlsContext.putVar("numberTool", new NumberTool()); diff --git a/templates/export/stops.xlsx b/templates/export/stops.xlsx index d6bb4c3b9..0c00b7bff 100644 Binary files a/templates/export/stops.xlsx and b/templates/export/stops.xlsx differ diff --git a/templates/export/summary.xlsx b/templates/export/summary.xlsx index 73e702a70..a71f013a9 100644 Binary files a/templates/export/summary.xlsx and b/templates/export/summary.xlsx differ diff --git a/templates/export/trips.xlsx b/templates/export/trips.xlsx index 4a6734850..c5fa73342 100644 Binary files a/templates/export/trips.xlsx and b/templates/export/trips.xlsx differ diff --git a/templates/mail/deviceOverspeed.vm b/templates/mail/deviceOverspeed.vm index 0715a3d60..b1f0a6734 100644 --- a/templates/mail/deviceOverspeed.vm +++ b/templates/mail/deviceOverspeed.vm @@ -1,8 +1,8 @@ #set($subject = "$device.name: exceeds the speed") -#if($speedUnits == 'kmh') +#if($speedUnit == 'kmh') #set($speedValue = $position.speed * 1.852) #set($speedString = $numberTool.format("0.0 km/h", $speedValue)) -#elseif($speedUnits == 'mph') +#elseif($speedUnit == 'mph') #set($speedValue = $position.speed * 1.15078) #set($speedString = $numberTool.format("0.0 mph", $speedValue)) #else diff --git a/templates/sms/deviceOverspeed.vm b/templates/sms/deviceOverspeed.vm index ef0d9d955..f0b03c9e7 100644 --- a/templates/sms/deviceOverspeed.vm +++ b/templates/sms/deviceOverspeed.vm @@ -1,7 +1,7 @@ -#if($speedUnits == 'kmh') +#if($speedUnit == 'kmh') #set($speedValue = $position.speed * 1.852) #set($speedString = $numberTool.format("0.0 km/h", $speedValue)) -#elseif($speedUnits == 'mph') +#elseif($speedUnit == 'mph') #set($speedValue = $position.speed * 1.15078) #set($speedString = $numberTool.format("0.0 mph", $speedValue)) #else -- cgit v1.2.3 From 925806fe70e10e47bcc12eb8bcc4fe21a9ece220 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Tue, 12 Sep 2017 17:42:16 +0500 Subject: Implement Saved Commands --- schema/changelog-3.15.xml | 64 +++++++++- src/org/traccar/Context.java | 12 ++ src/org/traccar/api/BaseObjectResource.java | 7 ++ src/org/traccar/api/resource/CommandResource.java | 46 ++++++- .../traccar/api/resource/CommandTypeResource.java | 8 +- src/org/traccar/database/CommandsManager.java | 136 +++++++++++++++++++++ src/org/traccar/database/DataManager.java | 3 + src/org/traccar/database/DeviceManager.java | 51 -------- src/org/traccar/database/PermissionsManager.java | 26 ++++ src/org/traccar/model/Command.java | 18 +++ src/org/traccar/model/Server.java | 10 ++ src/org/traccar/model/User.java | 10 ++ 12 files changed, 332 insertions(+), 59 deletions(-) create mode 100644 src/org/traccar/database/CommandsManager.java (limited to 'src/org/traccar/model/User.java') 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"> - + @@ -21,5 +21,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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) geofenceManager; } else if (clazz.equals(Driver.class)) { return (BaseObjectManager) driversManager; + } else if (clazz.equals(Command.class)) { + return (BaseObjectManager) commandsManager; } return null; } diff --git a/src/org/traccar/api/BaseObjectResource.java b/src/org/traccar/api/BaseObjectResource.java index b13dc2e71..4315832b5 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; @@ -73,6 +74,8 @@ public abstract class BaseObjectResource 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 manager = Context.getManager(baseClass); @@ -98,6 +101,8 @@ public abstract class BaseObjectResource 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 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..f7e7d4f8c 100644 --- a/src/org/traccar/api/resource/CommandResource.java +++ b/src/org/traccar/api/resource/CommandResource.java @@ -16,26 +16,62 @@ 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 { + + public CommandResource() { + super(Command.class); + } + + @GET + @Path("send") + public Collection get(@QueryParam("deviceId") long deviceId, + @QueryParam("textChannel") boolean textChannel) throws SQLException { + Context.getPermissionsManager().checkDevice(getUserId(), deviceId); + CommandsManager commandsManager = Context.getCommandsManager(); + Set result = null; + result = new HashSet<>(commandsManager.getUserItems(getUserId())); + result.retainAll(commandsManager.getProperCommands(deviceId, textChannel)); + 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); + Command command = entity; + long deviceId = command.getDeviceId(); + long id = command.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(command); + } 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 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/database/CommandsManager.java b/src/org/traccar/database/CommandsManager.java new file mode 100644 index 000000000..9f97c929c --- /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 { + + 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 getProperCommands(long deviceId, boolean textChannel) { + List result = new ArrayList<>(); + Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId); + for (long commandId : getAllDeviceItems(deviceId)) { + Command command = getById(commandId); + if (command.getTextChannel() == textChannel) { + if (lastPosition != null) { + BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol()); + Collection protocolCommands = + textChannel ? protocol.getSupportedTextCommands() : protocol.getSupportedDataCommands(); + if (protocolCommands.contains(command.getType())) { + result.add(commandId); + } + } else if (command.getType().equals(Command.TYPE_CUSTOM)) { + result.add(commandId); + } + } + } + return result; + } + + public Collection getCommandTypes(long deviceId, boolean textChannel) { + List result = new ArrayList<>(); + Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId); + if (lastPosition != null) { + BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol()); + Collection 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 getAllCommandTypes() { + List 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 implements Identity private final Map 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 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 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 getCommandTypes(long deviceId, boolean textChannel) { - List result = new ArrayList<>(); - Position lastPosition = Context.getDeviceManager().getLastPosition(deviceId); - if (lastPosition != null) { - BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol()); - Collection 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..3da99dd13 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; @@ -197,6 +198,11 @@ public class PermissionsManager { return user != null && user.getDeviceReadonly(); } + public boolean isLimitCommands(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))) { throw new SecurityException("Account is readonly"); @@ -209,6 +215,18 @@ public class PermissionsManager { } } + public void checkLimitCommands(long userId) throws SecurityException { + if (!isAdmin(userId) && (server.getLimitCommands() || isLimitCommands(userId))) { + throw new SecurityException("Account has limit sending commands"); + } + } + + public void checkUserDeviceCommand(long userId, long deviceId, long commandId) throws SecurityException { + if (!isAdmin(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) { @@ -300,6 +318,8 @@ 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"); } @@ -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; -- cgit v1.2.3