From 9acf9c7f7a4c3d8279b0afb9683098984a1b4518 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 31 Jan 2022 22:57:36 -0800 Subject: Add option to disable reports --- src/main/java/org/traccar/api/resource/ReportResource.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 7347bfd64..23ffaf54c 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2016 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -99,6 +99,7 @@ public class ReportResource extends BaseResource { public Collection getRoute( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); return Route.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -110,6 +111,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws SQLException, IOException { + Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); Route.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); @@ -122,6 +124,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); return Events.getObjects(getUserId(), deviceIds, groupIds, types, from, to); } @@ -134,6 +137,7 @@ public class ReportResource extends BaseResource { @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws SQLException, IOException { + Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); Events.getExcel(stream, getUserId(), deviceIds, groupIds, types, from, to); @@ -146,6 +150,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily) throws SQLException { + Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); return Summary.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); } @@ -158,6 +163,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily, @QueryParam("mail") boolean mail) throws SQLException, IOException { + Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); Summary.getExcel(stream, getUserId(), deviceIds, groupIds, from, to, daily); @@ -170,6 +176,7 @@ public class ReportResource extends BaseResource { public Collection getTrips( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); return Trips.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -181,6 +188,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws SQLException, IOException { + Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); Trips.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); @@ -193,6 +201,7 @@ public class ReportResource extends BaseResource { public Collection getStops( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); return Stops.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -204,6 +213,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws SQLException, IOException { + Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); Stops.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); -- cgit v1.2.3 From 1c73bae2e23242673e0a07cdbc2493700f134ceb Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 13 Feb 2022 23:34:25 -0800 Subject: New storage implementation --- setup/default.xml | 30 --- src/main/java/org/traccar/MainEventHandler.java | 4 +- .../java/org/traccar/api/BaseObjectResource.java | 7 +- .../org/traccar/api/SecurityRequestFilter.java | 4 +- .../traccar/api/resource/AttributeResource.java | 9 +- .../org/traccar/api/resource/DeviceResource.java | 3 +- .../org/traccar/api/resource/EventResource.java | 6 +- .../org/traccar/api/resource/PasswordResource.java | 6 +- .../traccar/api/resource/PermissionsResource.java | 10 +- .../org/traccar/api/resource/PositionResource.java | 4 +- .../org/traccar/api/resource/ReportResource.java | 28 +-- .../org/traccar/api/resource/ServerResource.java | 6 +- .../org/traccar/api/resource/SessionResource.java | 6 +- .../traccar/api/resource/StatisticsResource.java | 4 +- .../org/traccar/api/resource/UserResource.java | 3 +- .../org/traccar/database/BaseObjectManager.java | 10 +- .../org/traccar/database/ConnectionManager.java | 6 +- .../java/org/traccar/database/DataManager.java | 265 ++++++++------------- .../java/org/traccar/database/DeviceManager.java | 28 +-- .../traccar/database/ExtendedObjectManager.java | 6 +- .../java/org/traccar/database/GroupsManager.java | 4 +- .../org/traccar/database/NotificationManager.java | 4 +- .../org/traccar/database/PermissionsManager.java | 10 +- .../org/traccar/database/SimpleObjectManager.java | 6 +- .../org/traccar/database/StatisticsManager.java | 4 +- .../java/org/traccar/database/UsersManager.java | 9 + .../java/org/traccar/handler/FilterHandler.java | 4 +- src/main/java/org/traccar/model/Attribute.java | 3 + src/main/java/org/traccar/model/Calendar.java | 2 + src/main/java/org/traccar/model/Command.java | 8 + src/main/java/org/traccar/model/Device.java | 7 +- src/main/java/org/traccar/model/Driver.java | 4 + src/main/java/org/traccar/model/Event.java | 3 + src/main/java/org/traccar/model/Geofence.java | 2 + src/main/java/org/traccar/model/Group.java | 3 + src/main/java/org/traccar/model/Maintenance.java | 3 + src/main/java/org/traccar/model/Notification.java | 4 +- src/main/java/org/traccar/model/Order.java | 3 + src/main/java/org/traccar/model/Position.java | 15 +- src/main/java/org/traccar/model/Server.java | 2 + src/main/java/org/traccar/model/Statistics.java | 3 + src/main/java/org/traccar/model/User.java | 2 + src/main/java/org/traccar/reports/Events.java | 6 +- src/main/java/org/traccar/reports/Route.java | 6 +- src/main/java/org/traccar/reports/Stops.java | 8 +- src/main/java/org/traccar/reports/Summary.java | 8 +- src/main/java/org/traccar/reports/Trips.java | 8 +- .../java/org/traccar/storage/DatabaseStorage.java | 71 ++++-- .../java/org/traccar/storage/QueryBuilder.java | 6 +- src/main/java/org/traccar/storage/Storage.java | 15 +- .../java/org/traccar/storage/query/Columns.java | 22 +- .../java/org/traccar/storage/query/Condition.java | 42 +++- src/main/java/org/traccar/storage/query/Limit.java | 15 ++ .../java/org/traccar/storage/query/Request.java | 22 ++ .../java/org/traccar/database/DataManagerTest.java | 81 ------- 55 files changed, 420 insertions(+), 440 deletions(-) create mode 100644 src/main/java/org/traccar/storage/query/Limit.java delete mode 100644 src/test/java/org/traccar/database/DataManagerTest.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/setup/default.xml b/setup/default.xml index 0d8133627..a1ba5ca33 100644 --- a/setup/default.xml +++ b/setup/default.xml @@ -41,37 +41,7 @@ true true - true ./schema/changelog-master.xml - - - SELECT * FROM tc_users - WHERE email = :email OR login = :email - - - - SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime BETWEEN :from AND :to ORDER BY fixTime - - - - SELECT * FROM tc_positions WHERE deviceId = :deviceId AND fixTime <= :time ORDER BY fixTime DESC LIMIT 1 - - - - SELECT tc_positions.* FROM tc_positions INNER JOIN tc_devices ON tc_positions.id = tc_devices.positionid; - - - - UPDATE tc_devices SET positionId = :id WHERE id = :deviceId - - - - SELECT * FROM tc_events WHERE deviceId = :deviceId AND eventTime BETWEEN :from AND :to ORDER BY eventTime - - - - SELECT * FROM tc_statistics WHERE captureTime BETWEEN :from AND :to ORDER BY captureTime - 5001 5002 diff --git a/src/main/java/org/traccar/MainEventHandler.java b/src/main/java/org/traccar/MainEventHandler.java index 4889f6a2e..a3f6f4105 100644 --- a/src/main/java/org/traccar/MainEventHandler.java +++ b/src/main/java/org/traccar/MainEventHandler.java @@ -27,8 +27,8 @@ import org.traccar.config.Keys; import org.traccar.database.StatisticsManager; import org.traccar.helper.DateUtil; import org.traccar.model.Position; +import org.traccar.storage.StorageException; -import java.sql.SQLException; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; @@ -57,7 +57,7 @@ public class MainEventHandler extends ChannelInboundHandlerAdapter { Position position = (Position) msg; try { Context.getDeviceManager().updateLatestPosition(position); - } catch (SQLException error) { + } catch (StorageException error) { LOGGER.warn("Failed to update device", error); } diff --git a/src/main/java/org/traccar/api/BaseObjectResource.java b/src/main/java/org/traccar/api/BaseObjectResource.java index 71f3939cb..22756f62a 100644 --- a/src/main/java/org/traccar/api/BaseObjectResource.java +++ b/src/main/java/org/traccar/api/BaseObjectResource.java @@ -41,6 +41,7 @@ import org.traccar.model.Group; import org.traccar.model.GroupedModel; import org.traccar.model.ScheduledModel; import org.traccar.model.User; +import org.traccar.storage.StorageException; public abstract class BaseObjectResource extends BaseResource { @@ -87,7 +88,7 @@ public abstract class BaseObjectResource extends BaseResour } @POST - public Response add(T entity) throws SQLException { + public Response add(T entity) throws StorageException { Context.getPermissionsManager().checkReadonly(getUserId()); if (baseClass.equals(Device.class)) { Context.getPermissionsManager().checkDeviceReadonly(getUserId()); @@ -120,7 +121,7 @@ public abstract class BaseObjectResource extends BaseResour @Path("{id}") @PUT - public Response update(T entity) throws SQLException { + public Response update(T entity) throws StorageException { Context.getPermissionsManager().checkReadonly(getUserId()); if (baseClass.equals(Device.class)) { Context.getPermissionsManager().checkDeviceReadonly(getUserId()); @@ -150,7 +151,7 @@ public abstract class BaseObjectResource extends BaseResour @Path("{id}") @DELETE - public Response remove(@PathParam("id") long id) throws SQLException { + public Response remove(@PathParam("id") long id) throws StorageException { Context.getPermissionsManager().checkReadonly(getUserId()); if (baseClass.equals(Device.class)) { Context.getPermissionsManager().checkDeviceReadonly(getUserId()); diff --git a/src/main/java/org/traccar/api/SecurityRequestFilter.java b/src/main/java/org/traccar/api/SecurityRequestFilter.java index 33b6b37df..6b190be9f 100644 --- a/src/main/java/org/traccar/api/SecurityRequestFilter.java +++ b/src/main/java/org/traccar/api/SecurityRequestFilter.java @@ -23,6 +23,7 @@ import org.traccar.api.resource.SessionResource; import org.traccar.database.StatisticsManager; import org.traccar.helper.DataConverter; import org.traccar.model.User; +import org.traccar.storage.StorageException; import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletRequest; @@ -34,7 +35,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; -import java.sql.SQLException; public class SecurityRequestFilter implements ContainerRequestFilter { @@ -82,7 +82,7 @@ public class SecurityRequestFilter implements ContainerRequestFilter { Main.getInjector().getInstance(StatisticsManager.class).registerRequest(user.getId()); securityContext = new UserSecurityContext(new UserPrincipal(user.getId())); } - } catch (SQLException e) { + } catch (StorageException e) { throw new WebApplicationException(e); } diff --git a/src/main/java/org/traccar/api/resource/AttributeResource.java b/src/main/java/org/traccar/api/resource/AttributeResource.java index de69d871c..d2dc28903 100644 --- a/src/main/java/org/traccar/api/resource/AttributeResource.java +++ b/src/main/java/org/traccar/api/resource/AttributeResource.java @@ -16,8 +16,6 @@ */ package org.traccar.api.resource; -import java.sql.SQLException; - import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.POST; @@ -34,6 +32,7 @@ import org.traccar.api.ExtendedObjectResource; import org.traccar.model.Attribute; import org.traccar.model.Position; import org.traccar.handler.ComputedAttributesHandler; +import org.traccar.storage.StorageException; @Path("attributes/computed") @Produces(MediaType.APPLICATION_JSON) @@ -75,21 +74,21 @@ public class AttributeResource extends ExtendedObjectResource { } @POST - public Response add(Attribute entity) throws SQLException { + public Response add(Attribute entity) throws StorageException { Context.getPermissionsManager().checkAdmin(getUserId()); return super.add(entity); } @Path("{id}") @PUT - public Response update(Attribute entity) throws SQLException { + public Response update(Attribute entity) throws StorageException { Context.getPermissionsManager().checkAdmin(getUserId()); return super.update(entity); } @Path("{id}") @DELETE - public Response remove(@PathParam("id") long id) throws SQLException { + public Response remove(@PathParam("id") long id) throws StorageException { Context.getPermissionsManager().checkAdmin(getUserId()); return super.remove(id); } diff --git a/src/main/java/org/traccar/api/resource/DeviceResource.java b/src/main/java/org/traccar/api/resource/DeviceResource.java index 7006cdb84..9436b59f6 100644 --- a/src/main/java/org/traccar/api/resource/DeviceResource.java +++ b/src/main/java/org/traccar/api/resource/DeviceResource.java @@ -21,6 +21,7 @@ import org.traccar.database.DeviceManager; import org.traccar.helper.LogAction; import org.traccar.model.Device; import org.traccar.model.DeviceAccumulators; +import org.traccar.storage.StorageException; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -87,7 +88,7 @@ public class DeviceResource extends BaseObjectResource { @Path("{id}/accumulators") @PUT - public Response updateAccumulators(DeviceAccumulators entity) throws SQLException { + public Response updateAccumulators(DeviceAccumulators entity) throws StorageException { if (!Context.getPermissionsManager().getUserAdmin(getUserId())) { Context.getPermissionsManager().checkManager(getUserId()); Context.getPermissionsManager().checkPermission(Device.class, getUserId(), entity.getDeviceId()); diff --git a/src/main/java/org/traccar/api/resource/EventResource.java b/src/main/java/org/traccar/api/resource/EventResource.java index 34e4a94ce..354d96e4f 100644 --- a/src/main/java/org/traccar/api/resource/EventResource.java +++ b/src/main/java/org/traccar/api/resource/EventResource.java @@ -15,8 +15,6 @@ */ package org.traccar.api.resource; -import java.sql.SQLException; - import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -31,16 +29,16 @@ import org.traccar.api.BaseResource; import org.traccar.model.Event; import org.traccar.model.Geofence; import org.traccar.model.Maintenance; +import org.traccar.storage.StorageException; @Path("events") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - public class EventResource extends BaseResource { @Path("{id}") @GET - public Event get(@PathParam("id") long id) throws SQLException { + public Event get(@PathParam("id") long id) throws StorageException { Event event = Context.getDataManager().getObject(Event.class, id); if (event == null) { throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build()); diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java index 1868a6191..0642ff3cc 100644 --- a/src/main/java/org/traccar/api/resource/PasswordResource.java +++ b/src/main/java/org/traccar/api/resource/PasswordResource.java @@ -21,6 +21,7 @@ import org.traccar.api.BaseResource; import org.traccar.model.User; import org.traccar.notification.NotificationMessage; import org.traccar.notification.TextTemplateFormatter; +import org.traccar.storage.StorageException; import javax.annotation.security.PermitAll; import javax.mail.MessagingException; @@ -31,7 +32,6 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.sql.SQLException; import java.util.UUID; @Path("password") @@ -44,7 +44,7 @@ public class PasswordResource extends BaseResource { @Path("reset") @PermitAll @POST - public Response reset(@FormParam("email") String email) throws SQLException, MessagingException { + public Response reset(@FormParam("email") String email) throws StorageException, MessagingException { for (long userId : Context.getUsersManager().getAllItems()) { User user = Context.getUsersManager().getById(userId); if (email.equals(user.getEmail())) { @@ -66,7 +66,7 @@ public class PasswordResource extends BaseResource { @PermitAll @POST public Response update( - @FormParam("token") String token, @FormParam("password") String password) throws SQLException { + @FormParam("token") String token, @FormParam("password") String password) throws StorageException { for (long userId : Context.getUsersManager().getAllItems()) { User user = Context.getUsersManager().getById(userId); if (token.equals(user.getString(PASSWORD_RESET_TOKEN))) { diff --git a/src/main/java/org/traccar/api/resource/PermissionsResource.java b/src/main/java/org/traccar/api/resource/PermissionsResource.java index 54d3964b6..7def38919 100644 --- a/src/main/java/org/traccar/api/resource/PermissionsResource.java +++ b/src/main/java/org/traccar/api/resource/PermissionsResource.java @@ -16,7 +16,6 @@ */ package org.traccar.api.resource; -import java.sql.SQLException; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -37,6 +36,7 @@ import org.traccar.helper.LogAction; import org.traccar.model.Device; import org.traccar.model.Permission; import org.traccar.model.User; +import org.traccar.storage.StorageException; @Path("permissions") @Produces(MediaType.APPLICATION_JSON) @@ -71,7 +71,7 @@ public class PermissionsResource extends BaseResource { @Path("bulk") @POST - public Response add(List> entities) throws SQLException, ClassNotFoundException { + public Response add(List> entities) throws StorageException, ClassNotFoundException { Context.getPermissionsManager().checkReadonly(getUserId()); checkPermissionTypes(entities); for (LinkedHashMap entity: entities) { @@ -89,13 +89,13 @@ public class PermissionsResource extends BaseResource { } @POST - public Response add(LinkedHashMap entity) throws SQLException, ClassNotFoundException { + public Response add(LinkedHashMap entity) throws StorageException, ClassNotFoundException { return add(Collections.singletonList(entity)); } @DELETE @Path("bulk") - public Response remove(List> entities) throws SQLException, ClassNotFoundException { + public Response remove(List> entities) throws StorageException, ClassNotFoundException { Context.getPermissionsManager().checkReadonly(getUserId()); checkPermissionTypes(entities); for (LinkedHashMap entity: entities) { @@ -113,7 +113,7 @@ public class PermissionsResource extends BaseResource { } @DELETE - public Response remove(LinkedHashMap entity) throws SQLException, ClassNotFoundException { + public Response remove(LinkedHashMap entity) throws StorageException, ClassNotFoundException { return remove(Collections.singletonList(entity)); } diff --git a/src/main/java/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java index 53157197b..511032402 100644 --- a/src/main/java/org/traccar/api/resource/PositionResource.java +++ b/src/main/java/org/traccar/api/resource/PositionResource.java @@ -18,6 +18,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; import org.traccar.model.Position; +import org.traccar.storage.StorageException; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -25,7 +26,6 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -41,7 +41,7 @@ public class PositionResource extends BaseResource { public Collection getJson( @QueryParam("deviceId") long deviceId, @QueryParam("id") List positionIds, @QueryParam("from") Date from, @QueryParam("to") Date to) - throws SQLException { + throws StorageException { if (!positionIds.isEmpty()) { ArrayList positions = new ArrayList<>(); for (Long positionId : positionIds) { diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 23ffaf54c..03df0d03a 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -18,7 +18,6 @@ package org.traccar.api.resource; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.sql.SQLException; import java.util.Collection; import java.util.Date; import java.util.List; @@ -51,6 +50,7 @@ import org.traccar.reports.model.SummaryReport; import org.traccar.reports.model.TripReport; import org.traccar.reports.Route; import org.traccar.reports.Stops; +import org.traccar.storage.StorageException; @Path("reports") @Produces(MediaType.APPLICATION_JSON) @@ -63,11 +63,11 @@ public class ReportResource extends BaseResource { private static final String CONTENT_DISPOSITION_VALUE_XLSX = "attachment; filename=report.xlsx"; private interface ReportExecutor { - void execute(ByteArrayOutputStream stream) throws SQLException, IOException; + void execute(ByteArrayOutputStream stream) throws StorageException, IOException; } private Response executeReport( - long userId, boolean mail, ReportExecutor executor) throws SQLException, IOException { + long userId, boolean mail, ReportExecutor executor) throws StorageException, IOException { final ByteArrayOutputStream stream = new ByteArrayOutputStream(); if (mail) { new Thread(() -> { @@ -82,7 +82,7 @@ public class ReportResource extends BaseResource { Context.getMailManager().sendMessage( userId, "Report", "The report is in the attachment.", attachment); - } catch (SQLException | IOException | MessagingException e) { + } catch (StorageException | IOException | MessagingException e) { LOGGER.warn("Report failed", e); } }).start(); @@ -98,7 +98,7 @@ public class ReportResource extends BaseResource { @GET public Collection getRoute( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); return Route.getObjects(getUserId(), deviceIds, groupIds, from, to); @@ -110,7 +110,7 @@ public class ReportResource extends BaseResource { public Response getRouteExcel( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws SQLException, IOException { + throws StorageException, IOException { Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); @@ -123,7 +123,7 @@ public class ReportResource extends BaseResource { public Collection getEvents( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("type") final List types, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); return Events.getObjects(getUserId(), deviceIds, groupIds, types, from, to); @@ -136,7 +136,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws SQLException, IOException { + throws StorageException, IOException { Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); @@ -149,7 +149,7 @@ public class ReportResource extends BaseResource { public Collection getSummary( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily) - throws SQLException { + throws StorageException { Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); return Summary.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); @@ -162,7 +162,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily, @QueryParam("mail") boolean mail) - throws SQLException, IOException { + throws StorageException, IOException { Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); @@ -175,7 +175,7 @@ public class ReportResource extends BaseResource { @Produces(MediaType.APPLICATION_JSON) public Collection getTrips( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); return Trips.getObjects(getUserId(), deviceIds, groupIds, from, to); @@ -187,7 +187,7 @@ public class ReportResource extends BaseResource { public Response getTripsExcel( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws SQLException, IOException { + throws StorageException, IOException { Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); @@ -200,7 +200,7 @@ public class ReportResource extends BaseResource { @Produces(MediaType.APPLICATION_JSON) public Collection getStops( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { Context.getPermissionsManager().checkDisableReports(getUserId()); LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); return Stops.getObjects(getUserId(), deviceIds, groupIds, from, to); @@ -212,7 +212,7 @@ public class ReportResource extends BaseResource { public Response getStopsExcel( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws SQLException, IOException { + throws StorageException, IOException { Context.getPermissionsManager().checkDisableReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); diff --git a/src/main/java/org/traccar/api/resource/ServerResource.java b/src/main/java/org/traccar/api/resource/ServerResource.java index 91488afff..8096c66fa 100644 --- a/src/main/java/org/traccar/api/resource/ServerResource.java +++ b/src/main/java/org/traccar/api/resource/ServerResource.java @@ -19,6 +19,7 @@ import org.traccar.Context; import org.traccar.api.BaseResource; import org.traccar.helper.LogAction; import org.traccar.model.Server; +import org.traccar.storage.StorageException; import javax.annotation.security.PermitAll; import javax.ws.rs.Consumes; @@ -29,7 +30,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.sql.SQLException; @Path("server") @Produces(MediaType.APPLICATION_JSON) @@ -38,7 +38,7 @@ public class ServerResource extends BaseResource { @PermitAll @GET - public Server get(@QueryParam("force") boolean force) throws SQLException { + public Server get(@QueryParam("force") boolean force) throws StorageException { if (force) { return Context.getDataManager().getServer(); } else { @@ -47,7 +47,7 @@ public class ServerResource extends BaseResource { } @PUT - public Response update(Server entity) throws SQLException { + public Response update(Server entity) throws StorageException { Context.getPermissionsManager().checkAdmin(getUserId()); Context.getPermissionsManager().updateServer(entity); LogAction.edit(getUserId(), entity); diff --git a/src/main/java/org/traccar/api/resource/SessionResource.java b/src/main/java/org/traccar/api/resource/SessionResource.java index 60ce5490a..8422e0b49 100644 --- a/src/main/java/org/traccar/api/resource/SessionResource.java +++ b/src/main/java/org/traccar/api/resource/SessionResource.java @@ -21,6 +21,7 @@ import org.traccar.helper.DataConverter; import org.traccar.helper.ServletHelper; import org.traccar.helper.LogAction; import org.traccar.model.User; +import org.traccar.storage.StorageException; import javax.annotation.security.PermitAll; import javax.servlet.http.Cookie; @@ -40,7 +41,6 @@ import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; -import java.sql.SQLException; @Path("session") @Produces(MediaType.APPLICATION_JSON) @@ -56,7 +56,7 @@ public class SessionResource extends BaseResource { @PermitAll @GET - public User get(@QueryParam("token") String token) throws SQLException, UnsupportedEncodingException { + public User get(@QueryParam("token") String token) throws StorageException, UnsupportedEncodingException { if (token != null) { User user = Context.getUsersManager().getUserByToken(token); @@ -107,7 +107,7 @@ public class SessionResource extends BaseResource { @PermitAll @POST public User add( - @FormParam("email") String email, @FormParam("password") String password) throws SQLException { + @FormParam("email") String email, @FormParam("password") String password) throws StorageException { User user = Context.getPermissionsManager().login(email, password); if (user != null) { request.getSession().setAttribute(USER_ID_KEY, user.getId()); diff --git a/src/main/java/org/traccar/api/resource/StatisticsResource.java b/src/main/java/org/traccar/api/resource/StatisticsResource.java index 58073e7d1..5c0734877 100644 --- a/src/main/java/org/traccar/api/resource/StatisticsResource.java +++ b/src/main/java/org/traccar/api/resource/StatisticsResource.java @@ -18,6 +18,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; import org.traccar.model.Statistics; +import org.traccar.storage.StorageException; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -25,7 +26,6 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; -import java.sql.SQLException; import java.util.Collection; import java.util.Date; @@ -36,7 +36,7 @@ public class StatisticsResource extends BaseResource { @GET public Collection get( - @QueryParam("from") Date from, @QueryParam("to") Date to) throws SQLException { + @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { Context.getPermissionsManager().checkAdmin(getUserId()); return Context.getDataManager().getStatistics(from, to); } diff --git a/src/main/java/org/traccar/api/resource/UserResource.java b/src/main/java/org/traccar/api/resource/UserResource.java index d54cc2382..83bb8fd0b 100644 --- a/src/main/java/org/traccar/api/resource/UserResource.java +++ b/src/main/java/org/traccar/api/resource/UserResource.java @@ -22,6 +22,7 @@ import org.traccar.database.UsersManager; import org.traccar.helper.LogAction; import org.traccar.model.ManagedUser; import org.traccar.model.User; +import org.traccar.storage.StorageException; import javax.annotation.security.PermitAll; import javax.ws.rs.Consumes; @@ -67,7 +68,7 @@ public class UserResource extends BaseObjectResource { @Override @PermitAll @POST - public Response add(User entity) throws SQLException { + public Response add(User entity) throws StorageException { if (!Context.getPermissionsManager().getUserAdmin(getUserId())) { Context.getPermissionsManager().checkUserUpdate(getUserId(), new User(), entity); if (Context.getPermissionsManager().getUserManager(getUserId())) { diff --git a/src/main/java/org/traccar/database/BaseObjectManager.java b/src/main/java/org/traccar/database/BaseObjectManager.java index be6310033..dd8b3bae4 100644 --- a/src/main/java/org/traccar/database/BaseObjectManager.java +++ b/src/main/java/org/traccar/database/BaseObjectManager.java @@ -16,7 +16,6 @@ */ package org.traccar.database; -import java.sql.SQLException; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; @@ -29,6 +28,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.model.BaseModel; +import org.traccar.storage.StorageException; public class BaseObjectManager { @@ -102,7 +102,7 @@ public class BaseObjectManager { removeCachedItem(cachedItemId); } } - } catch (SQLException error) { + } catch (StorageException error) { LOGGER.warn("Error refreshing items", error); } finally { writeUnlock(); @@ -119,7 +119,7 @@ public class BaseObjectManager { } } - public void addItem(T item) throws SQLException { + public void addItem(T item) throws StorageException { dataManager.addObject(item); addNewItem(item); } @@ -133,7 +133,7 @@ public class BaseObjectManager { } } - public void updateItem(T item) throws SQLException { + public void updateItem(T item) throws StorageException { dataManager.updateObject(item); updateCachedItem(item); } @@ -147,7 +147,7 @@ public class BaseObjectManager { } } - public void removeItem(long itemId) throws SQLException { + public void removeItem(long itemId) throws StorageException { BaseModel item = getById(itemId); if (item != null) { dataManager.removeObject(baseClass, itemId); diff --git a/src/main/java/org/traccar/database/ConnectionManager.java b/src/main/java/org/traccar/database/ConnectionManager.java index e12d44612..359061f00 100644 --- a/src/main/java/org/traccar/database/ConnectionManager.java +++ b/src/main/java/org/traccar/database/ConnectionManager.java @@ -30,9 +30,9 @@ import org.traccar.model.Device; import org.traccar.model.DeviceState; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.storage.StorageException; import java.net.SocketAddress; -import java.sql.SQLException; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -127,8 +127,8 @@ public class ConnectionManager { try { Context.getDeviceManager().updateDeviceStatus(device); - } catch (SQLException error) { - LOGGER.warn("Update device status error", error); + } catch (StorageException e) { + LOGGER.warn("Update device status error", e); } updateDevice(device); diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java index 199167419..303b8e033 100644 --- a/src/main/java/org/traccar/database/DataManager.java +++ b/src/main/java/org/traccar/database/DataManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2012 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,15 +41,20 @@ import org.traccar.model.Group; import org.traccar.model.Maintenance; import org.traccar.model.ManagedUser; import org.traccar.model.Notification; -import org.traccar.model.Order; import org.traccar.model.Permission; import org.traccar.model.Position; import org.traccar.model.Server; import org.traccar.model.Statistics; import org.traccar.model.User; +import org.traccar.storage.DatabaseStorage; import org.traccar.storage.QueryBuilder; -import org.traccar.storage.QueryExtended; -import org.traccar.storage.QueryIgnore; +import org.traccar.storage.Storage; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Limit; +import org.traccar.storage.query.Order; +import org.traccar.storage.query.Request; import javax.sql.DataSource; import java.beans.Introspector; @@ -57,11 +62,10 @@ import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.sql.SQLException; -import java.util.Arrays; import java.util.Collection; import java.util.Date; -import java.util.HashSet; -import java.util.Set; +import java.util.LinkedList; +import java.util.List; public class DataManager { @@ -81,6 +85,8 @@ public class DataManager { return dataSource; } + private final Storage storage; + private boolean generateQueries; private final boolean forceLdap; @@ -92,6 +98,8 @@ public class DataManager { initDatabase(); initDatabaseSchema(); + + storage = new DatabaseStorage(dataSource); } private void initDatabase() throws Exception { @@ -134,58 +142,6 @@ public class DataManager { dataSource = new HikariDataSource(hikariConfig); } - public static String constructObjectQuery(String action, Class clazz, boolean extended) { - 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) { - boolean skip; - if (extended) { - skip = !method.isAnnotationPresent(QueryExtended.class); - } else { - skip = method.isAnnotationPresent(QueryIgnore.class) - || method.isAnnotationPresent(QueryExtended.class) && !action.equals(ACTION_INSERT); - } - 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(", "); - } - } - } - 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(") "); - result.append("VALUES (").append(values).append(")"); - } else { - result.append("UPDATE ").append(getObjectsTableName(clazz)).append(" SET "); - result.append(fields); - result.append(" WHERE 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: @@ -204,39 +160,6 @@ public class DataManager { } } - private String getQuery(String key) { - String query = config.getString(key); - if (query == null) { - LOGGER.info("Query not provided: " + key); - } - return query; - } - - public String getQuery(String action, Class clazz) { - return getQuery(action, clazz, false); - } - - 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(); - if (extended) { - queryName += "Extended"; - } - } - String query = config.getString(queryName); - if (query == null) { - if (generateQueries) { - query = constructObjectQuery(action, clazz, extended); - } else { - LOGGER.info("Query not provided: " + queryName); - } - } - return query; - } - public String getQuery(String action, Class owner, Class property) { String queryName; switch (action) { @@ -302,10 +225,12 @@ public class DataManager { } } - public User login(String email, String password) throws SQLException { - User user = QueryBuilder.create(dataSource, getQuery("database.loginUser")) - .setString("email", email.trim()) - .executeQuerySingle(User.class); + public User login(String email, String password) throws StorageException { + User user = storage.getObject(User.class, new Request( + new Columns.Include("id", "login", "hashedPassword", "salt"), + new Condition.Or( + new Condition.Equals("email", "email", email.trim()), + new Condition.Equals("login", "email")))); LdapProvider ldapProvider = Context.getLdapProvider(); if (user != null) { if (ldapProvider != null && user.getLogin() != null && ldapProvider.login(user.getLogin(), password) @@ -322,57 +247,75 @@ public class DataManager { return null; } - public void updateDeviceStatus(Device device) throws SQLException { - QueryBuilder.create(dataSource, getQuery(ACTION_UPDATE, Device.class, true)) - .setObject(device) - .executeUpdate(); + public void updateUserPassword(User user) throws StorageException { + storage.updateObject(user, new Request( + new Columns.Include("hashedPassword", "salt"), + new Condition.Equals("id", "id"))); } - public Collection getPositions(long deviceId, Date from, Date to) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectPositions")) - .setLong("deviceId", deviceId) - .setDate("from", from) - .setDate("to", to) - .executeQuery(Position.class); + public void updateDeviceStatus(Device device) throws StorageException { + storage.updateObject(device, new Request( + new Columns.Include("lastUpdate"), + new Condition.Equals("id", "id"))); } - public Position getPrecedingPosition(long deviceId, Date date) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectPrecedingPosition")) - .setLong("deviceId", deviceId) - .setDate("time", date) - .executeQuerySingle(Position.class); + public Collection getPositions(long deviceId, Date from, Date to) throws StorageException { + return storage.getObjects(Position.class, new Request( + new Columns.All(), + new Condition.And( + new Condition.Equals("deviceId", "deviceId", deviceId), + new Condition.Between("fixTime", "from", from, "to", to)), + new Order("fixTime"))); } - public void updateLatestPosition(Position position) throws SQLException { - QueryBuilder.create(dataSource, getQuery("database.updateLatestPosition")) - .setDate("now", new Date()) - .setObject(position) - .executeUpdate(); + public Position getPrecedingPosition(long deviceId, Date date) throws StorageException { + return storage.getObject(Position.class, new Request( + new Columns.All(), + new Condition.And( + new Condition.Equals("deviceId", "deviceId", deviceId), + new Condition.Compare("fixTime", "<=", "time", date)), + new Order(true, "fixTime"), + new Limit(1))); } - public Collection getLatestPositions() throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectLatestPositions")) - .executeQuery(Position.class); + public void updateLatestPosition(Position position) throws StorageException { + Device device = new Device(); + device.setId(position.getDeviceId()); + device.setPositionId(position.getId()); + storage.updateObject(device, new Request( + new Columns.Include("positionId"), + new Condition.Equals("id", "id"))); + } + + public Collection getLatestPositions() throws StorageException { + List positions = new LinkedList<>(); + List devices = storage.getObjects(Device.class, new Request(new Columns.Include("positionId"))); + for (Device device : devices) { + positions.addAll(storage.getObjects(Position.class, new Request( + new Columns.All(), + new Condition.Equals("id", "id", device.getPositionId())))); + } + return positions; } - public Server getServer() throws SQLException { - return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, Server.class)) - .executeQuerySingle(Server.class); + public Server getServer() throws StorageException { + return storage.getObject(Server.class, new Request(new Columns.All())); } - public Collection getEvents(long deviceId, Date from, Date to) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectEvents")) - .setLong("deviceId", deviceId) - .setDate("from", from) - .setDate("to", to) - .executeQuery(Event.class); + public Collection getEvents(long deviceId, Date from, Date to) throws StorageException { + return storage.getObjects(Event.class, new Request( + new Columns.All(), + new Condition.And( + new Condition.Equals("deviceId", "deviceId", deviceId), + new Condition.Between("eventTime", "from", from, "to", to)), + new Order("eventTime"))); } - public Collection getStatistics(Date from, Date to) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectStatistics")) - .setDate("from", from) - .setDate("to", to) - .executeQuery(Statistics.class); + public Collection getStatistics(Date from, Date to) throws StorageException { + return storage.getObjects(Statistics.class, new Request( + new Columns.All(), + new Condition.Between("captureTime", "from", from, "to", to), + new Order("captureTime"))); } public static Class getClassByName(String name) throws ClassNotFoundException { @@ -400,7 +343,7 @@ public class DataManager { case "notification": return Notification.class; case "order": - return Order.class; + return org.traccar.model.Order.class; default: throw new ClassNotFoundException(); } @@ -412,51 +355,49 @@ public class DataManager { } public Collection getPermissions(Class owner, Class property) - throws SQLException, ClassNotFoundException { - return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property)) - .executePermissionsQuery(); + throws StorageException, ClassNotFoundException { + try { + return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, owner, property)) + .executePermissionsQuery(); + } catch (SQLException e) { + throw new StorageException(e); + } } public void linkObject(Class owner, long ownerId, Class property, long propertyId, boolean link) - throws SQLException { + throws StorageException { + try { QueryBuilder.create(dataSource, getQuery(link ? ACTION_INSERT : ACTION_DELETE, owner, property)) .setLong(makeNameId(owner), ownerId) .setLong(makeNameId(property), propertyId) .executeUpdate(); + } catch (SQLException e) { + throw new StorageException(e); + } } - public T getObject(Class clazz, long entityId) throws SQLException { - return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT, clazz)) - .setLong("id", entityId) - .executeQuerySingle(clazz); + public T getObject(Class clazz, long entityId) throws StorageException { + return storage.getObject(clazz, new Request( + new Columns.All(), + new Condition.Equals("id", "id", entityId))); } - public Collection getObjects(Class clazz) throws SQLException { - return QueryBuilder.create(dataSource, getQuery(ACTION_SELECT_ALL, clazz)) - .executeQuery(clazz); + public Collection getObjects(Class clazz) throws StorageException { + return storage.getObjects(clazz, new Request(new Columns.All())); } - public void addObject(BaseModel entity) throws SQLException { - entity.setId(QueryBuilder.create(dataSource, getQuery(ACTION_INSERT, entity.getClass()), true) - .setObject(entity) - .executeUpdate()); + public void addObject(BaseModel entity) throws StorageException { + entity.setId(storage.addObject(entity, new Request(new Columns.Exclude("id")))); } - public void updateObject(BaseModel entity) throws SQLException { - 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 updateObject(BaseModel entity) throws StorageException { + storage.updateObject(entity, new Request( + new Columns.Exclude("id"), + new Condition.Equals("id", "id"))); } - public void removeObject(Class clazz, long entityId) throws SQLException { - QueryBuilder.create(dataSource, getQuery(ACTION_DELETE, clazz)) - .setLong("id", entityId) - .executeUpdate(); + public void removeObject(Class clazz, long entityId) throws StorageException { + storage.removeObject(clazz, new Request(new Condition.Equals("id", "id", entityId))); } } diff --git a/src/main/java/org/traccar/database/DeviceManager.java b/src/main/java/org/traccar/database/DeviceManager.java index c8a99274c..40591e869 100644 --- a/src/main/java/org/traccar/database/DeviceManager.java +++ b/src/main/java/org/traccar/database/DeviceManager.java @@ -37,6 +37,7 @@ import org.traccar.model.DeviceAccumulators; import org.traccar.model.Group; import org.traccar.model.Position; import org.traccar.model.Server; +import org.traccar.storage.StorageException; public class DeviceManager extends BaseObjectManager implements IdentityManager, ManagableObjects { @@ -94,13 +95,13 @@ public class DeviceManager extends BaseObjectManager implements Identity } return device.getId(); - } catch (SQLException e) { + } catch (StorageException e) { LOGGER.warn("Automatic device registration error", e); return 0; } } - public void updateDeviceCache(boolean force) throws SQLException { + public void updateDeviceCache(boolean force) { long lastUpdate = devicesLastUpdate.get(); if ((force || System.currentTimeMillis() - lastUpdate > dataRefreshDelay) && devicesLastUpdate.compareAndSet(lastUpdate, System.currentTimeMillis())) { @@ -144,24 +145,11 @@ public class DeviceManager extends BaseObjectManager implements Identity return defaultPassword; } - public Device getDeviceByPhone(String phone) { - try { - readLock(); - return devicesByPhone.get(phone); - } finally { - readUnlock(); - } - } - @Override public Set getAllItems() { Set result = super.getAllItems(); if (result.isEmpty()) { - try { - updateDeviceCache(true); - } catch (SQLException e) { - LOGGER.warn("Update device cache error", e); - } + updateDeviceCache(true); result = super.getAllItems(); } return result; @@ -309,7 +297,7 @@ public class DeviceManager extends BaseObjectManager implements Identity positions.remove(deviceId); } - public void updateDeviceStatus(Device device) throws SQLException { + public void updateDeviceStatus(Device device) throws StorageException { getDataManager().updateDeviceStatus(device); Device cachedDevice = getById(device.getId()); if (cachedDevice != null) { @@ -323,7 +311,7 @@ public class DeviceManager extends BaseObjectManager implements Identity for (Position position : getDataManager().getLatestPositions()) { positions.put(position.getDeviceId(), position); } - } catch (SQLException error) { + } catch (StorageException error) { LOGGER.warn("Load latest positions error", error); } } @@ -334,7 +322,7 @@ public class DeviceManager extends BaseObjectManager implements Identity return lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) >= 0; } - public void updateLatestPosition(Position position) throws SQLException { + public void updateLatestPosition(Position position) throws StorageException { if (isLatestPosition(position)) { @@ -451,7 +439,7 @@ public class DeviceManager extends BaseObjectManager implements Identity return result; } - public void resetDeviceAccumulators(DeviceAccumulators deviceAccumulators) throws SQLException { + public void resetDeviceAccumulators(DeviceAccumulators deviceAccumulators) throws StorageException { Position last = positions.get(deviceAccumulators.getDeviceId()); if (last != null) { if (deviceAccumulators.getTotalDistance() != null) { diff --git a/src/main/java/org/traccar/database/ExtendedObjectManager.java b/src/main/java/org/traccar/database/ExtendedObjectManager.java index 93e5820fb..006ed47b2 100644 --- a/src/main/java/org/traccar/database/ExtendedObjectManager.java +++ b/src/main/java/org/traccar/database/ExtendedObjectManager.java @@ -16,7 +16,6 @@ */ package org.traccar.database; -import java.sql.SQLException; import java.util.Collection; import java.util.HashSet; import java.util.Map; @@ -30,6 +29,7 @@ import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.model.Permission; import org.traccar.model.BaseModel; +import org.traccar.storage.StorageException; public abstract class ExtendedObjectManager extends SimpleObjectManager { @@ -87,7 +87,7 @@ public abstract class ExtendedObjectManager extends SimpleO } @Override - public void removeItem(long itemId) throws SQLException { + public void removeItem(long itemId) throws StorageException { super.removeItem(itemId); refreshExtendedPermissions(); } @@ -133,7 +133,7 @@ public abstract class ExtendedObjectManager extends SimpleO } } - } catch (SQLException | ClassNotFoundException error) { + } catch (StorageException | ClassNotFoundException error) { LOGGER.warn("Refresh permissions error", error); } finally { writeUnlock(); diff --git a/src/main/java/org/traccar/database/GroupsManager.java b/src/main/java/org/traccar/database/GroupsManager.java index c35f35f93..dafddc0cc 100644 --- a/src/main/java/org/traccar/database/GroupsManager.java +++ b/src/main/java/org/traccar/database/GroupsManager.java @@ -16,12 +16,12 @@ */ package org.traccar.database; -import java.sql.SQLException; import java.util.HashSet; import java.util.Set; import org.traccar.Context; import org.traccar.model.Group; +import org.traccar.storage.StorageException; public class GroupsManager extends BaseObjectManager implements ManagableObjects { @@ -57,7 +57,7 @@ public class GroupsManager extends BaseObjectManager implements Managable } @Override - public void updateItem(Group group) throws SQLException { + public void updateItem(Group group) throws StorageException { checkGroupCycles(group); super.updateItem(group); } diff --git a/src/main/java/org/traccar/database/NotificationManager.java b/src/main/java/org/traccar/database/NotificationManager.java index 9f9a83cd2..f358b1d4d 100644 --- a/src/main/java/org/traccar/database/NotificationManager.java +++ b/src/main/java/org/traccar/database/NotificationManager.java @@ -18,7 +18,6 @@ package org.traccar.database; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.sql.SQLException; import java.util.Arrays; import java.util.Date; import java.util.HashSet; @@ -36,6 +35,7 @@ import org.traccar.model.Event; import org.traccar.model.Notification; import org.traccar.model.Position; import org.traccar.model.Typed; +import org.traccar.storage.StorageException; public class NotificationManager extends ExtendedObjectManager { @@ -66,7 +66,7 @@ public class NotificationManager extends ExtendedObjectManager { public void updateEvent(Event event, Position position) { try { getDataManager().addObject(event); - } catch (SQLException error) { + } catch (StorageException error) { LOGGER.warn("Event save error", error); } diff --git a/src/main/java/org/traccar/database/PermissionsManager.java b/src/main/java/org/traccar/database/PermissionsManager.java index ab841a521..2bb808033 100644 --- a/src/main/java/org/traccar/database/PermissionsManager.java +++ b/src/main/java/org/traccar/database/PermissionsManager.java @@ -33,8 +33,8 @@ import org.traccar.model.Order; import org.traccar.model.Permission; import org.traccar.model.Server; import org.traccar.model.User; +import org.traccar.storage.StorageException; -import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -156,7 +156,7 @@ public class PermissionsManager { public void refreshServer() { try { server = dataManager.getServer(); - } catch (SQLException error) { + } catch (StorageException error) { LOGGER.warn("Refresh server config error", error); } } @@ -193,7 +193,7 @@ public class PermissionsManager { } } - } catch (SQLException | ClassNotFoundException error) { + } catch (StorageException | ClassNotFoundException error) { LOGGER.warn("Refresh device permissions error", error); } @@ -499,12 +499,12 @@ public class PermissionsManager { return server; } - public void updateServer(Server server) throws SQLException { + public void updateServer(Server server) throws StorageException { dataManager.updateObject(server); this.server = server; } - public User login(String email, String password) throws SQLException { + public User login(String email, String password) throws StorageException { User user = dataManager.login(email, password); if (user != null) { checkUserEnabled(user.getId()); diff --git a/src/main/java/org/traccar/database/SimpleObjectManager.java b/src/main/java/org/traccar/database/SimpleObjectManager.java index eb8284d4e..78701720f 100644 --- a/src/main/java/org/traccar/database/SimpleObjectManager.java +++ b/src/main/java/org/traccar/database/SimpleObjectManager.java @@ -16,7 +16,6 @@ */ package org.traccar.database; -import java.sql.SQLException; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -28,6 +27,7 @@ import org.traccar.Context; import org.traccar.model.BaseModel; import org.traccar.model.Permission; import org.traccar.model.User; +import org.traccar.storage.StorageException; public abstract class SimpleObjectManager extends BaseObjectManager implements ManagableObjects { @@ -83,7 +83,7 @@ public abstract class SimpleObjectManager extends BaseObjec Set items = userItems.computeIfAbsent(permission.getOwnerId(), key -> new HashSet<>()); items.add(permission.getPropertyId()); } - } catch (SQLException | ClassNotFoundException error) { + } catch (StorageException | ClassNotFoundException error) { LOGGER.warn("Error getting permissions", error); } finally { writeUnlock(); @@ -92,7 +92,7 @@ public abstract class SimpleObjectManager extends BaseObjec } @Override - public void removeItem(long itemId) throws SQLException { + public void removeItem(long itemId) throws StorageException { super.removeItem(itemId); refreshUserItems(); } diff --git a/src/main/java/org/traccar/database/StatisticsManager.java b/src/main/java/org/traccar/database/StatisticsManager.java index 4ad6d9d5c..3579ce7a5 100644 --- a/src/main/java/org/traccar/database/StatisticsManager.java +++ b/src/main/java/org/traccar/database/StatisticsManager.java @@ -23,12 +23,12 @@ import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.helper.DateUtil; import org.traccar.model.Statistics; +import org.traccar.storage.StorageException; import javax.inject.Inject; import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Form; -import java.sql.SQLException; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -106,7 +106,7 @@ public class StatisticsManager { try { dataManager.addObject(statistics); - } catch (SQLException e) { + } catch (StorageException e) { LOGGER.warn("Error saving statistics", e); } diff --git a/src/main/java/org/traccar/database/UsersManager.java b/src/main/java/org/traccar/database/UsersManager.java index b741a85b6..31759dc8b 100644 --- a/src/main/java/org/traccar/database/UsersManager.java +++ b/src/main/java/org/traccar/database/UsersManager.java @@ -21,6 +21,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.traccar.model.User; +import org.traccar.storage.StorageException; public class UsersManager extends SimpleObjectManager { @@ -58,6 +59,14 @@ public class UsersManager extends SimpleObjectManager { } } + @Override + public void updateItem(User user) throws StorageException { + if (user.getHashedPassword() != null) { + getDataManager().updateUserPassword(user); + } + super.updateItem(user); + } + @Override protected void removeCachedItem(long userId) { User cachedUser = getById(userId); diff --git a/src/main/java/org/traccar/handler/FilterHandler.java b/src/main/java/org/traccar/handler/FilterHandler.java index 2b850c755..e576a26b8 100644 --- a/src/main/java/org/traccar/handler/FilterHandler.java +++ b/src/main/java/org/traccar/handler/FilterHandler.java @@ -24,8 +24,8 @@ import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; +import org.traccar.storage.StorageException; -import java.sql.SQLException; import java.util.Date; @ChannelHandler.Sharable @@ -174,7 +174,7 @@ public class FilterHandler extends BaseDataHandler { try { Date newFixTime = position.getFixTime(); preceding = Context.getDataManager().getPrecedingPosition(deviceId, newFixTime); - } catch (SQLException e) { + } catch (StorageException e) { LOGGER.warn("Error retrieving preceding position; fallbacking to last received position.", e); preceding = getLastReceivedPosition(deviceId); } diff --git a/src/main/java/org/traccar/model/Attribute.java b/src/main/java/org/traccar/model/Attribute.java index 45d40b3ec..65f2e3881 100644 --- a/src/main/java/org/traccar/model/Attribute.java +++ b/src/main/java/org/traccar/model/Attribute.java @@ -16,6 +16,9 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + +@StorageName("tc_attributes") public class Attribute extends BaseModel { private String description; diff --git a/src/main/java/org/traccar/model/Calendar.java b/src/main/java/org/traccar/model/Calendar.java index af6364626..102c0be52 100644 --- a/src/main/java/org/traccar/model/Calendar.java +++ b/src/main/java/org/traccar/model/Calendar.java @@ -25,6 +25,7 @@ import net.fortuna.ical4j.model.DateTime; import net.fortuna.ical4j.model.Period; import net.fortuna.ical4j.model.component.CalendarComponent; import org.traccar.storage.QueryIgnore; +import org.traccar.storage.StorageName; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -32,6 +33,7 @@ import java.time.Duration; import java.util.Collection; import java.util.Date; +@StorageName("tc_calendars") public class Calendar extends ExtendedModel { private String name; diff --git a/src/main/java/org/traccar/model/Command.java b/src/main/java/org/traccar/model/Command.java index 71bc232e9..03961c7b2 100644 --- a/src/main/java/org/traccar/model/Command.java +++ b/src/main/java/org/traccar/model/Command.java @@ -18,7 +18,9 @@ package org.traccar.model; import org.traccar.storage.QueryIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import org.traccar.storage.StorageName; +@StorageName("tc_commands") @JsonIgnoreProperties(ignoreUnknown = true) public class Command extends Message implements Cloneable { @@ -104,6 +106,12 @@ public class Command extends Message implements Cloneable { return super.getDeviceId(); } + @QueryIgnore + @Override + public void setDeviceId(long deviceId) { + super.setDeviceId(deviceId); + } + private String description; public String getDescription() { diff --git a/src/main/java/org/traccar/model/Device.java b/src/main/java/org/traccar/model/Device.java index 46de8003d..836a6709c 100644 --- a/src/main/java/org/traccar/model/Device.java +++ b/src/main/java/org/traccar/model/Device.java @@ -20,7 +20,9 @@ import java.util.List; import org.traccar.storage.QueryExtended; import org.traccar.storage.QueryIgnore; +import org.traccar.storage.StorageName; +@StorageName("tc_devices") public class Device extends GroupedModel { private String name; @@ -54,13 +56,13 @@ public class Device extends GroupedModel { return status != null ? status : STATUS_OFFLINE; } + @QueryIgnore public void setStatus(String status) { this.status = status; } private Date lastUpdate; - @QueryExtended public Date getLastUpdate() { if (lastUpdate != null) { return new Date(lastUpdate.getTime()); @@ -69,6 +71,7 @@ public class Device extends GroupedModel { } } + @QueryExtended public void setLastUpdate(Date lastUpdate) { if (lastUpdate != null) { this.lastUpdate = new Date(lastUpdate.getTime()); @@ -84,6 +87,7 @@ public class Device extends GroupedModel { return positionId; } + @QueryIgnore public void setPositionId(long positionId) { this.positionId = positionId; } @@ -95,6 +99,7 @@ public class Device extends GroupedModel { return geofenceIds; } + @QueryIgnore public void setGeofenceIds(List geofenceIds) { this.geofenceIds = geofenceIds; } diff --git a/src/main/java/org/traccar/model/Driver.java b/src/main/java/org/traccar/model/Driver.java index 05f52fd4d..b9e023088 100644 --- a/src/main/java/org/traccar/model/Driver.java +++ b/src/main/java/org/traccar/model/Driver.java @@ -16,6 +16,9 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + +@StorageName("tc_drivers") public class Driver extends ExtendedModel { private String name; @@ -37,4 +40,5 @@ public class Driver extends ExtendedModel { public void setUniqueId(String uniqueId) { this.uniqueId = uniqueId; } + } diff --git a/src/main/java/org/traccar/model/Event.java b/src/main/java/org/traccar/model/Event.java index a7a134ecf..6e3953fda 100644 --- a/src/main/java/org/traccar/model/Event.java +++ b/src/main/java/org/traccar/model/Event.java @@ -15,8 +15,11 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + import java.util.Date; +@StorageName("tc_events") public class Event extends Message { public Event(String type, Position position) { diff --git a/src/main/java/org/traccar/model/Geofence.java b/src/main/java/org/traccar/model/Geofence.java index a451da9f5..5b857580d 100644 --- a/src/main/java/org/traccar/model/Geofence.java +++ b/src/main/java/org/traccar/model/Geofence.java @@ -26,7 +26,9 @@ import org.traccar.geofence.GeofencePolygon; import org.traccar.geofence.GeofencePolyline; import com.fasterxml.jackson.annotation.JsonIgnore; +import org.traccar.storage.StorageName; +@StorageName("tc_geofences") public class Geofence extends ScheduledModel { public static final String TYPE_GEOFENCE_CILCLE = "geofenceCircle"; diff --git a/src/main/java/org/traccar/model/Group.java b/src/main/java/org/traccar/model/Group.java index 91ea2319d..ff69f61fa 100644 --- a/src/main/java/org/traccar/model/Group.java +++ b/src/main/java/org/traccar/model/Group.java @@ -15,6 +15,9 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + +@StorageName("tc_groups") public class Group extends GroupedModel { private String name; diff --git a/src/main/java/org/traccar/model/Maintenance.java b/src/main/java/org/traccar/model/Maintenance.java index 73f67ea96..cad100a3a 100644 --- a/src/main/java/org/traccar/model/Maintenance.java +++ b/src/main/java/org/traccar/model/Maintenance.java @@ -16,6 +16,9 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + +@StorageName("tc_maintenances") public class Maintenance extends ExtendedModel { private String name; diff --git a/src/main/java/org/traccar/model/Notification.java b/src/main/java/org/traccar/model/Notification.java index 01ca2711c..95e446132 100644 --- a/src/main/java/org/traccar/model/Notification.java +++ b/src/main/java/org/traccar/model/Notification.java @@ -21,7 +21,9 @@ import java.util.Set; import org.traccar.storage.QueryIgnore; import com.fasterxml.jackson.annotation.JsonIgnore; +import org.traccar.storage.StorageName; +@StorageName("tc_notifications") public class Notification extends ScheduledModel { private boolean always; @@ -44,7 +46,6 @@ public class Notification extends ScheduledModel { this.type = type; } - private String notificators; public String getNotificators() { @@ -55,7 +56,6 @@ public class Notification extends ScheduledModel { this.notificators = transports; } - @JsonIgnore @QueryIgnore public Set getNotificatorsTypes() { diff --git a/src/main/java/org/traccar/model/Order.java b/src/main/java/org/traccar/model/Order.java index fe6d926b8..7d09b0a47 100644 --- a/src/main/java/org/traccar/model/Order.java +++ b/src/main/java/org/traccar/model/Order.java @@ -15,6 +15,9 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + +@StorageName("tc_orders") public class Order extends ExtendedModel { private String uniqueId; diff --git a/src/main/java/org/traccar/model/Position.java b/src/main/java/org/traccar/model/Position.java index bbea58901..348370e2c 100644 --- a/src/main/java/org/traccar/model/Position.java +++ b/src/main/java/org/traccar/model/Position.java @@ -17,8 +17,11 @@ package org.traccar.model; import java.util.Date; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.traccar.storage.QueryIgnore; +import org.traccar.storage.StorageName; +@StorageName("tc_positions") public class Position extends Message { public static final String KEY_ORIGINAL = "raw"; @@ -190,6 +193,7 @@ public class Position extends Message { this.fixTime = fixTime; } + @QueryIgnore public void setTime(Date time) { setDeviceTime(time); setFixTime(time); @@ -202,6 +206,7 @@ public class Position extends Message { return outdated; } + @QueryIgnore public void setOutdated(boolean outdated) { this.outdated = outdated; } @@ -296,10 +301,18 @@ public class Position extends Message { this.network = network; } - @Override + @JsonIgnore @QueryIgnore + @Override public String getType() { return super.getType(); } + @JsonIgnore + @QueryIgnore + @Override + public void setType(String type) { + super.setType(type); + } + } diff --git a/src/main/java/org/traccar/model/Server.java b/src/main/java/org/traccar/model/Server.java index fdb071a18..b48e84939 100644 --- a/src/main/java/org/traccar/model/Server.java +++ b/src/main/java/org/traccar/model/Server.java @@ -18,7 +18,9 @@ package org.traccar.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.traccar.Context; import org.traccar.storage.QueryIgnore; +import org.traccar.storage.StorageName; +@StorageName("tc_servers") @JsonIgnoreProperties(ignoreUnknown = true) public class Server extends ExtendedModel { diff --git a/src/main/java/org/traccar/model/Statistics.java b/src/main/java/org/traccar/model/Statistics.java index a9a117aef..0dc1b98e8 100644 --- a/src/main/java/org/traccar/model/Statistics.java +++ b/src/main/java/org/traccar/model/Statistics.java @@ -15,9 +15,12 @@ */ package org.traccar.model; +import org.traccar.storage.StorageName; + import java.util.Date; import java.util.Map; +@StorageName("tc_statistics") public class Statistics extends ExtendedModel { private Date captureTime; diff --git a/src/main/java/org/traccar/model/User.java b/src/main/java/org/traccar/model/User.java index 447cf691c..94828ab95 100644 --- a/src/main/java/org/traccar/model/User.java +++ b/src/main/java/org/traccar/model/User.java @@ -20,9 +20,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import org.traccar.storage.QueryExtended; import org.traccar.storage.QueryIgnore; import org.traccar.helper.Hashing; +import org.traccar.storage.StorageName; import java.util.Date; +@StorageName("tc_users") public class User extends ExtendedModel { private String name; diff --git a/src/main/java/org/traccar/reports/Events.java b/src/main/java/org/traccar/reports/Events.java index 66d9e708d..e4b905702 100644 --- a/src/main/java/org/traccar/reports/Events.java +++ b/src/main/java/org/traccar/reports/Events.java @@ -20,7 +20,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -35,6 +34,7 @@ import org.traccar.model.Geofence; import org.traccar.model.Group; import org.traccar.model.Maintenance; import org.traccar.reports.model.DeviceReport; +import org.traccar.storage.StorageException; public final class Events { @@ -42,7 +42,7 @@ public final class Events { } public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, - Collection types, Date from, Date to) throws SQLException { + Collection types, Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { @@ -66,7 +66,7 @@ public final class Events { public static void getExcel(OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, - Collection types, Date from, Date to) throws SQLException, IOException { + Collection types, Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); ArrayList devicesEvents = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); diff --git a/src/main/java/org/traccar/reports/Route.java b/src/main/java/org/traccar/reports/Route.java index 6adb00aae..4a5edd295 100644 --- a/src/main/java/org/traccar/reports/Route.java +++ b/src/main/java/org/traccar/reports/Route.java @@ -20,7 +20,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -31,6 +30,7 @@ import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.model.Position; import org.traccar.reports.model.DeviceReport; +import org.traccar.storage.StorageException; public final class Route { @@ -38,7 +38,7 @@ public final class Route { } public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws SQLException { + Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { @@ -50,7 +50,7 @@ public final class Route { public static void getExcel(OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws SQLException, IOException { + Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); ArrayList devicesRoutes = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); diff --git a/src/main/java/org/traccar/reports/Stops.java b/src/main/java/org/traccar/reports/Stops.java index 2036b0641..36a4a7549 100644 --- a/src/main/java/org/traccar/reports/Stops.java +++ b/src/main/java/org/traccar/reports/Stops.java @@ -21,7 +21,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -35,13 +34,14 @@ import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.reports.model.DeviceReport; import org.traccar.reports.model.StopReport; +import org.traccar.storage.StorageException; public final class Stops { private Stops() { } - private static Collection detectStops(long deviceId, Date from, Date to) throws SQLException { + private static Collection detectStops(long deviceId, Date from, Date to) throws StorageException { boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); @@ -55,7 +55,7 @@ public final class Stops { public static Collection getObjects( long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws SQLException { + Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { @@ -67,7 +67,7 @@ public final class Stops { public static void getExcel( OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws SQLException, IOException { + Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); ArrayList devicesStops = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); diff --git a/src/main/java/org/traccar/reports/Summary.java b/src/main/java/org/traccar/reports/Summary.java index d576ac1e6..4924af062 100644 --- a/src/main/java/org/traccar/reports/Summary.java +++ b/src/main/java/org/traccar/reports/Summary.java @@ -20,7 +20,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -31,6 +30,7 @@ import org.traccar.Context; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; import org.traccar.reports.model.SummaryReport; +import org.traccar.storage.StorageException; public final class Summary { @@ -97,7 +97,7 @@ public final class Summary { } private static Collection calculateSummaryResults( - long userId, long deviceId, Date from, Date to, boolean daily) throws SQLException { + long userId, long deviceId, Date from, Date to, boolean daily) throws StorageException { ArrayList positions = new ArrayList<>(Context.getDataManager().getPositions(deviceId, from, to)); @@ -122,7 +122,7 @@ public final class Summary { } public static Collection getObjects(long userId, Collection deviceIds, - Collection groupIds, Date from, Date to, boolean daily) throws SQLException { + Collection groupIds, Date from, Date to, boolean daily) throws StorageException { ReportUtils.checkPeriodLimit(from, to); ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { @@ -134,7 +134,7 @@ public final class Summary { public static void getExcel(OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, - Date from, Date to, boolean daily) throws SQLException, IOException { + Date from, Date to, boolean daily) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); Collection summaries = getObjects(userId, deviceIds, groupIds, from, to, daily); String templatePath = Context.getConfig().getString("report.templatesPath", diff --git a/src/main/java/org/traccar/reports/Trips.java b/src/main/java/org/traccar/reports/Trips.java index 7c0cd6921..1461b869e 100644 --- a/src/main/java/org/traccar/reports/Trips.java +++ b/src/main/java/org/traccar/reports/Trips.java @@ -20,7 +20,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; @@ -34,13 +33,14 @@ import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.reports.model.DeviceReport; import org.traccar.reports.model.TripReport; +import org.traccar.storage.StorageException; public final class Trips { private Trips() { } - private static Collection detectTrips(long deviceId, Date from, Date to) throws SQLException { + private static Collection detectTrips(long deviceId, Date from, Date to) throws StorageException { boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); @@ -53,7 +53,7 @@ public final class Trips { } public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws SQLException { + Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { @@ -65,7 +65,7 @@ public final class Trips { public static void getExcel(OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws SQLException, IOException { + Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); ArrayList devicesTrips = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java index 0bcab7d20..2c893ebbc 100644 --- a/src/main/java/org/traccar/storage/DatabaseStorage.java +++ b/src/main/java/org/traccar/storage/DatabaseStorage.java @@ -2,6 +2,7 @@ package org.traccar.storage; import org.traccar.storage.query.Columns; import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Limit; import org.traccar.storage.query.Order; import org.traccar.storage.query.Request; @@ -24,7 +25,7 @@ public class DatabaseStorage extends Storage { @Override public List getObjects(Class clazz, Request request) throws StorageException { StringBuilder query = new StringBuilder("SELECT "); - query.append(formatColumns(request.getColumns(), clazz, c -> c)); + query.append(formatColumns(request.getColumns(), clazz, "get", c -> c)); query.append(" FROM ").append(getTableName(clazz)); query.append(formatCondition(request.getCondition())); query.append(formatOrder(request.getOrder())); @@ -44,9 +45,9 @@ public class DatabaseStorage extends Storage { StringBuilder query = new StringBuilder("INSERT INTO "); query.append(getTableName(entity.getClass())); query.append("("); - query.append(formatColumns(request.getColumns(), entity.getClass(), c -> c)); + query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c)); query.append(") VALUES ("); - query.append(formatColumns(request.getColumns(), entity.getClass(), c -> ':' + c)); + query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> ':' + c)); query.append(")"); try { QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true); @@ -62,7 +63,7 @@ public class DatabaseStorage extends Storage { StringBuilder query = new StringBuilder("UPDATE "); query.append(getTableName(entity.getClass())); query.append(" SET "); - query.append(formatColumns(request.getColumns(), entity.getClass(), c -> c + " = :" + c)); + query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c + " = :" + c)); query.append(formatCondition(request.getCondition())); try { QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); @@ -101,31 +102,46 @@ public class DatabaseStorage extends Storage { } private Map getConditionVariables(Condition genericCondition) { - Map result = new HashMap<>(); - if (genericCondition instanceof Condition.Equals) { - Condition.Equals condition = (Condition.Equals) genericCondition; - result.put(condition.getVariable(), condition.getValue()); + Map results = new HashMap<>(); + if (genericCondition instanceof Condition.Compare) { + Condition.Compare condition = (Condition.Compare) genericCondition; + if (condition.getValue() != null) { + results.put(condition.getVariable(), condition.getValue()); + } } else if (genericCondition instanceof Condition.Between) { Condition.Between condition = (Condition.Between) genericCondition; - result.put(condition.getFromVariable(), condition.getFromValue()); - result.put(condition.getToVariable(), condition.getToValue()); + results.put(condition.getFromVariable(), condition.getFromValue()); + results.put(condition.getToVariable(), condition.getToValue()); + } else if (genericCondition instanceof Condition.Binary) { + Condition.Binary condition = (Condition.Binary) genericCondition; + results.putAll(getConditionVariables(condition.getFirst())); + results.putAll(getConditionVariables(condition.getSecond())); } - return result; + return results; } - private String formatColumns(Columns columns, Class clazz, Function mapper) { - return columns.getColumns(clazz).stream().map(mapper).collect(Collectors.joining(", ")); + private String formatColumns( + Columns columns, Class clazz, String type, Function mapper) { + return columns.getColumns(clazz, type).stream().map(mapper).collect(Collectors.joining(", ")); } private String formatCondition(Condition genericCondition) { + return formatCondition(genericCondition, true); + } + + private String formatCondition(Condition genericCondition, boolean appendWhere) { StringBuilder result = new StringBuilder(); if (genericCondition != null) { - result.append(" WHERE "); - if (genericCondition instanceof Condition.Equals) { + if (appendWhere) { + result.append(" WHERE "); + } + if (genericCondition instanceof Condition.Compare) { - Condition.Equals condition = (Condition.Equals) genericCondition; + Condition.Compare condition = (Condition.Compare) genericCondition; result.append(condition.getColumn()); - result.append(" == :"); + result.append(" "); + result.append(condition.getOperator()); + result.append(" :"); result.append(condition.getVariable()); } else if (genericCondition instanceof Condition.Between) { @@ -137,12 +153,14 @@ public class DatabaseStorage extends Storage { result.append(" AND :"); result.append(condition.getToVariable()); - } else if (genericCondition instanceof Condition.And) { + } else if (genericCondition instanceof Condition.Binary) { - Condition.And condition = (Condition.And) genericCondition; - result.append(formatCondition(condition.getFirst())); - result.append(" AND "); - result.append(formatCondition(condition.getSecond())); + Condition.Binary condition = (Condition.Binary) genericCondition; + result.append(formatCondition(condition.getFirst(), false)); + result.append(" "); + result.append(condition.getOperator()); + result.append(" "); + result.append(formatCondition(condition.getSecond(), false)); } } @@ -161,4 +179,13 @@ public class DatabaseStorage extends Storage { return result.toString(); } + private String formatLimit(Limit limit) { + StringBuilder result = new StringBuilder(); + if (limit != null) { + result.append(" LIMIT "); + result.append(limit.getValue()); + } + return result.toString(); + } + } diff --git a/src/main/java/org/traccar/storage/QueryBuilder.java b/src/main/java/org/traccar/storage/QueryBuilder.java index 838472c8b..edaacb74d 100644 --- a/src/main/java/org/traccar/storage/QueryBuilder.java +++ b/src/main/java/org/traccar/storage/QueryBuilder.java @@ -276,8 +276,7 @@ public final class QueryBuilder { Method[] methods = object.getClass().getMethods(); for (Method method : methods) { - if (method.getName().startsWith("get") && method.getParameterTypes().length == 0 - && !method.isAnnotationPresent(QueryIgnore.class)) { + if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { String name = method.getName().substring(3); try { if (method.getReturnType().equals(boolean.class)) { @@ -412,8 +411,7 @@ public final class QueryBuilder { Method[] methods = clazz.getMethods(); for (final Method method : methods) { - if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 - && !method.isAnnotationPresent(QueryIgnore.class)) { + if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) { final String name = method.getName().substring(3); diff --git a/src/main/java/org/traccar/storage/Storage.java b/src/main/java/org/traccar/storage/Storage.java index b95ce9505..3726fbf50 100644 --- a/src/main/java/org/traccar/storage/Storage.java +++ b/src/main/java/org/traccar/storage/Storage.java @@ -6,20 +6,17 @@ import java.util.List; public abstract class Storage { - abstract List getObjects(Class clazz, Request request) throws StorageException; + public abstract List getObjects(Class clazz, Request request) throws StorageException; - abstract long addObject(T entity, Request request) throws StorageException; + public abstract long addObject(T entity, Request request) throws StorageException; - abstract void updateObject(T entity, Request request) throws StorageException; + public abstract void updateObject(T entity, Request request) throws StorageException; - abstract void removeObject(Class clazz, Request request) throws StorageException; + public abstract void removeObject(Class clazz, Request request) throws StorageException; - T getObject(Class clazz, Request request) throws StorageException { + public T getObject(Class clazz, Request request) throws StorageException { var objects = getObjects(clazz, request); - if (objects.isEmpty()) { - throw new StorageException("No objects found"); - } - return objects.get(0); + return objects.isEmpty() ? null : objects.get(0); } } diff --git a/src/main/java/org/traccar/storage/query/Columns.java b/src/main/java/org/traccar/storage/query/Columns.java index 1a13665ee..196d2281c 100644 --- a/src/main/java/org/traccar/storage/query/Columns.java +++ b/src/main/java/org/traccar/storage/query/Columns.java @@ -1,5 +1,6 @@ package org.traccar.storage.query; +import org.traccar.storage.QueryExtended; import org.traccar.storage.QueryIgnore; import java.lang.reflect.Method; @@ -11,14 +12,17 @@ import java.util.stream.Collectors; public abstract class Columns { - public abstract List getColumns(Class clazz); + public abstract List getColumns(Class clazz, String type); - protected List getAllColumns(Class clazz) { + protected List getAllColumns(Class clazz, String type) { List columns = new LinkedList<>(); Method[] methods = clazz.getMethods(); for (Method method : methods) { - if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 - && !method.isAnnotationPresent(QueryIgnore.class)) { + int parameterCount = type.equals("set") ? 1 : 0; + if (method.getName().startsWith(type) && method.getParameterTypes().length == parameterCount + && !method.isAnnotationPresent(QueryIgnore.class) + && !method.isAnnotationPresent(QueryExtended.class) + && !method.getName().equals("getClass")) { columns.add(method.getName().substring(3).toLowerCase()); } } @@ -27,8 +31,8 @@ public abstract class Columns { public static class All extends Columns { @Override - public List getColumns(Class clazz) { - return getAllColumns(clazz); + public List getColumns(Class clazz, String type) { + return getAllColumns(clazz, type); } } @@ -40,7 +44,7 @@ public abstract class Columns { } @Override - public List getColumns(Class clazz) { + public List getColumns(Class clazz, String type) { return columns; } } @@ -53,8 +57,8 @@ public abstract class Columns { } @Override - public List getColumns(Class clazz) { - return getAllColumns(clazz).stream() + public List getColumns(Class clazz, String type) { + return getAllColumns(clazz, type).stream() .filter(column -> !columns.contains(column)) .collect(Collectors.toList()); } diff --git a/src/main/java/org/traccar/storage/query/Condition.java b/src/main/java/org/traccar/storage/query/Condition.java index 50d520bc7..82c8e8479 100644 --- a/src/main/java/org/traccar/storage/query/Condition.java +++ b/src/main/java/org/traccar/storage/query/Condition.java @@ -2,13 +2,25 @@ package org.traccar.storage.query; public interface Condition { - class Equals implements Condition { + class Equals extends Compare { + public Equals(String column, String variable) { + this(column, variable, null); + } + + public Equals(String column, String variable, Object value) { + super(column, "=", variable, value); + } + } + + class Compare implements Condition { private final String column; + private final String operator; private final String variable; private final Object value; - public Equals(String column, String variable, Object value) { + public Compare(String column, String operator, String variable, Object value) { this.column = column; + this.operator = operator; this.variable = variable; this.value = value; } @@ -17,6 +29,10 @@ public interface Condition { return column; } + public String getOperator() { + return operator; + } + public String getVariable() { return variable; } @@ -62,13 +78,27 @@ public interface Condition { } } - class And implements Condition { + class Or extends Binary { + public Or(Condition first, Condition second) { + super(first, second, "OR"); + } + } + + class And extends Binary { + public And(Condition first, Condition second) { + super(first, second, "AND"); + } + } + + class Binary implements Condition { private final Condition first; private final Condition second; + private final String operator; - public And(Condition first, Condition second) { + public Binary(Condition first, Condition second, String operator) { this.first = first; this.second = second; + this.operator = operator; } public Condition getFirst() { @@ -78,6 +108,10 @@ public interface Condition { public Condition getSecond() { return second; } + + public String getOperator() { + return operator; + } } } diff --git a/src/main/java/org/traccar/storage/query/Limit.java b/src/main/java/org/traccar/storage/query/Limit.java new file mode 100644 index 000000000..4a20f0ce2 --- /dev/null +++ b/src/main/java/org/traccar/storage/query/Limit.java @@ -0,0 +1,15 @@ +package org.traccar.storage.query; + +public class Limit { + + private final int value; + + public Limit(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + +} diff --git a/src/main/java/org/traccar/storage/query/Request.java b/src/main/java/org/traccar/storage/query/Request.java index 8536cafd0..a98dd48f7 100644 --- a/src/main/java/org/traccar/storage/query/Request.java +++ b/src/main/java/org/traccar/storage/query/Request.java @@ -5,11 +5,29 @@ public class Request { private final Columns columns; private final Condition condition; private final Order order; + private final Limit limit; + + public Request(Columns columns) { + this(columns, null, null); + } + + public Request(Condition condition) { + this(null, condition, null); + } + + public Request(Columns columns, Condition condition) { + this(columns, condition, null); + } public Request(Columns columns, Condition condition, Order order) { + this(columns, condition, order, null); + } + + public Request(Columns columns, Condition condition, Order order, Limit limit) { this.columns = columns; this.condition = condition; this.order = order; + this.limit = limit; } public Columns getColumns() { @@ -24,4 +42,8 @@ public class Request { return order; } + public Limit getLimit() { + return limit; + } + } diff --git a/src/test/java/org/traccar/database/DataManagerTest.java b/src/test/java/org/traccar/database/DataManagerTest.java deleted file mode 100644 index 23043e96e..000000000 --- a/src/test/java/org/traccar/database/DataManagerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.traccar.database; - -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; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class DataManagerTest { - - @Test - public void constructObjectQuery() { - assertEquals("SELECT * FROM tc_users", - DataManager.constructObjectQuery(DataManager.ACTION_SELECT_ALL, User.class, false)); - assertEquals("DELETE FROM tc_groups WHERE id = :id", - DataManager.constructObjectQuery(DataManager.ACTION_DELETE, Group.class, false)); - assertEquals("SELECT * FROM tc_positions WHERE id = :id", - DataManager.constructObjectQuery(DataManager.ACTION_SELECT, Position.class, false)); - - String insertDevice = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Device.class, false); - assertFalse(insertDevice.contains("class")); - assertFalse(insertDevice.contains("id")); - assertFalse(insertDevice.contains("status")); - assertFalse(insertDevice.contains("geofenceIds")); - - String updateDeviceStatus = DataManager.constructObjectQuery("update", Device.class, true); - assertTrue(updateDeviceStatus.contains("lastUpdate")); - - String updateUser = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, false); - assertFalse(updateUser.contains("class")); - assertFalse(updateUser.contains("password")); - assertFalse(updateUser.contains("salt")); - - String updateUserPassword = DataManager.constructObjectQuery(DataManager.ACTION_UPDATE, User.class, true); - assertFalse(updateUserPassword.contains("name")); - assertTrue(updateUserPassword.contains("hashedPassword")); - assertTrue(updateUserPassword.contains("salt")); - - String insertPosition = DataManager.constructObjectQuery(DataManager.ACTION_INSERT, Position.class, false); - assertFalse(insertPosition.contains("type")); - assertFalse(insertPosition.contains("outdated")); - - } - - @Test - public void constructPermissionsQuery() { - assertEquals("SELECT userId, deviceId FROM tc_user_device", - DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, Device.class)); - - assertEquals("SELECT userId, managedUserId FROM tc_user_user", - DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, User.class, ManagedUser.class)); - - assertEquals("SELECT deviceId, driverId FROM tc_device_driver", - DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Device.class, Driver.class)); - - assertEquals("SELECT groupId, geofenceId FROM tc_group_geofence", - DataManager.constructPermissionQuery(DataManager.ACTION_SELECT_ALL, Group.class, Geofence.class)); - - assertEquals("INSERT INTO tc_user_device (userId, deviceId) VALUES (:userId, :deviceId)", - DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, User.class, Device.class)); - - assertEquals("DELETE FROM tc_user_user WHERE userId = :userId AND managedUserId = :managedUserId", - DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, User.class, ManagedUser.class)); - - assertEquals("INSERT INTO tc_device_geofence (deviceId, geofenceId) VALUES (:deviceId, :geofenceId)", - DataManager.constructPermissionQuery(DataManager.ACTION_INSERT, Device.class, Geofence.class)); - - assertEquals("DELETE FROM tc_group_attribute WHERE groupId = :groupId AND attributeId = :attributeId", - DataManager.constructPermissionQuery(DataManager.ACTION_DELETE, Group.class, Attribute.class)); - - } - -} -- cgit v1.2.3 From 9ec2d09ad8a757d58f70812b9cf5e835321382e6 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 21 Feb 2022 17:33:58 -0800 Subject: Migrate permissions to storage --- debug.xml | 1 + gradle/checkstyle.xml | 4 +- src/main/java/org/traccar/MainModule.java | 5 - .../java/org/traccar/api/BaseObjectResource.java | 105 ++++------------ src/main/java/org/traccar/api/BaseResource.java | 12 +- .../org/traccar/api/ExtendedObjectResource.java | 51 ++++---- src/main/java/org/traccar/api/MediaFilter.java | 6 +- .../java/org/traccar/api/SimpleObjectResource.java | 30 +++-- .../org/traccar/api/resource/DeviceResource.java | 4 +- .../org/traccar/api/resource/EventResource.java | 18 +-- .../traccar/api/resource/NotificationResource.java | 3 +- .../org/traccar/api/resource/PositionResource.java | 2 +- .../org/traccar/api/resource/ReportResource.java | 20 +-- .../traccar/api/security/PermissionsService.java | 136 +++++++++++++++++++++ src/main/java/org/traccar/config/Keys.java | 7 ++ .../java/org/traccar/database/DeviceManager.java | 3 +- .../org/traccar/database/PermissionsManager.java | 22 ---- src/main/java/org/traccar/model/Permission.java | 2 +- src/main/java/org/traccar/model/User.java | 6 + .../java/org/traccar/storage/DatabaseStorage.java | 57 +++++++-- .../java/org/traccar/storage/MemoryStorage.java | 5 +- .../java/org/traccar/storage/QueryBuilder.java | 20 +-- src/main/java/org/traccar/storage/Storage.java | 17 ++- .../java/org/traccar/storage/query/Condition.java | 38 ++++++ 24 files changed, 375 insertions(+), 199 deletions(-) create mode 100644 src/main/java/org/traccar/api/security/PermissionsService.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/debug.xml b/debug.xml index f9515bb2b..941b849bb 100644 --- a/debug.xml +++ b/debug.xml @@ -11,6 +11,7 @@ true true + true org.h2.Driver jdbc:h2:./target/database diff --git a/gradle/checkstyle.xml b/gradle/checkstyle.xml index 9d30e53d6..6cff6ffa5 100644 --- a/gradle/checkstyle.xml +++ b/gradle/checkstyle.xml @@ -122,7 +122,9 @@ - + + + diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index 842f7e3ce..79cfcc0a8 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -444,9 +444,4 @@ public class MainModule extends AbstractModule { return GlobalTimer.getTimer(); } - @Override - protected void configure() { - binder().requireExplicitBindings(); - } - } diff --git a/src/main/java/org/traccar/api/BaseObjectResource.java b/src/main/java/org/traccar/api/BaseObjectResource.java index 22756f62a..07c74449c 100644 --- a/src/main/java/org/traccar/api/BaseObjectResource.java +++ b/src/main/java/org/traccar/api/BaseObjectResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,70 +16,44 @@ */ package org.traccar.api; -import java.sql.SQLException; -import java.util.Set; - -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.Response; - import org.traccar.Context; import org.traccar.database.BaseObjectManager; import org.traccar.database.ExtendedObjectManager; -import org.traccar.database.ManagableObjects; import org.traccar.database.SimpleObjectManager; import org.traccar.helper.LogAction; import org.traccar.model.BaseModel; import org.traccar.model.Calendar; -import org.traccar.model.Command; import org.traccar.model.Device; import org.traccar.model.Group; -import org.traccar.model.GroupedModel; -import org.traccar.model.ScheduledModel; +import org.traccar.model.Permission; import org.traccar.model.User; import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Response; public abstract class BaseObjectResource extends BaseResource { - private final Class baseClass; + protected final Class baseClass; public BaseObjectResource(Class baseClass) { this.baseClass = baseClass; } - protected final Class getBaseClass() { - return baseClass; - } - - protected final Set getSimpleManagerItems(BaseObjectManager manager, boolean all, long userId) { - Set result; - if (all) { - if (Context.getPermissionsManager().getUserAdmin(getUserId())) { - result = manager.getAllItems(); - } else { - Context.getPermissionsManager().checkManager(getUserId()); - result = ((ManagableObjects) manager).getManagedItems(getUserId()); - } - } else { - if (userId == 0) { - userId = getUserId(); - } - Context.getPermissionsManager().checkUser(getUserId(), userId); - result = ((ManagableObjects) manager).getUserItems(userId); - } - return result; - } - @Path("{id}") @GET - public Response getSingle(@PathParam("id") long id) throws SQLException { - Context.getPermissionsManager().checkPermission(baseClass, getUserId(), id); - BaseObjectManager manager = Context.getManager(baseClass); - T entity = manager.getById(id); + public Response getSingle(@PathParam("id") long id) throws StorageException { + permissionsService.checkPermission(baseClass, getUserId(), id); + T entity = storage.getObject(baseClass, new Request( + new Columns.All(), new Condition.Equals("id", "id", id))); if (entity != null) { return Response.ok(entity).build(); } else { @@ -89,25 +63,13 @@ public abstract class BaseObjectResource extends BaseResour @POST public Response add(T entity) throws StorageException { - Context.getPermissionsManager().checkReadonly(getUserId()); - if (baseClass.equals(Device.class)) { - Context.getPermissionsManager().checkDeviceReadonly(getUserId()); - Context.getPermissionsManager().checkDeviceLimit(getUserId()); - } else if (baseClass.equals(Command.class)) { - Context.getPermissionsManager().checkLimitCommands(getUserId()); - } else if (entity instanceof GroupedModel && ((GroupedModel) entity).getGroupId() != 0) { - Context.getPermissionsManager().checkPermission( - Group.class, getUserId(), ((GroupedModel) entity).getGroupId()); - } else if (entity instanceof ScheduledModel && ((ScheduledModel) entity).getCalendarId() != 0) { - Context.getPermissionsManager().checkPermission( - Calendar.class, getUserId(), ((ScheduledModel) entity).getCalendarId()); - } + permissionsService.checkEdit(getUserId(), entity, true); BaseObjectManager manager = Context.getManager(baseClass); manager.addItem(entity); LogAction.create(getUserId(), entity); - Context.getDataManager().linkObject(User.class, getUserId(), baseClass, entity.getId(), true); + storage.addPermission(new Permission(User.class, getUserId(), baseClass, entity.getId())); LogAction.link(getUserId(), User.class, getUserId(), baseClass, entity.getId()); if (manager instanceof SimpleObjectManager) { @@ -122,22 +84,8 @@ public abstract class BaseObjectResource extends BaseResour @Path("{id}") @PUT public Response update(T entity) throws StorageException { - Context.getPermissionsManager().checkReadonly(getUserId()); - if (baseClass.equals(Device.class)) { - Context.getPermissionsManager().checkDeviceReadonly(getUserId()); - } 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()); - } else if (entity instanceof GroupedModel && ((GroupedModel) entity).getGroupId() != 0) { - Context.getPermissionsManager().checkPermission( - Group.class, getUserId(), ((GroupedModel) entity).getGroupId()); - } else if (entity instanceof ScheduledModel && ((ScheduledModel) entity).getCalendarId() != 0) { - Context.getPermissionsManager().checkPermission( - Calendar.class, getUserId(), ((ScheduledModel) entity).getCalendarId()); - } - Context.getPermissionsManager().checkPermission(baseClass, getUserId(), entity.getId()); + permissionsService.checkEdit(getUserId(), entity, false); + permissionsService.checkPermission(baseClass, getUserId(), entity.getId()); Context.getManager(baseClass).updateItem(entity); LogAction.edit(getUserId(), entity); @@ -152,13 +100,8 @@ public abstract class BaseObjectResource extends BaseResour @Path("{id}") @DELETE public Response remove(@PathParam("id") long id) throws StorageException { - 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); + permissionsService.checkEdit(getUserId(), baseClass, false); + permissionsService.checkPermission(baseClass, getUserId(), id); BaseObjectManager manager = Context.getManager(baseClass); manager.removeItem(id); diff --git a/src/main/java/org/traccar/api/BaseResource.java b/src/main/java/org/traccar/api/BaseResource.java index 6dff8c8c3..33abe73fa 100644 --- a/src/main/java/org/traccar/api/BaseResource.java +++ b/src/main/java/org/traccar/api/BaseResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,11 @@ */ package org.traccar.api; +import org.traccar.api.security.PermissionsService; import org.traccar.api.security.UserPrincipal; +import org.traccar.storage.Storage; +import javax.inject.Inject; import javax.ws.rs.core.Context; import javax.ws.rs.core.SecurityContext; @@ -25,6 +28,12 @@ public class BaseResource { @Context private SecurityContext securityContext; + @Inject + protected Storage storage; + + @Inject + protected PermissionsService permissionsService; + protected long getUserId() { UserPrincipal principal = (UserPrincipal) securityContext.getUserPrincipal(); if (principal != null) { @@ -32,4 +41,5 @@ public class BaseResource { } return 0; } + } diff --git a/src/main/java/org/traccar/api/ExtendedObjectResource.java b/src/main/java/org/traccar/api/ExtendedObjectResource.java index 9e554217e..a12314a2c 100644 --- a/src/main/java/org/traccar/api/ExtendedObjectResource.java +++ b/src/main/java/org/traccar/api/ExtendedObjectResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,17 +16,19 @@ */ package org.traccar.api; -import java.sql.SQLException; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import org.traccar.model.BaseModel; +import org.traccar.model.Device; +import org.traccar.model.Group; +import org.traccar.model.User; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; import javax.ws.rs.GET; import javax.ws.rs.QueryParam; - -import org.traccar.Context; -import org.traccar.database.ExtendedObjectManager; -import org.traccar.model.BaseModel; +import java.util.Collection; +import java.util.LinkedList; public class ExtendedObjectResource extends BaseObjectResource { @@ -36,27 +38,28 @@ public class ExtendedObjectResource extends BaseObjectResou @GET public Collection get( - @QueryParam("all") boolean all, @QueryParam("userId") long userId, @QueryParam("groupId") long groupId, - @QueryParam("deviceId") long deviceId, @QueryParam("refresh") boolean refresh) throws SQLException { - - ExtendedObjectManager manager = (ExtendedObjectManager) Context.getManager(getBaseClass()); - if (refresh) { - manager.refreshItems(); - } + @QueryParam("all") boolean all, @QueryParam("userId") long userId, + @QueryParam("groupId") long groupId, @QueryParam("deviceId") long deviceId) throws StorageException { - Set result = new HashSet<>(getSimpleManagerItems(manager, all, userId)); + var conditions = new LinkedList(); - if (groupId != 0) { - Context.getPermissionsManager().checkGroup(getUserId(), groupId); - result.retainAll(manager.getGroupItems(groupId)); + if (all) { + permissionsService.checkAdmin(getUserId()); + } else { + permissionsService.checkUser(getUserId(), userId); + conditions.add(new Condition.Permission(User.class, userId, baseClass)); } - if (deviceId != 0) { - Context.getPermissionsManager().checkDevice(getUserId(), deviceId); - result.retainAll(manager.getDeviceItems(deviceId)); + if (groupId > 0) { + permissionsService.checkPermission(Group.class, getUserId(), groupId); + conditions.add(new Condition.Permission(Group.class, groupId, baseClass)); + } + if (deviceId > 0) { + permissionsService.checkPermission(Device.class, getUserId(), deviceId); + conditions.add(new Condition.Permission(Device.class, deviceId, baseClass)); } - return manager.getItems(result); + return storage.getObjects(baseClass, new Request(new Columns.All(), Condition.merge(conditions))); } } diff --git a/src/main/java/org/traccar/api/MediaFilter.java b/src/main/java/org/traccar/api/MediaFilter.java index 77731a810..0433147f8 100644 --- a/src/main/java/org/traccar/api/MediaFilter.java +++ b/src/main/java/org/traccar/api/MediaFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ package org.traccar.api; import java.io.IOException; -import java.sql.SQLException; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -76,9 +75,6 @@ public class MediaFilter implements Filter { } catch (SecurityException e) { httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); httpResponse.getWriter().println(Log.exceptionStack(e)); - } catch (SQLException e) { - httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); - httpResponse.getWriter().println(Log.exceptionStack(e)); } } diff --git a/src/main/java/org/traccar/api/SimpleObjectResource.java b/src/main/java/org/traccar/api/SimpleObjectResource.java index a7fcae0e7..b55bf91e3 100644 --- a/src/main/java/org/traccar/api/SimpleObjectResource.java +++ b/src/main/java/org/traccar/api/SimpleObjectResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,15 +16,17 @@ */ package org.traccar.api; -import java.sql.SQLException; -import java.util.Collection; +import org.traccar.model.BaseModel; +import org.traccar.model.User; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; import javax.ws.rs.GET; import javax.ws.rs.QueryParam; - -import org.traccar.Context; -import org.traccar.database.BaseObjectManager; -import org.traccar.model.BaseModel; +import java.util.Collection; +import java.util.LinkedList; public class SimpleObjectResource extends BaseObjectResource { @@ -34,10 +36,18 @@ public class SimpleObjectResource extends BaseObjectResourc @GET public Collection get( - @QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException { + @QueryParam("all") boolean all, @QueryParam("userId") long userId) throws StorageException { + + var conditions = new LinkedList(); + + if (all) { + permissionsService.checkAdmin(getUserId()); + } else { + permissionsService.checkUser(getUserId(), userId); + conditions.add(new Condition.Permission(User.class, userId, baseClass)); + } - BaseObjectManager manager = Context.getManager(getBaseClass()); - return manager.getItems(getSimpleManagerItems(manager, all, userId)); + return storage.getObjects(baseClass, new Request(new Columns.All(), Condition.merge(conditions))); } } diff --git a/src/main/java/org/traccar/api/resource/DeviceResource.java b/src/main/java/org/traccar/api/resource/DeviceResource.java index 9436b59f6..309308e75 100644 --- a/src/main/java/org/traccar/api/resource/DeviceResource.java +++ b/src/main/java/org/traccar/api/resource/DeviceResource.java @@ -31,8 +31,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; - -import java.sql.SQLException; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -51,7 +49,7 @@ public class DeviceResource extends BaseObjectResource { public Collection get( @QueryParam("all") boolean all, @QueryParam("userId") long userId, @QueryParam("uniqueId") List uniqueIds, - @QueryParam("id") List deviceIds) throws SQLException { + @QueryParam("id") List deviceIds) { DeviceManager deviceManager = Context.getDeviceManager(); Set result; if (all) { diff --git a/src/main/java/org/traccar/api/resource/EventResource.java b/src/main/java/org/traccar/api/resource/EventResource.java index 354d96e4f..38b101b25 100644 --- a/src/main/java/org/traccar/api/resource/EventResource.java +++ b/src/main/java/org/traccar/api/resource/EventResource.java @@ -15,6 +15,11 @@ */ package org.traccar.api.resource; +import org.traccar.Context; +import org.traccar.api.BaseResource; +import org.traccar.model.Event; +import org.traccar.storage.StorageException; + import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -24,13 +29,6 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.traccar.Context; -import org.traccar.api.BaseResource; -import org.traccar.model.Event; -import org.traccar.model.Geofence; -import org.traccar.model.Maintenance; -import org.traccar.storage.StorageException; - @Path("events") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @@ -44,12 +42,6 @@ public class EventResource extends BaseResource { throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build()); } Context.getPermissionsManager().checkDevice(getUserId(), event.getDeviceId()); - if (event.getGeofenceId() != 0) { - Context.getPermissionsManager().checkPermission(Geofence.class, getUserId(), event.getGeofenceId()); - } - if (event.getMaintenanceId() != 0) { - Context.getPermissionsManager().checkPermission(Maintenance.class, getUserId(), event.getMaintenanceId()); - } return event; } diff --git a/src/main/java/org/traccar/api/resource/NotificationResource.java b/src/main/java/org/traccar/api/resource/NotificationResource.java index 9631a52b7..cf4b66fa1 100644 --- a/src/main/java/org/traccar/api/resource/NotificationResource.java +++ b/src/main/java/org/traccar/api/resource/NotificationResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,6 @@ import org.traccar.model.Notification; import org.traccar.model.Typed; import org.traccar.notification.MessageException; - @Path("notifications") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) diff --git a/src/main/java/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java index 511032402..941417231 100644 --- a/src/main/java/org/traccar/api/resource/PositionResource.java +++ b/src/main/java/org/traccar/api/resource/PositionResource.java @@ -55,7 +55,7 @@ public class PositionResource extends BaseResource { } else { Context.getPermissionsManager().checkDevice(getUserId(), deviceId); if (from != null && to != null) { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); return Context.getDataManager().getPositions(deviceId, from, to); } else { return Collections.singleton(Context.getDeviceManager().getLastPosition(deviceId)); diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 03df0d03a..901385d0d 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -99,7 +99,7 @@ public class ReportResource extends BaseResource { public Collection getRoute( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); return Route.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -111,7 +111,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); Route.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); @@ -124,7 +124,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); return Events.getObjects(getUserId(), deviceIds, groupIds, types, from, to); } @@ -137,7 +137,7 @@ public class ReportResource extends BaseResource { @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); Events.getExcel(stream, getUserId(), deviceIds, groupIds, types, from, to); @@ -150,7 +150,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily) throws StorageException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); return Summary.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); } @@ -163,7 +163,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily, @QueryParam("mail") boolean mail) throws StorageException, IOException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); Summary.getExcel(stream, getUserId(), deviceIds, groupIds, from, to, daily); @@ -176,7 +176,7 @@ public class ReportResource extends BaseResource { public Collection getTrips( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); return Trips.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -188,7 +188,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); Trips.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); @@ -201,7 +201,7 @@ public class ReportResource extends BaseResource { public Collection getStops( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); return Stops.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -213,7 +213,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - Context.getPermissionsManager().checkDisableReports(getUserId()); + permissionsService.checkReports(getUserId()); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); Stops.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); diff --git a/src/main/java/org/traccar/api/security/PermissionsService.java b/src/main/java/org/traccar/api/security/PermissionsService.java new file mode 100644 index 000000000..e39b8808f --- /dev/null +++ b/src/main/java/org/traccar/api/security/PermissionsService.java @@ -0,0 +1,136 @@ +/* + * Copyright 2022 Anton Tananaev (anton@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.api.security; + +import org.traccar.model.Calendar; +import org.traccar.model.Command; +import org.traccar.model.Device; +import org.traccar.model.Group; +import org.traccar.model.GroupedModel; +import org.traccar.model.ScheduledModel; +import org.traccar.model.Server; +import org.traccar.model.User; +import org.traccar.storage.Storage; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; + +import javax.inject.Inject; + +public class PermissionsService { + + private final Storage storage; + + private Server server; + private User user; + + @Inject + public PermissionsService(Storage storage) { + this.storage = storage; + } + + private Server getServer() throws StorageException { + if (server == null) { + server = storage.getObject( + Server.class, new Request(new Columns.All())); + } + return server; + } + + private User getUser(long userId) throws StorageException { + if (user == null) { + user = storage.getObject( + User.class, new Request(new Columns.All(), new Condition.Equals("id", "id", userId))); + } + return user; + } + + public void checkAdmin(long userId) throws StorageException, SecurityException { + if (!getUser(userId).getAdministrator()) { + throw new SecurityException("Account is readonly"); + } + } + + public void checkReports(long userId) throws StorageException, SecurityException { + if (!getUser(userId).getAdministrator() + && (server.getDisableReports() || getUser(userId).getDisableReports())) { + throw new SecurityException("Reports are disabled"); + } + } + + public void checkEdit(long userId, Class clazz, boolean addition) throws StorageException, SecurityException { + if (!getUser(userId).getAdministrator()) { + boolean denied = false; + if (getServer().getReadonly() || getUser(userId).getReadonly()) { + denied = true; + } else if (clazz.equals(Device.class)) { + denied = getServer().getDeviceReadonly() || getUser(userId).getDeviceReadonly(); + if (addition) { + int deviceCount = storage.getPermissions(User.class, userId, Device.class).size(); + denied = deviceCount >= getUser(userId).getDeviceLimit(); + } + } else if (clazz.equals(Command.class)) { + denied = getServer().getLimitCommands() || getUser(userId).getLimitCommands(); + } + if (denied) { + throw new SecurityException("Write access denied"); + } + } + } + + public void checkEdit(long userId, Object object, boolean addition) throws StorageException, SecurityException { + if (!getUser(userId).getAdministrator()) { + checkEdit(userId, object.getClass(), addition); + boolean denied = false; + if (object instanceof GroupedModel) { + long groupId = ((GroupedModel) object).getGroupId(); + if (groupId > 0) { + denied = storage.getPermissions(User.class, userId, Group.class, groupId).isEmpty(); + // TODO TEST NESTED GROUP PERMISSION + } + } + if (object instanceof ScheduledModel) { + long calendarId = ((ScheduledModel) object).getCalendarId(); + if (calendarId > 0) { + denied = storage.getPermissions(User.class, userId, Calendar.class, calendarId).isEmpty(); + } + } + if (denied) { + throw new SecurityException("Write access denied"); + } + } + } + + public void checkUser(long userId, long managedUserId) throws StorageException, SecurityException { + if (userId != managedUserId && !getUser(userId).getAdministrator()) { + if (!getUser(userId).getManager() + || storage.getPermissions(User.class, userId, User.class, managedUserId).isEmpty()) { + throw new SecurityException("User access denied"); + } + } + } + + public void checkPermission( + Class clazz, long userId, long objectId) throws StorageException, SecurityException { + if (!getUser(userId).getAdministrator() + && storage.getPermissions(User.class, userId, clazz, objectId).isEmpty()) { + // TODO handle nested objects + throw new SecurityException(clazz.getSimpleName() + " access denied"); + } + } + +} diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index ccfe4bee7..1341f4143 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1271,6 +1271,13 @@ public final class Keys { "logger.console", Collections.singletonList(KeyType.GLOBAL)); + /** + * Log executed SQL queries. + */ + public static final ConfigKey LOGGER_QUERIES = new ConfigKey<>( + "logger.queries", + Collections.singletonList(KeyType.GLOBAL)); + /** * Log file name. For rotating logs, a date is added at the end of the file name for non-current logs. */ diff --git a/src/main/java/org/traccar/database/DeviceManager.java b/src/main/java/org/traccar/database/DeviceManager.java index 40591e869..a9b8454eb 100644 --- a/src/main/java/org/traccar/database/DeviceManager.java +++ b/src/main/java/org/traccar/database/DeviceManager.java @@ -15,7 +15,6 @@ */ package org.traccar.database; -import java.sql.SQLException; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; @@ -110,7 +109,7 @@ public class DeviceManager extends BaseObjectManager implements Identity } @Override - public Device getByUniqueId(String uniqueId) throws SQLException { + public Device getByUniqueId(String uniqueId) { boolean forceUpdate; try { readLock(); diff --git a/src/main/java/org/traccar/database/PermissionsManager.java b/src/main/java/org/traccar/database/PermissionsManager.java index 2bb808033..9a673c784 100644 --- a/src/main/java/org/traccar/database/PermissionsManager.java +++ b/src/main/java/org/traccar/database/PermissionsManager.java @@ -264,45 +264,23 @@ public class PermissionsManager { return user != null && user.getReadonly(); } - 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 boolean getUserDisableReport(long userId) { - User user = getUser(userId); - return user != null && user.getDisableReports(); - } - public void checkReadonly(long userId) throws SecurityException { if (!getUserAdmin(userId) && (server.getReadonly() || getUserReadonly(userId))) { throw new SecurityException("Account is readonly"); } } - public void checkDeviceReadonly(long userId) throws SecurityException { - 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 checkDisableReports(long userId) throws SecurityException { - if (!getUserAdmin(userId) && (server.getDisableReports() || getUserDisableReport(userId))) { - throw new SecurityException("Account has reports disabled"); - } - } - 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"); diff --git a/src/main/java/org/traccar/model/Permission.java b/src/main/java/org/traccar/model/Permission.java index ad0176b39..bace6b7d4 100644 --- a/src/main/java/org/traccar/model/Permission.java +++ b/src/main/java/org/traccar/model/Permission.java @@ -71,7 +71,7 @@ public class Permission { data.put(getKey(propertyClass), propertyId); } - private static String getKey(Class clazz) { + public static String getKey(Class clazz) { return Introspector.decapitalize(clazz.getSimpleName()) + "Id"; } diff --git a/src/main/java/org/traccar/model/User.java b/src/main/java/org/traccar/model/User.java index 464d0cbfe..6a67f3276 100644 --- a/src/main/java/org/traccar/model/User.java +++ b/src/main/java/org/traccar/model/User.java @@ -79,6 +79,12 @@ public class User extends ExtendedModel { private boolean administrator; + @QueryIgnore + @JsonIgnore + public boolean getManager() { + return userLimit != 0; + } + public boolean getAdministrator() { return administrator; } diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java index d73dc7b25..4c985d98a 100644 --- a/src/main/java/org/traccar/storage/DatabaseStorage.java +++ b/src/main/java/org/traccar/storage/DatabaseStorage.java @@ -1,3 +1,18 @@ +/* + * Copyright 2022 Anton Tananaev (anton@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.storage; import org.traccar.model.Permission; @@ -10,6 +25,7 @@ import org.traccar.storage.query.Request; import javax.sql.DataSource; import java.sql.SQLException; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -96,9 +112,20 @@ public class DatabaseStorage extends Storage { } @Override - public List getPermissions(Class ownerClass, Class propertyClass) throws StorageException { + public List getPermissions( + Class ownerClass, long ownerId, Class propertyClass, long propertyId) throws StorageException { StringBuilder query = new StringBuilder("SELECT * FROM "); query.append(Permission.getStorageName(ownerClass, propertyClass)); + var conditions = new LinkedList(); + if (ownerId > 0) { + conditions.add(new Condition.Equals( + Permission.getKey(ownerClass), Permission.getKey(ownerClass), ownerId)); + } + if (propertyId > 0) { + conditions.add(new Condition.Equals( + Permission.getKey(propertyClass), Permission.getKey(propertyClass), propertyId)); + } + query.append(formatCondition(Condition.merge(conditions))); try { QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); return builder.executePermissionsQuery(); @@ -154,18 +181,21 @@ public class DatabaseStorage extends Storage { private Map getConditionVariables(Condition genericCondition) { Map results = new HashMap<>(); if (genericCondition instanceof Condition.Compare) { - Condition.Compare condition = (Condition.Compare) genericCondition; + var condition = (Condition.Compare) genericCondition; if (condition.getValue() != null) { results.put(condition.getVariable(), condition.getValue()); } } else if (genericCondition instanceof Condition.Between) { - Condition.Between condition = (Condition.Between) genericCondition; + var condition = (Condition.Between) genericCondition; results.put(condition.getFromVariable(), condition.getFromValue()); results.put(condition.getToVariable(), condition.getToValue()); } else if (genericCondition instanceof Condition.Binary) { - Condition.Binary condition = (Condition.Binary) genericCondition; + var condition = (Condition.Binary) genericCondition; results.putAll(getConditionVariables(condition.getFirst())); results.putAll(getConditionVariables(condition.getSecond())); + } else if (genericCondition instanceof Condition.Permission) { + var condition = (Condition.Permission) genericCondition; + results.put(Permission.getKey(condition.getOwnerClass()), condition.getOwnerId()); } return results; } @@ -187,7 +217,7 @@ public class DatabaseStorage extends Storage { } if (genericCondition instanceof Condition.Compare) { - Condition.Compare condition = (Condition.Compare) genericCondition; + var condition = (Condition.Compare) genericCondition; result.append(condition.getColumn()); result.append(" "); result.append(condition.getOperator()); @@ -196,7 +226,7 @@ public class DatabaseStorage extends Storage { } else if (genericCondition instanceof Condition.Between) { - Condition.Between condition = (Condition.Between) genericCondition; + var condition = (Condition.Between) genericCondition; result.append(condition.getColumn()); result.append(" BETWEEN :"); result.append(condition.getFromVariable()); @@ -205,13 +235,26 @@ public class DatabaseStorage extends Storage { } else if (genericCondition instanceof Condition.Binary) { - Condition.Binary condition = (Condition.Binary) genericCondition; + var condition = (Condition.Binary) genericCondition; result.append(formatCondition(condition.getFirst(), false)); result.append(" "); result.append(condition.getOperator()); result.append(" "); result.append(formatCondition(condition.getSecond(), false)); + } else if (genericCondition instanceof Condition.Permission) { + + var condition = (Condition.Permission) genericCondition; + result.append("id IN (SELECT "); + result.append(Permission.getKey(condition.getPropertyClass())); + result.append(" FROM "); + result.append(Permission.getStorageName(condition.getOwnerClass(), condition.getPropertyClass())); + result.append(" WHERE "); + result.append(Permission.getKey(condition.getOwnerClass())); + result.append(" = :"); + result.append(Permission.getKey(condition.getOwnerClass())); + result.append(")"); + } } return result.toString(); diff --git a/src/main/java/org/traccar/storage/MemoryStorage.java b/src/main/java/org/traccar/storage/MemoryStorage.java index 9cfe30a2b..115bbea7a 100644 --- a/src/main/java/org/traccar/storage/MemoryStorage.java +++ b/src/main/java/org/traccar/storage/MemoryStorage.java @@ -38,8 +38,11 @@ public class MemoryStorage extends Storage { } @Override - public List getPermissions(Class ownerClass, Class propertyClass) { + public List getPermissions( + Class ownerClass, long ownerId, Class propertyClass, long propertyId) { return getPermissionsSet(ownerClass, propertyClass).stream() + .filter(pair -> ownerId == 0 || pair.getFirst().equals(ownerId)) + .filter(pair -> propertyId == 0 || pair.getSecond().equals(propertyId)) .map(pair -> new Permission(ownerClass, pair.getFirst(), propertyClass, pair.getSecond())) .collect(Collectors.toList()); } diff --git a/src/main/java/org/traccar/storage/QueryBuilder.java b/src/main/java/org/traccar/storage/QueryBuilder.java index da8002f0b..874a046b4 100644 --- a/src/main/java/org/traccar/storage/QueryBuilder.java +++ b/src/main/java/org/traccar/storage/QueryBuilder.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.config.Keys; import org.traccar.model.Permission; import javax.sql.DataSource; @@ -309,15 +310,6 @@ public final class QueryBuilder { void process(T object, ResultSet resultSet) throws SQLException; } - public T executeQuerySingle(Class clazz) throws SQLException { - List result = executeQuery(clazz); - if (!result.isEmpty()) { - return result.iterator().next(); - } else { - return null; - } - } - private void addProcessors( List> processors, final Class parameterType, final Method method, final String name) { @@ -395,6 +387,12 @@ public final class QueryBuilder { } } + private void logQuery() { + if (Context.getConfig().getBoolean(Keys.LOGGER_QUERIES)) { + LOGGER.info(query); + } + } + public List executeQuery(Class clazz) throws SQLException { List result = new LinkedList<>(); @@ -402,6 +400,8 @@ public final class QueryBuilder { try { + logQuery(); + try (ResultSet resultSet = statement.executeQuery()) { ResultSetMetaData resultMetaData = resultSet.getMetaData(); @@ -457,6 +457,7 @@ public final class QueryBuilder { if (query != null) { try { + logQuery(); statement.execute(); if (returnGeneratedKeys) { ResultSet resultSet = statement.getGeneratedKeys(); @@ -476,6 +477,7 @@ public final class QueryBuilder { List result = new LinkedList<>(); if (query != null) { try { + logQuery(); try (ResultSet resultSet = statement.executeQuery()) { ResultSetMetaData resultMetaData = resultSet.getMetaData(); while (resultSet.next()) { diff --git a/src/main/java/org/traccar/storage/Storage.java b/src/main/java/org/traccar/storage/Storage.java index 22c48cae0..3b27f57e9 100644 --- a/src/main/java/org/traccar/storage/Storage.java +++ b/src/main/java/org/traccar/storage/Storage.java @@ -16,12 +16,27 @@ public abstract class Storage { public abstract void removeObject(Class clazz, Request request) throws StorageException; public abstract List getPermissions( - Class ownerClass, Class propertyClass) throws StorageException; + Class ownerClass, long ownerId, Class propertyClass, long propertyId) throws StorageException; public abstract void addPermission(Permission permission) throws StorageException; public abstract void removePermission(Permission permission) throws StorageException; + public List getPermissions( + Class ownerClass, Class propertyClass) throws StorageException { + return getPermissions(ownerClass, 0, propertyClass, 0); + } + + public List getPermissions( + Class ownerClass, long ownerId, Class propertyClass) throws StorageException { + return getPermissions(ownerClass, ownerId, propertyClass, 0); + } + + public List getPermissions( + Class ownerClass, Class propertyClass, long propertyId) throws StorageException { + return getPermissions(ownerClass, 0, propertyClass, propertyId); + } + public T getObject(Class clazz, Request request) throws StorageException { var objects = getObjects(clazz, request); return objects.isEmpty() ? null : objects.get(0); diff --git a/src/main/java/org/traccar/storage/query/Condition.java b/src/main/java/org/traccar/storage/query/Condition.java index 82c8e8479..304440698 100644 --- a/src/main/java/org/traccar/storage/query/Condition.java +++ b/src/main/java/org/traccar/storage/query/Condition.java @@ -1,7 +1,21 @@ package org.traccar.storage.query; +import java.util.List; + public interface Condition { + static Condition merge(List conditions) { + Condition result = null; + var iterator = conditions.iterator(); + if (iterator.hasNext()) { + result = iterator.next(); + while (iterator.hasNext()) { + result = new Condition.And(result, iterator.next()); + } + } + return result; + } + class Equals extends Compare { public Equals(String column, String variable) { this(column, variable, null); @@ -114,4 +128,28 @@ public interface Condition { } } + class Permission implements Condition { + private final Class ownerClass; + private final long ownerId; + private final Class propertyClass; + + public Permission(Class ownerClass, long ownerId, Class propertyClass) { + this.ownerClass = ownerClass; + this.ownerId = ownerId; + this.propertyClass = propertyClass; + } + + public Class getOwnerClass() { + return ownerClass; + } + + public long getOwnerId() { + return ownerId; + } + + public Class getPropertyClass() { + return propertyClass; + } + } + } -- cgit v1.2.3 From ec76482c15094a7e04964c67d3011a7e8e1ad6a9 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 4 Jun 2022 06:33:02 -0700 Subject: Refactor commands manager --- src/main/java/org/traccar/BaseProtocolDecoder.java | 19 ++- src/main/java/org/traccar/Context.java | 12 -- src/main/java/org/traccar/MainModule.java | 6 + .../org/traccar/api/resource/CommandResource.java | 104 ++++++++++---- .../org/traccar/api/resource/PositionResource.java | 3 +- .../org/traccar/api/resource/ReportResource.java | 21 +-- .../traccar/api/security/PermissionsService.java | 12 +- .../java/org/traccar/database/CommandsManager.java | 149 +++++++-------------- .../java/org/traccar/database/DataManager.java | 13 +- .../org/traccar/database/PermissionsManager.java | 31 ----- src/main/java/org/traccar/model/Server.java | 6 +- src/main/java/org/traccar/model/User.java | 8 +- .../java/org/traccar/model/UserRestrictions.java | 23 ++++ .../traccar/protocol/OsmAndProtocolDecoder.java | 9 +- .../java/org/traccar/storage/DatabaseStorage.java | 16 +++ .../java/org/traccar/storage/query/Condition.java | 16 +++ src/test/java/org/traccar/BaseTest.java | 2 + 17 files changed, 241 insertions(+), 209 deletions(-) create mode 100644 src/main/java/org/traccar/model/UserRestrictions.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/BaseProtocolDecoder.java b/src/main/java/org/traccar/BaseProtocolDecoder.java index 71ef686fa..5b3f129de 100644 --- a/src/main/java/org/traccar/BaseProtocolDecoder.java +++ b/src/main/java/org/traccar/BaseProtocolDecoder.java @@ -15,7 +15,6 @@ */ package org.traccar; -import com.google.inject.Inject; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import org.traccar.config.Config; @@ -32,6 +31,7 @@ import org.traccar.session.ConnectionManager; import org.traccar.session.DeviceSession; import org.traccar.storage.StorageException; +import javax.inject.Inject; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collection; @@ -51,6 +51,7 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { private ConnectionManager connectionManager; private StatisticsManager statisticsManager; private MediaManager mediaManager; + private CommandsManager commandsManager; public BaseProtocolDecoder(Protocol protocol) { this.protocol = protocol; @@ -96,6 +97,15 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { this.mediaManager = mediaManager; } + @Inject + public void setCommandsManager(CommandsManager commandsManager) { + this.commandsManager = commandsManager; + } + + public CommandsManager getCommandsManager() { + return commandsManager; + } + public String writeMediaFile(String uniqueId, ByteBuf buf, String extension) { return mediaManager.writeFile(uniqueId, buf, extension); } @@ -204,11 +214,8 @@ public abstract class BaseProtocolDecoder extends ExtendedObjectDecoder { } protected void sendQueuedCommands(Channel channel, SocketAddress remoteAddress, long deviceId) { - CommandsManager commandsManager = Context.getCommandsManager(); - if (commandsManager != null) { - for (Command command : commandsManager.readQueuedCommands(deviceId)) { - protocol.sendDataCommand(channel, remoteAddress, command); - } + for (Command command : commandsManager.readQueuedCommands(deviceId)) { + protocol.sendDataCommand(channel, remoteAddress, command); } } diff --git a/src/main/java/org/traccar/Context.java b/src/main/java/org/traccar/Context.java index 4eab36a89..6ee8344ce 100644 --- a/src/main/java/org/traccar/Context.java +++ b/src/main/java/org/traccar/Context.java @@ -25,7 +25,6 @@ import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.database.BaseObjectManager; import org.traccar.database.CalendarManager; -import org.traccar.database.CommandsManager; import org.traccar.session.ConnectionManager; import org.traccar.database.DataManager; import org.traccar.database.DeviceManager; @@ -45,7 +44,6 @@ import org.traccar.helper.Log; import org.traccar.helper.SanitizerModule; 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; @@ -217,12 +215,6 @@ public final class Context { return driversManager; } - private static CommandsManager commandsManager; - - public static CommandsManager getCommandsManager() { - return commandsManager; - } - private static MaintenancesManager maintenancesManager; public static MaintenancesManager getMaintenancesManager() { @@ -337,8 +329,6 @@ public final class Context { driversManager = new DriversManager(dataManager); - commandsManager = new CommandsManager(dataManager, config.getBoolean(Keys.COMMANDS_QUEUEING)); - orderManager = new OrderManager(dataManager); } @@ -392,8 +382,6 @@ 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; } else if (clazz.equals(Maintenance.class)) { return (BaseObjectManager) maintenancesManager; } else if (clazz.equals(Notification.class)) { diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index f46312221..7b46656b3 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -60,6 +60,7 @@ import org.traccar.handler.GeocoderHandler; import org.traccar.handler.GeolocationHandler; import org.traccar.handler.SpeedLimitHandler; import org.traccar.reports.model.TripsConfig; +import org.traccar.sms.SmsManager; import org.traccar.speedlimit.OverpassSpeedLimitProvider; import org.traccar.speedlimit.SpeedLimitProvider; import org.traccar.storage.Storage; @@ -134,6 +135,11 @@ public class MainModule extends AbstractModule { return Context.getMaintenancesManager(); } + @Provides + public static SmsManager provideSmsManager() { + return Context.getSmsManager(); + } + @Singleton @Provides public static Geocoder provideGeocoder(Config config) { diff --git a/src/main/java/org/traccar/api/resource/CommandResource.java b/src/main/java/org/traccar/api/resource/CommandResource.java index a31345246..17bb150f6 100644 --- a/src/main/java/org/traccar/api/resource/CommandResource.java +++ b/src/main/java/org/traccar/api/resource/CommandResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2015 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2016 Gabor Somogyi (gabor.g.somogyi@gmail.com) * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) * @@ -17,16 +17,23 @@ */ package org.traccar.api.resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.traccar.BaseProtocol; import org.traccar.Context; import org.traccar.api.ExtendedObjectResource; import org.traccar.database.CommandsManager; import org.traccar.model.Command; +import org.traccar.model.Device; +import org.traccar.model.Position; import org.traccar.model.Typed; +import org.traccar.model.UserRestrictions; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - +import javax.inject.Inject; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -35,40 +42,61 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; @Path("commands") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class CommandResource extends ExtendedObjectResource { + private static final Logger LOGGER = LoggerFactory.getLogger(CommandResource.class); + + @Inject + private CommandsManager commandsManager; + public CommandResource() { super(Command.class); } + private BaseProtocol getDeviceProtocol(long deviceId) throws StorageException { + Position position = storage.getObject(Position.class, new Request( + new Columns.All(), new Condition.LatestPositions(deviceId))); + if (position != null) { + return Context.getServerManager().getProtocol(position.getProtocol()); + } else { + return null; + } + } + @GET @Path("send") - public Collection get(@QueryParam("deviceId") long deviceId) { - Context.getPermissionsManager().checkDevice(getUserId(), deviceId); - CommandsManager commandsManager = Context.getCommandsManager(); - Set result = new HashSet<>(commandsManager.getUserItems(getUserId())); - result.retainAll(commandsManager.getSupportedCommands(deviceId)); - return commandsManager.getItems(result); + public Collection get(@QueryParam("deviceId") long deviceId) throws StorageException { + permissionsService.checkPermission(Device.class, getUserId(), deviceId); + BaseProtocol protocol = getDeviceProtocol(deviceId); + return get(false, 0, 0, deviceId).stream().filter(command -> { + String type = command.getType(); + if (protocol != null) { + return command.getTextChannel() && protocol.getSupportedTextCommands().contains(type) + || !command.getTextChannel() && protocol.getSupportedDataCommands().contains(type); + } else { + return type.equals(Command.TYPE_CUSTOM); + } + }).collect(Collectors.toList()); } @POST @Path("send") public Response send(Command entity) throws Exception { - Context.getPermissionsManager().checkReadonly(getUserId()); - long deviceId = entity.getDeviceId(); - long id = entity.getId(); - Context.getPermissionsManager().checkDevice(getUserId(), deviceId); - if (id != 0) { - Context.getPermissionsManager().checkPermission(Command.class, getUserId(), id); - Context.getPermissionsManager().checkUserDeviceCommand(getUserId(), deviceId, id); - } else { - Context.getPermissionsManager().checkLimitCommands(getUserId()); - } - if (!Context.getCommandsManager().sendCommand(entity)) { + permissionsService.checkRestriction(getUserId(), UserRestrictions::getReadonly); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getLimitCommands); + permissionsService.checkPermission(Device.class, getUserId(), entity.getDeviceId()); + if (!commandsManager.sendCommand(entity)) { return Response.accepted(entity).build(); } return Response.ok(entity).build(); @@ -78,15 +106,33 @@ public class CommandResource extends ExtendedObjectResource { @Path("types") public Collection get( @QueryParam("deviceId") long deviceId, - @QueryParam("protocol") String protocol, - @QueryParam("textChannel") boolean textChannel) { + @QueryParam("textChannel") boolean textChannel) throws StorageException { if (deviceId != 0) { - Context.getPermissionsManager().checkDevice(getUserId(), deviceId); - return Context.getCommandsManager().getCommandTypes(deviceId, textChannel); - } else if (protocol != null) { - return Context.getCommandsManager().getCommandTypes(protocol, textChannel); + permissionsService.checkPermission(Device.class, getUserId(), deviceId); + BaseProtocol protocol = getDeviceProtocol(deviceId); + if (protocol != null) { + if (textChannel) { + return protocol.getSupportedTextCommands().stream().map(Typed::new).collect(Collectors.toList()); + } else { + return protocol.getSupportedDataCommands().stream().map(Typed::new).collect(Collectors.toList()); + } + } else { + return Collections.singletonList(new Typed(Command.TYPE_CUSTOM)); + } } else { - return Context.getCommandsManager().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 Typed(field.get(null).toString())); + } catch (IllegalArgumentException | IllegalAccessException error) { + LOGGER.warn("Get command types error", error); + } + } + } + return result; } } + } diff --git a/src/main/java/org/traccar/api/resource/PositionResource.java b/src/main/java/org/traccar/api/resource/PositionResource.java index 941417231..2618a04cb 100644 --- a/src/main/java/org/traccar/api/resource/PositionResource.java +++ b/src/main/java/org/traccar/api/resource/PositionResource.java @@ -18,6 +18,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; import org.traccar.model.Position; +import org.traccar.model.UserRestrictions; import org.traccar.storage.StorageException; import javax.ws.rs.Consumes; @@ -55,7 +56,7 @@ public class PositionResource extends BaseResource { } else { Context.getPermissionsManager().checkDevice(getUserId(), deviceId); if (from != null && to != null) { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return Context.getDataManager().getPositions(deviceId, from, to); } else { return Collections.singleton(Context.getDeviceManager().getLastPosition(deviceId)); diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 901385d0d..06ccbe4fd 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -42,6 +42,7 @@ import org.traccar.api.BaseResource; import org.traccar.helper.LogAction; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.model.UserRestrictions; import org.traccar.reports.Events; import org.traccar.reports.Summary; import org.traccar.reports.Trips; @@ -99,7 +100,7 @@ public class ReportResource extends BaseResource { public Collection getRoute( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); return Route.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -111,7 +112,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); Route.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); @@ -124,7 +125,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); return Events.getObjects(getUserId(), deviceIds, groupIds, types, from, to); } @@ -137,7 +138,7 @@ public class ReportResource extends BaseResource { @QueryParam("type") final List types, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); Events.getExcel(stream, getUserId(), deviceIds, groupIds, types, from, to); @@ -150,7 +151,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily) throws StorageException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); return Summary.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); } @@ -163,7 +164,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily, @QueryParam("mail") boolean mail) throws StorageException, IOException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); Summary.getExcel(stream, getUserId(), deviceIds, groupIds, from, to, daily); @@ -176,7 +177,7 @@ public class ReportResource extends BaseResource { public Collection getTrips( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); return Trips.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -188,7 +189,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); Trips.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); @@ -201,7 +202,7 @@ public class ReportResource extends BaseResource { public Collection getStops( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); return Stops.getObjects(getUserId(), deviceIds, groupIds, from, to); } @@ -213,7 +214,7 @@ public class ReportResource extends BaseResource { @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) throws StorageException, IOException { - permissionsService.checkReports(getUserId()); + permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); Stops.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); diff --git a/src/main/java/org/traccar/api/security/PermissionsService.java b/src/main/java/org/traccar/api/security/PermissionsService.java index 9daef355e..b4a375109 100644 --- a/src/main/java/org/traccar/api/security/PermissionsService.java +++ b/src/main/java/org/traccar/api/security/PermissionsService.java @@ -25,6 +25,7 @@ import org.traccar.model.ManagedUser; import org.traccar.model.ScheduledModel; import org.traccar.model.Server; import org.traccar.model.User; +import org.traccar.model.UserRestrictions; import org.traccar.storage.Storage; import org.traccar.storage.StorageException; import org.traccar.storage.query.Columns; @@ -71,10 +72,15 @@ public class PermissionsService { } } - public void checkReports(long userId) throws StorageException, SecurityException { + public interface CheckRestrictionCallback { + boolean denied(UserRestrictions userRestrictions); + } + + public void checkRestriction( + long userId, CheckRestrictionCallback callback) throws StorageException, SecurityException { if (!getUser(userId).getAdministrator() - && (getServer().getDisableReports() || getUser(userId).getDisableReports())) { - throw new SecurityException("Reports are disabled"); + && (callback.denied(getServer()) || callback.denied(getUser(userId)))) { + throw new SecurityException("Operation restricted"); } } diff --git a/src/main/java/org/traccar/database/CommandsManager.java b/src/main/java/org/traccar/database/CommandsManager.java index 57ce0f9a4..d440755f7 100644 --- a/src/main/java/org/traccar/database/CommandsManager.java +++ b/src/main/java/org/traccar/database/CommandsManager.java @@ -16,66 +16,75 @@ */ package org.traccar.database; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; +import org.traccar.BaseProtocol; +import org.traccar.ServerManager; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.model.Command; +import org.traccar.model.Device; +import org.traccar.model.Position; +import org.traccar.session.ConnectionManager; +import org.traccar.session.DeviceSession; +import org.traccar.sms.SmsManager; +import org.traccar.storage.Storage; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.traccar.BaseProtocol; -import org.traccar.Context; -import org.traccar.model.Command; -import org.traccar.model.Typed; -import org.traccar.model.Position; -import org.traccar.session.DeviceSession; - -public class CommandsManager extends ExtendedObjectManager { +@Singleton +public class CommandsManager { - private static final Logger LOGGER = LoggerFactory.getLogger(CommandsManager.class); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Map> deviceQueues = new ConcurrentHashMap<>(); - private final boolean queueing; + private final Storage storage; + private final ServerManager serverManager; + private final SmsManager smsManager; + private final ConnectionManager connectionManager; - public CommandsManager(DataManager dataManager, boolean queueing) { - super(dataManager, Command.class); - this.queueing = queueing; - } + private final boolean queueing; - public boolean checkDeviceCommand(long deviceId, long commandId) { - return !getAllDeviceItems(deviceId).contains(commandId); + @Inject + public CommandsManager( + Storage storage, ServerManager serverManager, @Nullable SmsManager smsManager, + ConnectionManager connectionManager, Config config) { + this.storage = storage; + this.serverManager = serverManager; + this.smsManager = smsManager; + this.connectionManager = connectionManager; + queueing = config.getBoolean(Keys.COMMANDS_QUEUEING); } public boolean sendCommand(Command command) throws Exception { long deviceId = command.getDeviceId(); - if (command.getId() != 0) { - command = getById(command.getId()).clone(); - command.setDeviceId(deviceId); - } 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); + Device device = storage.getObject(Device.class, new Request( + new Columns.All(), new Condition.Equals("id", "id", deviceId))); + Position position = storage.getObject(Position.class, new Request( + new Columns.All(), new Condition.Equals("id", "id", device.getPositionId()))); + if (position != null) { + BaseProtocol protocol = serverManager.getProtocol(position.getProtocol()); + protocol.sendTextCommand(device.getPhone(), command); } else if (command.getType().equals(Command.TYPE_CUSTOM)) { - if (Context.getSmsManager() != null) { - Context.getSmsManager().sendMessageSync(phone, command.getString(Command.KEY_DATA), true); - } else { - throw new RuntimeException("SMS is not enabled"); - } + smsManager.sendMessageSync(device.getPhone(), command.getString(Command.KEY_DATA), true); } else { throw new RuntimeException("Command " + command.getType() + " is not supported"); } } else { - DeviceSession deviceSession = Context.getConnectionManager().getDeviceSession(deviceId); + DeviceSession deviceSession = connectionManager.getDeviceSession(deviceId); if (deviceSession != null) { if (deviceSession.supportsLiveCommands()) { deviceSession.sendCommand(command); @@ -93,76 +102,22 @@ public class CommandsManager extends ExtendedObjectManager { return true; } - public Collection getSupportedCommands(long deviceId) { - List result = new ArrayList<>(); - Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId); - for (long commandId : getAllDeviceItems(deviceId)) { - Command command = getById(commandId); - if (lastPosition != null) { - BaseProtocol protocol = Context.getServerManager().getProtocol(lastPosition.getProtocol()); - if (command.getTextChannel() && protocol.getSupportedTextCommands().contains(command.getType()) - || !command.getTextChannel() - && protocol.getSupportedDataCommands().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) { - Position lastPosition = Context.getIdentityManager().getLastPosition(deviceId); - if (lastPosition != null) { - return getCommandTypes(lastPosition.getProtocol(), textChannel); - } else { - return Collections.singletonList(new Typed(Command.TYPE_CUSTOM)); - } - } - - public Collection getCommandTypes(String protocolName, boolean textChannel) { - List result = new ArrayList<>(); - BaseProtocol protocol = Context.getServerManager().getProtocol(protocolName); - Collection commands; - commands = textChannel ? protocol.getSupportedTextCommands() : protocol.getSupportedDataCommands(); - for (String commandKey : commands) { - result.add(new Typed(commandKey)); - } - 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 Typed(field.get(null).toString())); - } catch (IllegalArgumentException | IllegalAccessException error) { - LOGGER.warn("Get command types error", error); - } - } - } - return result; - } - private Queue getDeviceQueue(long deviceId) { Queue deviceQueue; try { - readLock(); + lock.readLock().lock(); deviceQueue = deviceQueues.get(deviceId); } finally { - readUnlock(); + lock.readLock().unlock(); } if (deviceQueue != null) { return deviceQueue; } else { try { - writeLock(); + lock.writeLock().lock(); return deviceQueues.computeIfAbsent(deviceId, key -> new ConcurrentLinkedQueue<>()); } finally { - writeUnlock(); + lock.writeLock().unlock(); } } } @@ -174,10 +129,10 @@ public class CommandsManager extends ExtendedObjectManager { public Collection readQueuedCommands(long deviceId, int count) { Queue deviceQueue; try { - readLock(); + lock.readLock().lock(); deviceQueue = deviceQueues.get(deviceId); } finally { - readUnlock(); + lock.readLock().unlock(); } Collection result = new ArrayList<>(); if (deviceQueue != null) { diff --git a/src/main/java/org/traccar/database/DataManager.java b/src/main/java/org/traccar/database/DataManager.java index b5966ca9e..1426daea3 100644 --- a/src/main/java/org/traccar/database/DataManager.java +++ b/src/main/java/org/traccar/database/DataManager.java @@ -50,8 +50,6 @@ import java.lang.reflect.Method; import java.net.URL; import java.util.Collection; import java.util.Date; -import java.util.LinkedList; -import java.util.List; public class DataManager { @@ -205,14 +203,9 @@ public class DataManager { } public Collection getLatestPositions() throws StorageException { - List positions = new LinkedList<>(); - List devices = storage.getObjects(Device.class, new Request(new Columns.Include("positionId"))); - for (Device device : devices) { - positions.addAll(storage.getObjects(Position.class, new Request( - new Columns.All(), - new Condition.Equals("id", "id", device.getPositionId())))); - } - return positions; + return storage.getObjects(Position.class, new Request( + new Columns.All(), + new Condition.LatestPositions())); } public Server getServer() throws StorageException { diff --git a/src/main/java/org/traccar/database/PermissionsManager.java b/src/main/java/org/traccar/database/PermissionsManager.java index 29bb8a27b..4d5c59fcc 100644 --- a/src/main/java/org/traccar/database/PermissionsManager.java +++ b/src/main/java/org/traccar/database/PermissionsManager.java @@ -20,7 +20,6 @@ import org.slf4j.LoggerFactory; import org.traccar.Context; 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; @@ -274,18 +273,6 @@ public class PermissionsManager { } } - 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) { @@ -367,21 +354,9 @@ public class PermissionsManager { if (object.equals(Device.class)) { checkDevice(userId, objectId); - } else if (object.equals(Command.class)) { - manager = Context.getCommandsManager(); } else { throw new IllegalArgumentException("Unknown object type"); } - - if (manager != null && !manager.checkItemPermission(userId, objectId) && !getUserAdmin(userId)) { - checkManager(userId); - for (long managedUserId : usersManager.getManagedItems(userId)) { - if (manager.checkItemPermission(managedUserId, objectId)) { - return; - } - } - throw new SecurityException("Type " + object + " access denied"); - } } public void refreshAllUsersPermissions() { @@ -390,7 +365,6 @@ public class PermissionsManager { } Context.getCalendarManager().refreshUserItems(); Context.getDriversManager().refreshUserItems(); - Context.getCommandsManager().refreshUserItems(); Context.getMaintenancesManager().refreshUserItems(); if (Context.getNotificationManager() != null) { Context.getNotificationManager().refreshUserItems(); @@ -402,7 +376,6 @@ public class PermissionsManager { Context.getGeofenceManager().refreshExtendedPermissions(); } Context.getDriversManager().refreshExtendedPermissions(); - Context.getCommandsManager().refreshExtendedPermissions(); Context.getMaintenancesManager().refreshExtendedPermissions(); } @@ -420,8 +393,6 @@ public class PermissionsManager { Context.getDriversManager().refreshUserItems(); } else if (permission.getPropertyClass().equals(Calendar.class)) { Context.getCalendarManager().refreshUserItems(); - } else if (permission.getPropertyClass().equals(Command.class)) { - Context.getCommandsManager().refreshUserItems(); } else if (permission.getPropertyClass().equals(Maintenance.class)) { Context.getMaintenancesManager().refreshUserItems(); } else if (permission.getPropertyClass().equals(Order.class)) { @@ -435,8 +406,6 @@ public class PermissionsManager { Context.getGeofenceManager().refreshExtendedPermissions(); } else if (permission.getPropertyClass().equals(Driver.class)) { Context.getDriversManager().refreshExtendedPermissions(); - } else if (permission.getPropertyClass().equals(Command.class)) { - Context.getCommandsManager().refreshExtendedPermissions(); } else if (permission.getPropertyClass().equals(Maintenance.class)) { Context.getMaintenancesManager().refreshExtendedPermissions(); } else if (permission.getPropertyClass().equals(Order.class)) { diff --git a/src/main/java/org/traccar/model/Server.java b/src/main/java/org/traccar/model/Server.java index b48e84939..7cffd7eac 100644 --- a/src/main/java/org/traccar/model/Server.java +++ b/src/main/java/org/traccar/model/Server.java @@ -22,7 +22,7 @@ import org.traccar.storage.StorageName; @StorageName("tc_servers") @JsonIgnoreProperties(ignoreUnknown = true) -public class Server extends ExtendedModel { +public class Server extends ExtendedModel implements UserRestrictions { private boolean registration; @@ -36,6 +36,7 @@ public class Server extends ExtendedModel { private boolean readonly; + @Override public boolean getReadonly() { return readonly; } @@ -46,6 +47,7 @@ public class Server extends ExtendedModel { private boolean deviceReadonly; + @Override public boolean getDeviceReadonly() { return deviceReadonly; } @@ -146,6 +148,7 @@ public class Server extends ExtendedModel { private boolean limitCommands; + @Override public boolean getLimitCommands() { return limitCommands; } @@ -156,6 +159,7 @@ public class Server extends ExtendedModel { private boolean disableReports; + @Override public boolean getDisableReports() { return disableReports; } diff --git a/src/main/java/org/traccar/model/User.java b/src/main/java/org/traccar/model/User.java index 6a67f3276..12fd03d45 100644 --- a/src/main/java/org/traccar/model/User.java +++ b/src/main/java/org/traccar/model/User.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2013 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import org.traccar.storage.StorageName; import java.util.Date; @StorageName("tc_users") -public class User extends ExtendedModel { +public class User extends ExtendedModel implements UserRestrictions { private String name; @@ -69,6 +69,7 @@ public class User extends ExtendedModel { private boolean readonly; + @Override public boolean getReadonly() { return readonly; } @@ -195,6 +196,7 @@ public class User extends ExtendedModel { private boolean deviceReadonly; + @Override public boolean getDeviceReadonly() { return deviceReadonly; } @@ -222,6 +224,7 @@ public class User extends ExtendedModel { private boolean limitCommands; + @Override public boolean getLimitCommands() { return limitCommands; } @@ -234,6 +237,7 @@ public class User extends ExtendedModel { private boolean disableReports; + @Override public boolean getDisableReports() { return disableReports; } diff --git a/src/main/java/org/traccar/model/UserRestrictions.java b/src/main/java/org/traccar/model/UserRestrictions.java new file mode 100644 index 000000000..2e4e5e363 --- /dev/null +++ b/src/main/java/org/traccar/model/UserRestrictions.java @@ -0,0 +1,23 @@ +/* + * Copyright 2022 Anton Tananaev (anton@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.model; + +public interface UserRestrictions { + boolean getReadonly(); + boolean getDeviceReadonly(); + boolean getLimitCommands(); + boolean getDisableReports(); +} diff --git a/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java index 178ec344f..3574dd2a3 100644 --- a/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java @@ -21,10 +21,8 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.QueryStringDecoder; import org.traccar.BaseHttpProtocolDecoder; -import org.traccar.Context; import org.traccar.session.DeviceSession; import org.traccar.Protocol; -import org.traccar.database.CommandsManager; import org.traccar.helper.DateUtil; import org.traccar.model.CellTower; import org.traccar.model.Command; @@ -178,11 +176,8 @@ public class OsmAndProtocolDecoder extends BaseHttpProtocolDecoder { if (position.getDeviceId() != 0) { String response = null; - CommandsManager commandsManager = Context.getCommandsManager(); - if (commandsManager != null) { - for (Command command : commandsManager.readQueuedCommands(position.getDeviceId(), 1)) { - response = command.getString(Command.KEY_DATA); - } + for (Command command : getCommandsManager().readQueuedCommands(position.getDeviceId(), 1)) { + response = command.getString(Command.KEY_DATA); } if (response != null) { sendResponse(channel, HttpResponseStatus.OK, Unpooled.copiedBuffer(response, StandardCharsets.UTF_8)); diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java index 91dd6b077..fc468182e 100644 --- a/src/main/java/org/traccar/storage/DatabaseStorage.java +++ b/src/main/java/org/traccar/storage/DatabaseStorage.java @@ -209,6 +209,11 @@ public class DatabaseStorage extends Storage { } else { results.put(Permission.getKey(condition.getPropertyClass()), condition.getPropertyId()); } + } else if (genericCondition instanceof Condition.LatestPositions) { + var condition = (Condition.LatestPositions) genericCondition; + if (condition.getDeviceId() > 0) { + results.put("deviceId", condition.getDeviceId()); + } } return results; } @@ -262,6 +267,17 @@ public class DatabaseStorage extends Storage { result.append(formatPermissionQuery(condition)); result.append(")"); + } else if (genericCondition instanceof Condition.LatestPositions) { + + var condition = (Condition.LatestPositions) genericCondition; + result.append("id IN ("); + result.append("SELECT positionId FROM "); + result.append(getStorageName(Device.class)); + if (condition.getDeviceId() > 0) { + result.append(" WHERE id = :deviceId"); + } + result.append(")"); + } } return result.toString(); diff --git a/src/main/java/org/traccar/storage/query/Condition.java b/src/main/java/org/traccar/storage/query/Condition.java index 91ede236c..136b0402b 100644 --- a/src/main/java/org/traccar/storage/query/Condition.java +++ b/src/main/java/org/traccar/storage/query/Condition.java @@ -196,4 +196,20 @@ public interface Condition { } } + class LatestPositions implements Condition { + private final long deviceId; + + public LatestPositions(long deviceId) { + this.deviceId = deviceId; + } + + public LatestPositions() { + this(0); + } + + public long getDeviceId() { + return deviceId; + } + } + } diff --git a/src/test/java/org/traccar/BaseTest.java b/src/test/java/org/traccar/BaseTest.java index a34524c43..1652a6694 100644 --- a/src/test/java/org/traccar/BaseTest.java +++ b/src/test/java/org/traccar/BaseTest.java @@ -2,6 +2,7 @@ package org.traccar; import io.netty.channel.Channel; import org.traccar.config.Config; +import org.traccar.database.CommandsManager; import org.traccar.database.IdentityManager; import org.traccar.database.MediaManager; import org.traccar.database.StatisticsManager; @@ -52,6 +53,7 @@ public class BaseTest { decoder.setConnectionManager(connectionManager); decoder.setStatisticsManager(mock(StatisticsManager.class)); decoder.setMediaManager(mock(MediaManager.class)); + decoder.setCommandsManager(mock(CommandsManager.class)); return decoder; } -- cgit v1.2.3 From 8c12ded81c5dce295fcb229c566209d784f55356 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 4 Jun 2022 10:38:49 -0700 Subject: Remove maintenance manager --- src/main/java/org/traccar/Context.java | 13 +---- src/main/java/org/traccar/MainModule.java | 6 --- .../org/traccar/api/resource/ReportResource.java | 4 +- .../traccar/api/security/PermissionsService.java | 4 +- .../org/traccar/database/MaintenancesManager.java | 27 ---------- .../org/traccar/database/NotificationManager.java | 57 ++++++++++------------ .../org/traccar/database/PermissionsManager.java | 7 --- .../handler/events/MaintenanceEventHandler.java | 25 +++------- .../org/traccar/notification/EventForwarder.java | 20 +++++--- .../notification/NotificationFormatter.java | 21 ++++---- .../traccar/notificators/NotificatorFirebase.java | 5 +- .../org/traccar/notificators/NotificatorMail.java | 5 +- .../traccar/notificators/NotificatorPushover.java | 5 +- .../org/traccar/notificators/NotificatorSms.java | 7 ++- .../traccar/notificators/NotificatorTelegram.java | 5 +- src/main/java/org/traccar/reports/Events.java | 34 +++++++------ src/main/java/org/traccar/reports/ReportUtils.java | 16 ++++++ 17 files changed, 117 insertions(+), 144 deletions(-) delete mode 100644 src/main/java/org/traccar/database/MaintenancesManager.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/Context.java b/src/main/java/org/traccar/Context.java index 1aa673077..a833d0c52 100644 --- a/src/main/java/org/traccar/Context.java +++ b/src/main/java/org/traccar/Context.java @@ -32,7 +32,6 @@ import org.traccar.database.GeofenceManager; import org.traccar.database.GroupsManager; import org.traccar.database.IdentityManager; import org.traccar.database.MailManager; -import org.traccar.database.MaintenancesManager; import org.traccar.database.NotificationManager; import org.traccar.database.PermissionsManager; import org.traccar.database.UsersManager; @@ -45,7 +44,6 @@ import org.traccar.model.Device; import org.traccar.model.Driver; import org.traccar.model.Geofence; import org.traccar.model.Group; -import org.traccar.model.Maintenance; import org.traccar.model.Notification; import org.traccar.model.User; import org.traccar.notification.EventForwarder; @@ -193,12 +191,6 @@ public final class Context { return driversManager; } - private static MaintenancesManager maintenancesManager; - - public static MaintenancesManager getMaintenancesManager() { - return maintenancesManager; - } - private static SmsManager smsManager; public static SmsManager getSmsManager() { @@ -289,7 +281,7 @@ public final class Context { } if (config.hasKey(Keys.EVENT_FORWARD_URL)) { - eventForwarder = new EventForwarder(); + eventForwarder = new EventForwarder(config); } driversManager = new DriversManager(dataManager); @@ -300,7 +292,6 @@ public final class Context { geofenceManager = new GeofenceManager(dataManager); calendarManager = new CalendarManager(dataManager); - maintenancesManager = new MaintenancesManager(dataManager); notificationManager = new NotificationManager(dataManager); notificatorManager = new NotificatorManager(); Properties velocityProperties = new Properties(); @@ -345,8 +336,6 @@ public final class Context { return (BaseObjectManager) geofenceManager; } else if (clazz.equals(Driver.class)) { return (BaseObjectManager) driversManager; - } else if (clazz.equals(Maintenance.class)) { - return (BaseObjectManager) maintenancesManager; } else if (clazz.equals(Notification.class)) { return (BaseObjectManager) notificationManager; } diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index 15b9cefda..219a8fc11 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -30,7 +30,6 @@ import org.traccar.database.DataManager; import org.traccar.database.DeviceManager; import org.traccar.database.GeofenceManager; import org.traccar.database.IdentityManager; -import org.traccar.database.MaintenancesManager; import org.traccar.database.StatisticsManager; import org.traccar.geocoder.AddressFormat; import org.traccar.geocoder.BanGeocoder; @@ -131,11 +130,6 @@ public class MainModule extends AbstractModule { return Context.getCalendarManager(); } - @Provides - public static MaintenancesManager provideMaintenancesManager() { - return Context.getMaintenancesManager(); - } - @Provides public static SmsManager provideSmsManager() { return Context.getSmsManager(); diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 06ccbe4fd..a7bbe1067 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -127,7 +127,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); - return Events.getObjects(getUserId(), deviceIds, groupIds, types, from, to); + return Events.getObjects(storage, getUserId(), deviceIds, groupIds, types, from, to); } @Path("events") @@ -141,7 +141,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); - Events.getExcel(stream, getUserId(), deviceIds, groupIds, types, from, to); + Events.getExcel(stream, storage, getUserId(), deviceIds, groupIds, types, from, to); }); } diff --git a/src/main/java/org/traccar/api/security/PermissionsService.java b/src/main/java/org/traccar/api/security/PermissionsService.java index b4a375109..12a2189e9 100644 --- a/src/main/java/org/traccar/api/security/PermissionsService.java +++ b/src/main/java/org/traccar/api/security/PermissionsService.java @@ -138,13 +138,13 @@ public class PermissionsService { public void checkPermission( Class clazz, long userId, long objectId) throws StorageException, SecurityException { if (!getUser(userId).getAdministrator() && !(clazz.equals(User.class) && userId == objectId)) { - var objects = storage.getObjects(clazz, new Request( + var object = storage.getObject(clazz, new Request( new Columns.Include("id"), new Condition.And( new Condition.Equals("id", "id", objectId), new Condition.Permission( User.class, userId, clazz.equals(User.class) ? ManagedUser.class : clazz)))); - if (!objects.isEmpty()) { + if (object == null) { throw new SecurityException(clazz.getSimpleName() + " access denied"); } } diff --git a/src/main/java/org/traccar/database/MaintenancesManager.java b/src/main/java/org/traccar/database/MaintenancesManager.java deleted file mode 100644 index 4e266cb78..000000000 --- a/src/main/java/org/traccar/database/MaintenancesManager.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018 Anton Tananaev (anton@traccar.org) - * Copyright 2018 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 org.traccar.model.Maintenance; - -public class MaintenancesManager extends ExtendedObjectManager { - - public MaintenancesManager(DataManager dataManager) { - super(dataManager, Maintenance.class); - } - -} diff --git a/src/main/java/org/traccar/database/NotificationManager.java b/src/main/java/org/traccar/database/NotificationManager.java index f358b1d4d..64f3b6775 100644 --- a/src/main/java/org/traccar/database/NotificationManager.java +++ b/src/main/java/org/traccar/database/NotificationManager.java @@ -77,42 +77,37 @@ public class NotificationManager extends ExtendedObjectManager { usersToForward = new HashSet<>(); } for (long userId : users) { - if ((event.getGeofenceId() == 0 - || Context.getGeofenceManager().checkItemPermission(userId, event.getGeofenceId())) - && (event.getMaintenanceId() == 0 - || Context.getMaintenancesManager().checkItemPermission(userId, event.getMaintenanceId()))) { - if (usersToForward != null) { - usersToForward.add(userId); - } - final Set notificators = new HashSet<>(); - for (long notificationId : getEffectiveNotifications(userId, deviceId, event.getEventTime())) { - Notification notification = getById(notificationId); - if (getById(notificationId).getType().equals(event.getType())) { - boolean filter = false; - if (event.getType().equals(Event.TYPE_ALARM)) { - String alarmsAttribute = notification.getString("alarms"); - if (alarmsAttribute == null) { - filter = true; - } else { - List alarms = Arrays.asList(alarmsAttribute.split(",")); - filter = !alarms.contains(event.getString(Position.KEY_ALARM)); - } - } - if (!filter) { - notificators.addAll(notification.getNotificatorsTypes()); + if (usersToForward != null) { + usersToForward.add(userId); + } + final Set notificators = new HashSet<>(); + for (long notificationId : getEffectiveNotifications(userId, deviceId, event.getEventTime())) { + Notification notification = getById(notificationId); + if (getById(notificationId).getType().equals(event.getType())) { + boolean filter = false; + if (event.getType().equals(Event.TYPE_ALARM)) { + String alarmsAttribute = notification.getString("alarms"); + if (alarmsAttribute == null) { + filter = true; + } else { + List alarms = Arrays.asList(alarmsAttribute.split(",")); + filter = !alarms.contains(event.getString(Position.KEY_ALARM)); } } + if (!filter) { + notificators.addAll(notification.getNotificatorsTypes()); + } } + } - if (position != null && position.getAddress() == null - && geocodeOnRequest && Context.getGeocoder() != null) { - position.setAddress(Context.getGeocoder() - .getAddress(position.getLatitude(), position.getLongitude(), null)); - } + if (position != null && position.getAddress() == null + && geocodeOnRequest && Context.getGeocoder() != null) { + position.setAddress(Context.getGeocoder() + .getAddress(position.getLatitude(), position.getLongitude(), null)); + } - for (String notificator : notificators) { - Context.getNotificatorManager().getNotificator(notificator).sendAsync(userId, event, position); - } + for (String notificator : notificators) { + Context.getNotificatorManager().getNotificator(notificator).sendAsync(userId, event, position); } } if (Context.getEventForwarder() != null) { diff --git a/src/main/java/org/traccar/database/PermissionsManager.java b/src/main/java/org/traccar/database/PermissionsManager.java index 46e19d380..61b35b380 100644 --- a/src/main/java/org/traccar/database/PermissionsManager.java +++ b/src/main/java/org/traccar/database/PermissionsManager.java @@ -24,7 +24,6 @@ import org.traccar.model.Device; import org.traccar.model.Driver; import org.traccar.model.Geofence; import org.traccar.model.Group; -import org.traccar.model.Maintenance; import org.traccar.model.ManagedUser; import org.traccar.model.Notification; import org.traccar.model.Permission; @@ -364,7 +363,6 @@ public class PermissionsManager { } Context.getCalendarManager().refreshUserItems(); Context.getDriversManager().refreshUserItems(); - Context.getMaintenancesManager().refreshUserItems(); if (Context.getNotificationManager() != null) { Context.getNotificationManager().refreshUserItems(); } @@ -375,7 +373,6 @@ public class PermissionsManager { Context.getGeofenceManager().refreshExtendedPermissions(); } Context.getDriversManager().refreshExtendedPermissions(); - Context.getMaintenancesManager().refreshExtendedPermissions(); } public void refreshPermissions(Permission permission) { @@ -392,8 +389,6 @@ public class PermissionsManager { Context.getDriversManager().refreshUserItems(); } else if (permission.getPropertyClass().equals(Calendar.class)) { Context.getCalendarManager().refreshUserItems(); - } else if (permission.getPropertyClass().equals(Maintenance.class)) { - Context.getMaintenancesManager().refreshUserItems(); } else if (permission.getPropertyClass().equals(Notification.class) && Context.getNotificationManager() != null) { Context.getNotificationManager().refreshUserItems(); @@ -403,8 +398,6 @@ public class PermissionsManager { Context.getGeofenceManager().refreshExtendedPermissions(); } else if (permission.getPropertyClass().equals(Driver.class)) { Context.getDriversManager().refreshExtendedPermissions(); - } else if (permission.getPropertyClass().equals(Maintenance.class)) { - Context.getMaintenancesManager().refreshExtendedPermissions(); } else if (permission.getPropertyClass().equals(Notification.class) && Context.getNotificationManager() != null) { Context.getNotificationManager().refreshExtendedPermissions(); diff --git a/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java b/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java index 5b9ce4316..be3e9bf8d 100644 --- a/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java +++ b/src/main/java/org/traccar/handler/events/MaintenanceEventHandler.java @@ -20,41 +20,32 @@ import java.util.HashMap; import java.util.Map; import io.netty.channel.ChannelHandler; -import org.traccar.database.IdentityManager; -import org.traccar.database.MaintenancesManager; import org.traccar.model.Event; import org.traccar.model.Maintenance; import org.traccar.model.Position; +import org.traccar.session.cache.CacheManager; import javax.inject.Inject; @ChannelHandler.Sharable public class MaintenanceEventHandler extends BaseEventHandler { - private final IdentityManager identityManager; - private final MaintenancesManager maintenancesManager; + private final CacheManager cacheManager; @Inject - public MaintenanceEventHandler(IdentityManager identityManager, MaintenancesManager maintenancesManager) { - this.identityManager = identityManager; - this.maintenancesManager = maintenancesManager; + public MaintenanceEventHandler(CacheManager cacheManager) { + this.cacheManager = cacheManager; } @Override protected Map analyzePosition(Position position) { - if (identityManager.getById(position.getDeviceId()) == null - || !identityManager.isLatestPosition(position)) { - return null; - } - - Position lastPosition = identityManager.getLastPosition(position.getDeviceId()); - if (lastPosition == null) { + Position lastPosition = cacheManager.getPosition(position.getDeviceId()); + if (lastPosition == null || position.getFixTime().compareTo(lastPosition.getFixTime()) < 0) { return null; } Map events = new HashMap<>(); - for (long maintenanceId : maintenancesManager.getAllDeviceItems(position.getDeviceId())) { - Maintenance maintenance = maintenancesManager.getById(maintenanceId); + for (Maintenance maintenance : cacheManager.getDeviceObjects(position.getDeviceId(), Maintenance.class)) { if (maintenance.getPeriod() != 0) { double oldValue = lastPosition.getDouble(maintenance.getType()); double newValue = position.getDouble(maintenance.getType()); @@ -62,7 +53,7 @@ public class MaintenanceEventHandler extends BaseEventHandler { && (long) ((oldValue - maintenance.getStart()) / maintenance.getPeriod()) < (long) ((newValue - maintenance.getStart()) / maintenance.getPeriod())) { Event event = new Event(Event.TYPE_MAINTENANCE, position); - event.setMaintenanceId(maintenanceId); + event.setMaintenanceId(maintenance.getId()); event.set(maintenance.getType(), newValue); events.put(event, position); } diff --git a/src/main/java/org/traccar/notification/EventForwarder.java b/src/main/java/org/traccar/notification/EventForwarder.java index c908fedbd..b0494d74d 100644 --- a/src/main/java/org/traccar/notification/EventForwarder.java +++ b/src/main/java/org/traccar/notification/EventForwarder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,15 @@ package org.traccar.notification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.Main; +import org.traccar.config.Config; import org.traccar.config.Keys; import org.traccar.model.Device; import org.traccar.model.Event; import org.traccar.model.Geofence; import org.traccar.model.Maintenance; import org.traccar.model.Position; +import org.traccar.session.cache.CacheManager; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation; @@ -39,9 +42,12 @@ public class EventForwarder { private final String url; private final String header; - public EventForwarder() { - url = Context.getConfig().getString(Keys.EVENT_FORWARD_URL); - header = Context.getConfig().getString(Keys.EVENT_FORWARD_HEADERS); + private final CacheManager cacheManager; + + public EventForwarder(Config config) { + url = config.getString(Keys.EVENT_FORWARD_URL); + header = config.getString(Keys.EVENT_FORWARD_HEADERS); + cacheManager = Main.getInjector().getInstance(CacheManager.class); } private static final String KEY_POSITION = "position"; @@ -83,18 +89,18 @@ public class EventForwarder { if (position != null) { data.put(KEY_POSITION, position); } - Device device = Context.getIdentityManager().getById(event.getDeviceId()); + Device device = cacheManager.getObject(Device.class, event.getDeviceId()); if (device != null) { data.put(KEY_DEVICE, device); } if (event.getGeofenceId() != 0) { - Geofence geofence = Context.getGeofenceManager().getById(event.getGeofenceId()); + Geofence geofence = cacheManager.getObject(Geofence.class, event.getGeofenceId()); if (geofence != null) { data.put(KEY_GEOFENCE, geofence); } } if (event.getMaintenanceId() != 0) { - Maintenance maintenance = Context.getMaintenancesManager().getById(event.getMaintenanceId()); + Maintenance maintenance = cacheManager.getObject(Maintenance.class, event.getMaintenanceId()); if (maintenance != null) { data.put(KEY_MAINTENANCE, maintenance); } diff --git a/src/main/java/org/traccar/notification/NotificationFormatter.java b/src/main/java/org/traccar/notification/NotificationFormatter.java index 9a6723a71..107426e06 100644 --- a/src/main/java/org/traccar/notification/NotificationFormatter.java +++ b/src/main/java/org/traccar/notification/NotificationFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,19 +20,23 @@ import org.apache.velocity.VelocityContext; import org.traccar.Context; import org.traccar.model.Device; import org.traccar.model.Event; +import org.traccar.model.Geofence; +import org.traccar.model.Maintenance; import org.traccar.model.Position; import org.traccar.model.User; import org.traccar.reports.ReportUtils; +import org.traccar.session.cache.CacheManager; public final class NotificationFormatter { private NotificationFormatter() { } - public static VelocityContext prepareContext(long userId, Event event, Position position) { + public static NotificationMessage formatMessage( + CacheManager cacheManager, long userId, Event event, Position position, String templatePath) { - User user = Context.getPermissionsManager().getUser(userId); - Device device = Context.getIdentityManager().getById(event.getDeviceId()); + User user = cacheManager.getObject(User.class, userId); + Device device = cacheManager.getObject(Device.class, event.getDeviceId()); VelocityContext velocityContext = TextTemplateFormatter.prepareContext(user); @@ -45,21 +49,16 @@ public final class NotificationFormatter { velocityContext.put("volumeUnit", ReportUtils.getVolumeUnit(userId)); } if (event.getGeofenceId() != 0) { - velocityContext.put("geofence", Context.getGeofenceManager().getById(event.getGeofenceId())); + velocityContext.put("geofence", cacheManager.getObject(Geofence.class, event.getGeofenceId())); } if (event.getMaintenanceId() != 0) { - velocityContext.put("maintenance", Context.getMaintenancesManager().getById(event.getMaintenanceId())); + velocityContext.put("maintenance", cacheManager.getObject(Maintenance.class, event.getMaintenanceId())); } String driverUniqueId = event.getString(Position.KEY_DRIVER_UNIQUE_ID); if (driverUniqueId != null) { velocityContext.put("driver", Context.getDriversManager().getDriverByUniqueId(driverUniqueId)); } - return velocityContext; - } - - public static NotificationMessage formatMessage(long userId, Event event, Position position, String templatePath) { - VelocityContext velocityContext = prepareContext(userId, event, position); return TextTemplateFormatter.formatMessage(velocityContext, event.getType(), templatePath); } diff --git a/src/main/java/org/traccar/notificators/NotificatorFirebase.java b/src/main/java/org/traccar/notificators/NotificatorFirebase.java index f91ec25a0..bcce9a4d8 100644 --- a/src/main/java/org/traccar/notificators/NotificatorFirebase.java +++ b/src/main/java/org/traccar/notificators/NotificatorFirebase.java @@ -20,12 +20,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.Main; import org.traccar.config.Keys; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.model.User; import org.traccar.notification.NotificationMessage; import org.traccar.notification.NotificationFormatter; +import org.traccar.session.cache.CacheManager; import javax.ws.rs.client.Entity; import javax.ws.rs.client.InvocationCallback; @@ -69,7 +71,8 @@ public class NotificatorFirebase extends Notificator { final User user = Context.getPermissionsManager().getUser(userId); if (user.getAttributes().containsKey("notificationTokens")) { - NotificationMessage shortMessage = NotificationFormatter.formatMessage(userId, event, position, "short"); + NotificationMessage shortMessage = NotificationFormatter.formatMessage( + Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); Notification notification = new Notification(); notification.title = shortMessage.getSubject(); diff --git a/src/main/java/org/traccar/notificators/NotificatorMail.java b/src/main/java/org/traccar/notificators/NotificatorMail.java index 9b5637ed8..eb7f399eb 100644 --- a/src/main/java/org/traccar/notificators/NotificatorMail.java +++ b/src/main/java/org/traccar/notificators/NotificatorMail.java @@ -17,11 +17,13 @@ package org.traccar.notificators; import org.traccar.Context; +import org.traccar.Main; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.notification.NotificationMessage; import org.traccar.notification.MessageException; import org.traccar.notification.NotificationFormatter; +import org.traccar.session.cache.CacheManager; import javax.mail.MessagingException; @@ -30,7 +32,8 @@ public final class NotificatorMail extends Notificator { @Override public void sendSync(long userId, Event event, Position position) throws MessageException { try { - NotificationMessage fullMessage = NotificationFormatter.formatMessage(userId, event, position, "full"); + NotificationMessage fullMessage = NotificationFormatter.formatMessage( + Main.getInjector().getInstance(CacheManager.class), userId, event, position, "full"); Context.getMailManager().sendMessage(userId, fullMessage.getSubject(), fullMessage.getBody()); } catch (MessagingException e) { throw new MessageException(e); diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 456c2fe4f..73fad9bd2 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -19,12 +19,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.Main; import org.traccar.config.Keys; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.model.User; import org.traccar.notification.NotificationFormatter; import org.traccar.notification.NotificationMessage; +import org.traccar.session.cache.CacheManager; import javax.ws.rs.client.Entity; import javax.ws.rs.client.InvocationCallback; @@ -77,7 +79,8 @@ public class NotificatorPushover extends Notificator { return; } - NotificationMessage shortMessage = NotificationFormatter.formatMessage(userId, event, position, "short"); + NotificationMessage shortMessage = NotificationFormatter.formatMessage( + Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); Message message = new Message(); message.token = token; diff --git a/src/main/java/org/traccar/notificators/NotificatorSms.java b/src/main/java/org/traccar/notificators/NotificatorSms.java index fb817b112..09eb65b0c 100644 --- a/src/main/java/org/traccar/notificators/NotificatorSms.java +++ b/src/main/java/org/traccar/notificators/NotificatorSms.java @@ -25,6 +25,7 @@ import org.traccar.model.User; import org.traccar.notification.MessageException; import org.traccar.notification.NotificationFormatter; import org.traccar.notification.NotificationMessage; +import org.traccar.session.cache.CacheManager; public final class NotificatorSms extends Notificator { @@ -32,7 +33,8 @@ public final class NotificatorSms extends Notificator { public void sendAsync(long userId, Event event, Position position) { final User user = Context.getPermissionsManager().getUser(userId); if (user.getPhone() != null) { - NotificationMessage shortMessage = NotificationFormatter.formatMessage(userId, event, position, "short"); + NotificationMessage shortMessage = NotificationFormatter.formatMessage( + Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); Main.getInjector().getInstance(StatisticsManager.class).registerSms(); Context.getSmsManager().sendMessageAsync(user.getPhone(), shortMessage.getBody(), false); @@ -43,7 +45,8 @@ public final class NotificatorSms extends Notificator { public void sendSync(long userId, Event event, Position position) throws MessageException, InterruptedException { final User user = Context.getPermissionsManager().getUser(userId); if (user.getPhone() != null) { - NotificationMessage shortMessage = NotificationFormatter.formatMessage(userId, event, position, "short"); + NotificationMessage shortMessage = NotificationFormatter.formatMessage( + Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); Main.getInjector().getInstance(StatisticsManager.class).registerSms(); Context.getSmsManager().sendMessageSync(user.getPhone(), shortMessage.getBody(), false); diff --git a/src/main/java/org/traccar/notificators/NotificatorTelegram.java b/src/main/java/org/traccar/notificators/NotificatorTelegram.java index 70148110c..a8e69e77d 100644 --- a/src/main/java/org/traccar/notificators/NotificatorTelegram.java +++ b/src/main/java/org/traccar/notificators/NotificatorTelegram.java @@ -20,12 +20,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.Context; +import org.traccar.Main; import org.traccar.model.User; import org.traccar.config.Keys; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.notification.NotificationFormatter; import org.traccar.notification.NotificationMessage; +import org.traccar.session.cache.CacheManager; import javax.ws.rs.client.Entity; import javax.ws.rs.client.InvocationCallback; @@ -99,7 +101,8 @@ public class NotificatorTelegram extends Notificator { @Override public void sendSync(long userId, Event event, Position position) { User user = Context.getPermissionsManager().getUser(userId); - NotificationMessage shortMessage = NotificationFormatter.formatMessage(userId, event, position, "short"); + NotificationMessage shortMessage = NotificationFormatter.formatMessage( + Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); TextMessage message = new TextMessage(); message.chatId = user.getString("telegramChatId"); diff --git a/src/main/java/org/traccar/reports/Events.java b/src/main/java/org/traccar/reports/Events.java index e4b905702..818142b16 100644 --- a/src/main/java/org/traccar/reports/Events.java +++ b/src/main/java/org/traccar/reports/Events.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2016 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +34,7 @@ import org.traccar.model.Geofence; import org.traccar.model.Group; import org.traccar.model.Maintenance; import org.traccar.reports.model.DeviceReport; +import org.traccar.storage.Storage; import org.traccar.storage.StorageException; public final class Events { @@ -41,7 +42,9 @@ public final class Events { private Events() { } - public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, + public static Collection getObjects( + Storage storage, long userId, + Collection deviceIds, Collection groupIds, Collection types, Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); ArrayList result = new ArrayList<>(); @@ -53,9 +56,9 @@ public final class Events { if (all || types.contains(event.getType())) { long geofenceId = event.getGeofenceId(); long maintenanceId = event.getMaintenanceId(); - if ((geofenceId == 0 || Context.getGeofenceManager().checkItemPermission(userId, geofenceId)) + if ((geofenceId == 0 || ReportUtils.getObject(storage, userId, Geofence.class, geofenceId) != null) && (maintenanceId == 0 - || Context.getMaintenancesManager().checkItemPermission(userId, maintenanceId))) { + || ReportUtils.getObject(storage, userId, Maintenance.class, maintenanceId) != null)) { result.add(event); } } @@ -64,8 +67,9 @@ public final class Events { return result; } - public static void getExcel(OutputStream outputStream, - long userId, Collection deviceIds, Collection groupIds, + public static void getExcel( + OutputStream outputStream, Storage storage, long userId, + Collection deviceIds, Collection groupIds, Collection types, Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); ArrayList devicesEvents = new ArrayList<>(); @@ -82,20 +86,18 @@ public final class Events { long geofenceId = event.getGeofenceId(); long maintenanceId = event.getMaintenanceId(); if (geofenceId != 0) { - if (Context.getGeofenceManager().checkItemPermission(userId, geofenceId)) { - Geofence geofence = Context.getGeofenceManager().getById(geofenceId); - if (geofence != null) { - geofenceNames.put(geofenceId, geofence.getName()); - } + Geofence geofence = ReportUtils.getObject( + storage, userId, Geofence.class, geofenceId); + if (geofence != null) { + geofenceNames.put(geofenceId, geofence.getName()); } else { iterator.remove(); } } else if (maintenanceId != 0) { - if (Context.getMaintenancesManager().checkItemPermission(userId, maintenanceId)) { - Maintenance maintenance = Context.getMaintenancesManager().getById(maintenanceId); - if (maintenance != null) { - maintenanceNames.put(maintenanceId, maintenance.getName()); - } + Maintenance maintenance = ReportUtils.getObject( + storage, userId, Maintenance.class, maintenanceId); + if (maintenance != null) { + maintenanceNames.put(maintenanceId, maintenance.getName()); } else { iterator.remove(); } diff --git a/src/main/java/org/traccar/reports/ReportUtils.java b/src/main/java/org/traccar/reports/ReportUtils.java index 413d49ad7..98a80a23e 100644 --- a/src/main/java/org/traccar/reports/ReportUtils.java +++ b/src/main/java/org/traccar/reports/ReportUtils.java @@ -31,6 +31,8 @@ import org.traccar.database.DeviceManager; import org.traccar.database.IdentityManager; import org.traccar.handler.events.MotionEventHandler; import org.traccar.helper.UnitsConverter; +import org.traccar.model.BaseModel; +import org.traccar.model.User; import org.traccar.session.DeviceState; import org.traccar.model.Driver; import org.traccar.model.Event; @@ -39,6 +41,11 @@ import org.traccar.reports.model.BaseReport; import org.traccar.reports.model.StopReport; import org.traccar.reports.model.TripReport; import org.traccar.reports.model.TripsConfig; +import org.traccar.storage.Storage; +import org.traccar.storage.StorageException; +import org.traccar.storage.query.Columns; +import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Request; import java.io.IOException; import java.io.InputStream; @@ -59,6 +66,15 @@ public final class ReportUtils { private ReportUtils() { } + public static T getObject( + Storage storage, long userId, Class clazz, long objectId) throws StorageException, SecurityException { + return storage.getObject(clazz, new Request( + new Columns.Include("id"), + new Condition.And( + new Condition.Equals("id", "id", objectId), + new Condition.Permission(User.class, userId, clazz)))); + } + public static void checkPeriodLimit(Date from, Date to) { long limit = Context.getConfig().getLong(Keys.REPORT_PERIOD_LIMIT) * 1000; if (limit > 0 && to.getTime() - from.getTime() > limit) { -- cgit v1.2.3 From 94a2a94330d82fa1c1960b8783e5061c188196e3 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 4 Jun 2022 10:55:50 -0700 Subject: Rename report models --- .../org/traccar/api/resource/ReportResource.java | 12 +- src/main/java/org/traccar/reports/Events.java | 6 +- src/main/java/org/traccar/reports/Route.java | 6 +- src/main/java/org/traccar/reports/Stops.java | 18 +-- src/main/java/org/traccar/reports/Summary.java | 22 ++-- src/main/java/org/traccar/reports/Trips.java | 20 ++-- .../org/traccar/reports/common/ReportUtils.java | 22 ++-- .../java/org/traccar/reports/model/BaseReport.java | 126 -------------------- .../org/traccar/reports/model/BaseReportItem.java | 126 ++++++++++++++++++++ .../org/traccar/reports/model/DeviceReport.java | 55 --------- .../traccar/reports/model/DeviceReportSection.java | 55 +++++++++ .../java/org/traccar/reports/model/StopReport.java | 80 ------------- .../org/traccar/reports/model/StopReportItem.java | 80 +++++++++++++ .../org/traccar/reports/model/SummaryReport.java | 30 ----- .../traccar/reports/model/SummaryReportItem.java | 30 +++++ .../java/org/traccar/reports/model/TripReport.java | 130 --------------------- .../org/traccar/reports/model/TripReportItem.java | 130 +++++++++++++++++++++ .../java/org/traccar/reports/ReportUtilsTest.java | 82 ++++++------- 18 files changed, 515 insertions(+), 515 deletions(-) delete mode 100644 src/main/java/org/traccar/reports/model/BaseReport.java create mode 100644 src/main/java/org/traccar/reports/model/BaseReportItem.java delete mode 100644 src/main/java/org/traccar/reports/model/DeviceReport.java create mode 100644 src/main/java/org/traccar/reports/model/DeviceReportSection.java delete mode 100644 src/main/java/org/traccar/reports/model/StopReport.java create mode 100644 src/main/java/org/traccar/reports/model/StopReportItem.java delete mode 100644 src/main/java/org/traccar/reports/model/SummaryReport.java create mode 100644 src/main/java/org/traccar/reports/model/SummaryReportItem.java delete mode 100644 src/main/java/org/traccar/reports/model/TripReport.java create mode 100644 src/main/java/org/traccar/reports/model/TripReportItem.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index a7bbe1067..5346df31b 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -46,9 +46,9 @@ import org.traccar.model.UserRestrictions; import org.traccar.reports.Events; import org.traccar.reports.Summary; import org.traccar.reports.Trips; -import org.traccar.reports.model.StopReport; -import org.traccar.reports.model.SummaryReport; -import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.StopReportItem; +import org.traccar.reports.model.SummaryReportItem; +import org.traccar.reports.model.TripReportItem; import org.traccar.reports.Route; import org.traccar.reports.Stops; import org.traccar.storage.StorageException; @@ -147,7 +147,7 @@ public class ReportResource extends BaseResource { @Path("summary") @GET - public Collection getSummary( + public Collection getSummary( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily) throws StorageException { @@ -174,7 +174,7 @@ public class ReportResource extends BaseResource { @Path("trips") @GET @Produces(MediaType.APPLICATION_JSON) - public Collection getTrips( + public Collection getTrips( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); @@ -199,7 +199,7 @@ public class ReportResource extends BaseResource { @Path("stops") @GET @Produces(MediaType.APPLICATION_JSON) - public Collection getStops( + public Collection getStops( @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); diff --git a/src/main/java/org/traccar/reports/Events.java b/src/main/java/org/traccar/reports/Events.java index c5db305ed..130fba724 100644 --- a/src/main/java/org/traccar/reports/Events.java +++ b/src/main/java/org/traccar/reports/Events.java @@ -34,7 +34,7 @@ import org.traccar.model.Geofence; import org.traccar.model.Group; import org.traccar.model.Maintenance; import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReport; +import org.traccar.reports.model.DeviceReportSection; import org.traccar.storage.Storage; import org.traccar.storage.StorageException; @@ -73,7 +73,7 @@ public final class Events { Collection deviceIds, Collection groupIds, Collection types, Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesEvents = new ArrayList<>(); + ArrayList devicesEvents = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); HashMap geofenceNames = new HashMap<>(); HashMap maintenanceNames = new HashMap<>(); @@ -107,7 +107,7 @@ public final class Events { iterator.remove(); } } - DeviceReport deviceEvents = new DeviceReport(); + DeviceReportSection deviceEvents = new DeviceReportSection(); Device device = Context.getIdentityManager().getById(deviceId); deviceEvents.setDeviceName(device.getName()); sheetNames.add(WorkbookUtil.createSafeSheetName(deviceEvents.getDeviceName())); diff --git a/src/main/java/org/traccar/reports/Route.java b/src/main/java/org/traccar/reports/Route.java index d7745157a..5b8629aad 100644 --- a/src/main/java/org/traccar/reports/Route.java +++ b/src/main/java/org/traccar/reports/Route.java @@ -30,7 +30,7 @@ import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.model.Position; import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReport; +import org.traccar.reports.model.DeviceReportSection; import org.traccar.storage.StorageException; public final class Route { @@ -53,13 +53,13 @@ public final class Route { long userId, Collection deviceIds, Collection groupIds, Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesRoutes = new ArrayList<>(); + ArrayList devicesRoutes = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); Collection positions = Context.getDataManager() .getPositions(deviceId, from, to); - DeviceReport deviceRoutes = new DeviceReport(); + DeviceReportSection deviceRoutes = new DeviceReportSection(); Device device = Context.getIdentityManager().getById(deviceId); deviceRoutes.setDeviceName(device.getName()); sheetNames.add(WorkbookUtil.createSafeSheetName(deviceRoutes.getDeviceName())); diff --git a/src/main/java/org/traccar/reports/Stops.java b/src/main/java/org/traccar/reports/Stops.java index 82eb62f66..e688d53da 100644 --- a/src/main/java/org/traccar/reports/Stops.java +++ b/src/main/java/org/traccar/reports/Stops.java @@ -33,8 +33,8 @@ import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReport; -import org.traccar.reports.model.StopReport; +import org.traccar.reports.model.DeviceReportSection; +import org.traccar.reports.model.StopReportItem; import org.traccar.storage.StorageException; public final class Stops { @@ -42,7 +42,7 @@ public final class Stops { private Stops() { } - private static Collection detectStops(long deviceId, Date from, Date to) throws StorageException { + private static Collection detectStops(long deviceId, Date from, Date to) throws StorageException { boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); @@ -51,14 +51,14 @@ public final class Stops { return ReportUtils.detectTripsAndStops( identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), - Context.getTripsConfig(), ignoreOdometer, StopReport.class); + Context.getTripsConfig(), ignoreOdometer, StopReportItem.class); } - public static Collection getObjects( + public static Collection getObjects( long userId, Collection deviceIds, Collection groupIds, Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); + ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); result.addAll(detectStops(deviceId, from, to)); @@ -70,12 +70,12 @@ public final class Stops { OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesStops = new ArrayList<>(); + ArrayList devicesStops = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection stops = detectStops(deviceId, from, to); - DeviceReport deviceStops = new DeviceReport(); + Collection stops = detectStops(deviceId, from, to); + DeviceReportSection deviceStops = new DeviceReportSection(); Device device = Context.getIdentityManager().getById(deviceId); deviceStops.setDeviceName(device.getName()); sheetNames.add(WorkbookUtil.createSafeSheetName(deviceStops.getDeviceName())); diff --git a/src/main/java/org/traccar/reports/Summary.java b/src/main/java/org/traccar/reports/Summary.java index 20d80a9f5..30c4cb057 100644 --- a/src/main/java/org/traccar/reports/Summary.java +++ b/src/main/java/org/traccar/reports/Summary.java @@ -30,7 +30,7 @@ import org.traccar.Context; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.SummaryReport; +import org.traccar.reports.model.SummaryReportItem; import org.traccar.storage.StorageException; public final class Summary { @@ -38,8 +38,8 @@ public final class Summary { private Summary() { } - private static SummaryReport calculateSummaryResult(long deviceId, Collection positions) { - SummaryReport result = new SummaryReport(); + private static SummaryReportItem calculateSummaryResult(long deviceId, Collection positions) { + SummaryReportItem result = new SummaryReportItem(); result.setDeviceId(deviceId); result.setDeviceName(Context.getIdentityManager().getById(deviceId).getName()); if (positions != null && !positions.isEmpty()) { @@ -97,12 +97,12 @@ public final class Summary { return calendar.get(Calendar.DAY_OF_MONTH); } - private static Collection calculateSummaryResults( + private static Collection calculateSummaryResults( long userId, long deviceId, Date from, Date to, boolean daily) throws StorageException { ArrayList positions = new ArrayList<>(Context.getDataManager().getPositions(deviceId, from, to)); - ArrayList results = new ArrayList<>(); + ArrayList results = new ArrayList<>(); if (daily && !positions.isEmpty()) { int startIndex = 0; int startDay = getDay(userId, positions.iterator().next().getFixTime()); @@ -122,14 +122,14 @@ public final class Summary { return results; } - public static Collection getObjects(long userId, Collection deviceIds, - Collection groupIds, Date from, Date to, boolean daily) throws StorageException { + public static Collection getObjects(long userId, Collection deviceIds, + Collection groupIds, Date from, Date to, boolean daily) throws StorageException { ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); + ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection deviceResults = calculateSummaryResults(userId, deviceId, from, to, daily); - for (SummaryReport summaryReport : deviceResults) { + Collection deviceResults = calculateSummaryResults(userId, deviceId, from, to, daily); + for (SummaryReportItem summaryReport : deviceResults) { if (summaryReport.getStartTime() != null && summaryReport.getEndTime() != null) { result.add(summaryReport); } @@ -142,7 +142,7 @@ public final class Summary { long userId, Collection deviceIds, Collection groupIds, Date from, Date to, boolean daily) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); - Collection summaries = getObjects(userId, deviceIds, groupIds, from, to, daily); + Collection summaries = getObjects(userId, deviceIds, groupIds, from, to, daily); String templatePath = Context.getConfig().getString("report.templatesPath", "templates/export/"); try (InputStream inputStream = new FileInputStream(templatePath + "/summary.xlsx")) { diff --git a/src/main/java/org/traccar/reports/Trips.java b/src/main/java/org/traccar/reports/Trips.java index 58131debb..74e24cf2f 100644 --- a/src/main/java/org/traccar/reports/Trips.java +++ b/src/main/java/org/traccar/reports/Trips.java @@ -32,8 +32,8 @@ import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Group; import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReport; -import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.DeviceReportSection; +import org.traccar.reports.model.TripReportItem; import org.traccar.storage.StorageException; public final class Trips { @@ -41,7 +41,7 @@ public final class Trips { private Trips() { } - private static Collection detectTrips(long deviceId, Date from, Date to) throws StorageException { + private static Collection detectTrips(long deviceId, Date from, Date to) throws StorageException { boolean ignoreOdometer = Context.getDeviceManager() .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); @@ -50,13 +50,13 @@ public final class Trips { return ReportUtils.detectTripsAndStops( identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), - Context.getTripsConfig(), ignoreOdometer, TripReport.class); + Context.getTripsConfig(), ignoreOdometer, TripReportItem.class); } - public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException { + public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException { ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); + ArrayList result = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); result.addAll(detectTrips(deviceId, from, to)); @@ -68,12 +68,12 @@ public final class Trips { long userId, Collection deviceIds, Collection groupIds, Date from, Date to) throws StorageException, IOException { ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesTrips = new ArrayList<>(); + ArrayList devicesTrips = new ArrayList<>(); ArrayList sheetNames = new ArrayList<>(); for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection trips = detectTrips(deviceId, from, to); - DeviceReport deviceTrips = new DeviceReport(); + Collection trips = detectTrips(deviceId, from, to); + DeviceReportSection deviceTrips = new DeviceReportSection(); Device device = Context.getIdentityManager().getById(deviceId); deviceTrips.setDeviceName(device.getName()); sheetNames.add(WorkbookUtil.createSafeSheetName(deviceTrips.getDeviceName())); diff --git a/src/main/java/org/traccar/reports/common/ReportUtils.java b/src/main/java/org/traccar/reports/common/ReportUtils.java index 27972b453..b56b58a58 100644 --- a/src/main/java/org/traccar/reports/common/ReportUtils.java +++ b/src/main/java/org/traccar/reports/common/ReportUtils.java @@ -37,9 +37,9 @@ import org.traccar.session.DeviceState; import org.traccar.model.Driver; import org.traccar.model.Event; import org.traccar.model.Position; -import org.traccar.reports.model.BaseReport; -import org.traccar.reports.model.StopReport; -import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.BaseReportItem; +import org.traccar.reports.model.StopReportItem; +import org.traccar.reports.model.TripReportItem; import org.traccar.storage.Storage; import org.traccar.storage.StorageException; import org.traccar.storage.query.Columns; @@ -185,7 +185,7 @@ public final class ReportUtils { transformer.write(); } - private static TripReport calculateTrip( + private static TripReportItem calculateTrip( IdentityManager identityManager, ArrayList positions, int startIndex, int endIndex, boolean ignoreOdometer) { @@ -200,7 +200,7 @@ public final class ReportUtils { } } - TripReport trip = new TripReport(); + TripReportItem trip = new TripReportItem(); long tripDuration = endTrip.getFixTime().getTime() - startTrip.getFixTime().getTime(); long deviceId = startTrip.getDeviceId(); @@ -253,14 +253,14 @@ public final class ReportUtils { return trip; } - private static StopReport calculateStop( + private static StopReportItem calculateStop( IdentityManager identityManager, ArrayList positions, int startIndex, int endIndex, boolean ignoreOdometer) { Position startStop = positions.get(startIndex); Position endStop = positions.get(endIndex); - StopReport stop = new StopReport(); + StopReportItem stop = new StopReportItem(); long deviceId = startStop.getDeviceId(); stop.setDeviceId(deviceId); @@ -302,11 +302,11 @@ public final class ReportUtils { } - private static T calculateTripOrStop( + private static T calculateTripOrStop( IdentityManager identityManager, ArrayList positions, int startIndex, int endIndex, boolean ignoreOdometer, Class reportClass) { - if (reportClass.equals(TripReport.class)) { + if (reportClass.equals(TripReportItem.class)) { return (T) calculateTrip(identityManager, positions, startIndex, endIndex, ignoreOdometer); } else { return (T) calculateStop(identityManager, positions, startIndex, endIndex, ignoreOdometer); @@ -333,7 +333,7 @@ public final class ReportUtils { } } - public static Collection detectTripsAndStops( + public static Collection detectTripsAndStops( IdentityManager identityManager, DeviceManager deviceManager, Collection positionCollection, TripsConfig tripsConfig, boolean ignoreOdometer, Class reportClass) { @@ -342,7 +342,7 @@ public final class ReportUtils { ArrayList positions = new ArrayList<>(positionCollection); if (!positions.isEmpty()) { - boolean trips = reportClass.equals(TripReport.class); + boolean trips = reportClass.equals(TripReportItem.class); MotionEventHandler motionHandler = new MotionEventHandler(identityManager, deviceManager, tripsConfig); DeviceState deviceState = new DeviceState(); deviceState.setMotionState(isMoving(positions, 0, tripsConfig)); diff --git a/src/main/java/org/traccar/reports/model/BaseReport.java b/src/main/java/org/traccar/reports/model/BaseReport.java deleted file mode 100644 index 928c0557d..000000000 --- a/src/main/java/org/traccar/reports/model/BaseReport.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) - * Copyright 2016 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.reports.model; - -import java.util.Date; - -public class BaseReport { - - private long deviceId; - - public long getDeviceId() { - return deviceId; - } - - public void setDeviceId(long deviceId) { - this.deviceId = deviceId; - } - - private String deviceName; - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - private double distance; - - public double getDistance() { - return distance; - } - - public void setDistance(double distance) { - this.distance = distance; - } - - public void addDistance(double distance) { - this.distance += distance; - } - - private double averageSpeed; - - public double getAverageSpeed() { - return averageSpeed; - } - - public void setAverageSpeed(double averageSpeed) { - this.averageSpeed = averageSpeed; - } - - private double maxSpeed; - - public double getMaxSpeed() { - return maxSpeed; - } - - public void setMaxSpeed(double maxSpeed) { - this.maxSpeed = maxSpeed; - } - - private double spentFuel; - - public double getSpentFuel() { - return spentFuel; - } - - public void setSpentFuel(double spentFuel) { - this.spentFuel = spentFuel; - } - - private double startOdometer; - - public double getStartOdometer() { - return startOdometer; - } - - public void setStartOdometer(double startOdometer) { - this.startOdometer = startOdometer; - } - private double endOdometer; - - public double getEndOdometer() { - return endOdometer; - } - - public void setEndOdometer(double endOdometer) { - this.endOdometer = endOdometer; - } - - private Date startTime; - - public Date getStartTime() { - return startTime; - } - - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - private Date endTime; - - public Date getEndTime() { - return endTime; - } - - public void setEndTime(Date endTime) { - this.endTime = endTime; - } - -} diff --git a/src/main/java/org/traccar/reports/model/BaseReportItem.java b/src/main/java/org/traccar/reports/model/BaseReportItem.java new file mode 100644 index 000000000..6e270dfe3 --- /dev/null +++ b/src/main/java/org/traccar/reports/model/BaseReportItem.java @@ -0,0 +1,126 @@ +/* + * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2016 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.reports.model; + +import java.util.Date; + +public class BaseReportItem { + + private long deviceId; + + public long getDeviceId() { + return deviceId; + } + + public void setDeviceId(long deviceId) { + this.deviceId = deviceId; + } + + private String deviceName; + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + private double distance; + + public double getDistance() { + return distance; + } + + public void setDistance(double distance) { + this.distance = distance; + } + + public void addDistance(double distance) { + this.distance += distance; + } + + private double averageSpeed; + + public double getAverageSpeed() { + return averageSpeed; + } + + public void setAverageSpeed(double averageSpeed) { + this.averageSpeed = averageSpeed; + } + + private double maxSpeed; + + public double getMaxSpeed() { + return maxSpeed; + } + + public void setMaxSpeed(double maxSpeed) { + this.maxSpeed = maxSpeed; + } + + private double spentFuel; + + public double getSpentFuel() { + return spentFuel; + } + + public void setSpentFuel(double spentFuel) { + this.spentFuel = spentFuel; + } + + private double startOdometer; + + public double getStartOdometer() { + return startOdometer; + } + + public void setStartOdometer(double startOdometer) { + this.startOdometer = startOdometer; + } + private double endOdometer; + + public double getEndOdometer() { + return endOdometer; + } + + public void setEndOdometer(double endOdometer) { + this.endOdometer = endOdometer; + } + + private Date startTime; + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + private Date endTime; + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + +} diff --git a/src/main/java/org/traccar/reports/model/DeviceReport.java b/src/main/java/org/traccar/reports/model/DeviceReport.java deleted file mode 100644 index 932753d15..000000000 --- a/src/main/java/org/traccar/reports/model/DeviceReport.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 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.reports.model; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class DeviceReport { - - private String deviceName; - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - private String groupName = ""; - - public String getGroupName() { - return groupName; - } - - public void setGroupName(String groupName) { - this.groupName = groupName; - } - - private List objects; - - public Collection getObjects() { - return objects; - } - - public void setObjects(Collection objects) { - this.objects = new ArrayList<>(objects); - } - -} diff --git a/src/main/java/org/traccar/reports/model/DeviceReportSection.java b/src/main/java/org/traccar/reports/model/DeviceReportSection.java new file mode 100644 index 000000000..ffc4d774f --- /dev/null +++ b/src/main/java/org/traccar/reports/model/DeviceReportSection.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 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.reports.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class DeviceReportSection { + + private String deviceName; + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + private String groupName = ""; + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + private List objects; + + public Collection getObjects() { + return objects; + } + + public void setObjects(Collection objects) { + this.objects = new ArrayList<>(objects); + } + +} diff --git a/src/main/java/org/traccar/reports/model/StopReport.java b/src/main/java/org/traccar/reports/model/StopReport.java deleted file mode 100644 index e20f2c503..000000000 --- a/src/main/java/org/traccar/reports/model/StopReport.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2017 - 2020 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.reports.model; - -public class StopReport extends BaseReport { - - private long positionId; - - public long getPositionId() { - return positionId; - } - - public void setPositionId(long positionId) { - this.positionId = positionId; - } - - private double latitude; - - public double getLatitude() { - return latitude; - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - private double longitude; - - public double getLongitude() { - return longitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } - - private String address; - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - private long duration; - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - private long engineHours; // milliseconds - - public long getEngineHours() { - return engineHours; - } - - public void setEngineHours(long engineHours) { - this.engineHours = engineHours; - } -} diff --git a/src/main/java/org/traccar/reports/model/StopReportItem.java b/src/main/java/org/traccar/reports/model/StopReportItem.java new file mode 100644 index 000000000..3c35bdc21 --- /dev/null +++ b/src/main/java/org/traccar/reports/model/StopReportItem.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017 - 2020 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.reports.model; + +public class StopReportItem extends BaseReportItem { + + private long positionId; + + public long getPositionId() { + return positionId; + } + + public void setPositionId(long positionId) { + this.positionId = positionId; + } + + private double latitude; + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + private double longitude; + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + private String address; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + private long duration; + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + private long engineHours; // milliseconds + + public long getEngineHours() { + return engineHours; + } + + public void setEngineHours(long engineHours) { + this.engineHours = engineHours; + } +} diff --git a/src/main/java/org/traccar/reports/model/SummaryReport.java b/src/main/java/org/traccar/reports/model/SummaryReport.java deleted file mode 100644 index 886f8b9e2..000000000 --- a/src/main/java/org/traccar/reports/model/SummaryReport.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) - * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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.reports.model; - -public class SummaryReport extends BaseReport { - - private long engineHours; // milliseconds - - public long getEngineHours() { - return engineHours; - } - - public void setEngineHours(long engineHours) { - this.engineHours = engineHours; - } -} diff --git a/src/main/java/org/traccar/reports/model/SummaryReportItem.java b/src/main/java/org/traccar/reports/model/SummaryReportItem.java new file mode 100644 index 000000000..44a15cf1d --- /dev/null +++ b/src/main/java/org/traccar/reports/model/SummaryReportItem.java @@ -0,0 +1,30 @@ +/* + * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2017 Andrey Kunitsyn (andrey@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.reports.model; + +public class SummaryReportItem extends BaseReportItem { + + private long engineHours; // milliseconds + + public long getEngineHours() { + return engineHours; + } + + public void setEngineHours(long engineHours) { + this.engineHours = engineHours; + } +} diff --git a/src/main/java/org/traccar/reports/model/TripReport.java b/src/main/java/org/traccar/reports/model/TripReport.java deleted file mode 100644 index 151c34bd5..000000000 --- a/src/main/java/org/traccar/reports/model/TripReport.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 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.reports.model; - -public class TripReport extends BaseReport { - - private long startPositionId; - - public long getStartPositionId() { - return startPositionId; - } - - public void setStartPositionId(long startPositionId) { - this.startPositionId = startPositionId; - } - - private long endPositionId; - - public long getEndPositionId() { - return endPositionId; - } - - public void setEndPositionId(long endPositionId) { - this.endPositionId = endPositionId; - } - - private double startLat; - - public double getStartLat() { - return startLat; - } - - public void setStartLat(double startLat) { - this.startLat = startLat; - } - - private double startLon; - - public double getStartLon() { - return startLon; - } - - public void setStartLon(double startLon) { - this.startLon = startLon; - } - - private double endLat; - - public double getEndLat() { - return endLat; - } - - public void setEndLat(double endLat) { - this.endLat = endLat; - } - - private double endLon; - - public double getEndLon() { - return endLon; - } - - public void setEndLon(double endLon) { - this.endLon = endLon; - } - - private String startAddress; - - public String getStartAddress() { - return startAddress; - } - - public void setStartAddress(String address) { - this.startAddress = address; - } - - private String endAddress; - - public String getEndAddress() { - return endAddress; - } - - public void setEndAddress(String address) { - this.endAddress = address; - } - - private long duration; - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - private String driverUniqueId; - - public String getDriverUniqueId() { - return driverUniqueId; - } - - public void setDriverUniqueId(String driverUniqueId) { - this.driverUniqueId = driverUniqueId; - } - - private String driverName; - - public String getDriverName() { - return driverName; - } - - public void setDriverName(String driverName) { - this.driverName = driverName; - } -} diff --git a/src/main/java/org/traccar/reports/model/TripReportItem.java b/src/main/java/org/traccar/reports/model/TripReportItem.java new file mode 100644 index 000000000..332a34cca --- /dev/null +++ b/src/main/java/org/traccar/reports/model/TripReportItem.java @@ -0,0 +1,130 @@ +/* + * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 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.reports.model; + +public class TripReportItem extends BaseReportItem { + + private long startPositionId; + + public long getStartPositionId() { + return startPositionId; + } + + public void setStartPositionId(long startPositionId) { + this.startPositionId = startPositionId; + } + + private long endPositionId; + + public long getEndPositionId() { + return endPositionId; + } + + public void setEndPositionId(long endPositionId) { + this.endPositionId = endPositionId; + } + + private double startLat; + + public double getStartLat() { + return startLat; + } + + public void setStartLat(double startLat) { + this.startLat = startLat; + } + + private double startLon; + + public double getStartLon() { + return startLon; + } + + public void setStartLon(double startLon) { + this.startLon = startLon; + } + + private double endLat; + + public double getEndLat() { + return endLat; + } + + public void setEndLat(double endLat) { + this.endLat = endLat; + } + + private double endLon; + + public double getEndLon() { + return endLon; + } + + public void setEndLon(double endLon) { + this.endLon = endLon; + } + + private String startAddress; + + public String getStartAddress() { + return startAddress; + } + + public void setStartAddress(String address) { + this.startAddress = address; + } + + private String endAddress; + + public String getEndAddress() { + return endAddress; + } + + public void setEndAddress(String address) { + this.endAddress = address; + } + + private long duration; + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + private String driverUniqueId; + + public String getDriverUniqueId() { + return driverUniqueId; + } + + public void setDriverUniqueId(String driverUniqueId) { + this.driverUniqueId = driverUniqueId; + } + + private String driverName; + + public String getDriverName() { + return driverName; + } + + public void setDriverName(String driverName) { + this.driverName = driverName; + } +} diff --git a/src/test/java/org/traccar/reports/ReportUtilsTest.java b/src/test/java/org/traccar/reports/ReportUtilsTest.java index 247e43499..e947a9afa 100644 --- a/src/test/java/org/traccar/reports/ReportUtilsTest.java +++ b/src/test/java/org/traccar/reports/ReportUtilsTest.java @@ -6,8 +6,8 @@ import org.traccar.database.IdentityManager; import org.traccar.model.Device; import org.traccar.model.Position; import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.StopReport; -import org.traccar.reports.model.TripReport; +import org.traccar.reports.model.StopReportItem; +import org.traccar.reports.model.TripReportItem; import org.traccar.reports.common.TripsConfig; import java.text.DateFormat; @@ -93,13 +93,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 180000, 900000, false, false, 0.01); - Collection trips = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, TripReport.class); + Collection trips = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, TripReportItem.class); assertNotNull(trips); assertFalse(trips.isEmpty()); - TripReport itemTrip = trips.iterator().next(); + TripReportItem itemTrip = trips.iterator().next(); assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime()); assertEquals(date("2016-01-01 00:05:00.000"), itemTrip.getEndTime()); @@ -108,15 +108,15 @@ public class ReportUtilsTest extends BaseTest { assertEquals(10, itemTrip.getMaxSpeed(), 0.01); assertEquals(3000, itemTrip.getDistance(), 0.01); - Collection stops = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection stops = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(stops); assertFalse(stops.isEmpty()); - Iterator iterator = stops.iterator(); + Iterator iterator = stops.iterator(); - StopReport itemStop = iterator.next(); + StopReportItem itemStop = iterator.next(); assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getEndTime()); @@ -147,13 +147,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 180000, 900000, true, false, 0.01); - Collection trips = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, TripReport.class); + Collection trips = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, TripReportItem.class); assertNotNull(trips); assertFalse(trips.isEmpty()); - TripReport itemTrip = trips.iterator().next(); + TripReportItem itemTrip = trips.iterator().next(); assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime()); assertEquals(date("2016-01-01 00:05:00.000"), itemTrip.getEndTime()); @@ -163,7 +163,7 @@ public class ReportUtilsTest extends BaseTest { assertEquals(3000, itemTrip.getDistance(), 0.01); trips = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, TripReport.class); + mockIdentityManager(), null, data, tripsConfig, false, TripReportItem.class); assertNotNull(trips); assertFalse(trips.isEmpty()); @@ -177,15 +177,15 @@ public class ReportUtilsTest extends BaseTest { assertEquals(10, itemTrip.getMaxSpeed(), 0.01); assertEquals(3000, itemTrip.getDistance(), 0.01); - Collection stops = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection stops = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(stops); assertFalse(stops.isEmpty()); - Iterator iterator = stops.iterator(); + Iterator iterator = stops.iterator(); - StopReport itemStop = iterator.next(); + StopReportItem itemStop = iterator.next(); assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getEndTime()); @@ -218,13 +218,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 180000, 900000, false, false, 0.01); - Collection trips = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, TripReport.class); + Collection trips = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, TripReportItem.class); assertNotNull(trips); assertFalse(trips.isEmpty()); - TripReport itemTrip = trips.iterator().next(); + TripReportItem itemTrip = trips.iterator().next(); assertEquals(date("2016-01-01 00:02:00.000"), itemTrip.getStartTime()); assertEquals(date("2016-01-01 00:09:00.000"), itemTrip.getEndTime()); @@ -233,15 +233,15 @@ public class ReportUtilsTest extends BaseTest { assertEquals(10, itemTrip.getMaxSpeed(), 0.01); assertEquals(7000, itemTrip.getDistance(), 0.01); - Collection stops = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection stops = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(stops); assertFalse(stops.isEmpty()); - Iterator iterator = stops.iterator(); + Iterator iterator = stops.iterator(); - StopReport itemStop = iterator.next(); + StopReportItem itemStop = iterator.next(); assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getEndTime()); @@ -268,13 +268,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01); - Collection result = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection result = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(result); assertFalse(result.isEmpty()); - StopReport itemStop = result.iterator().next(); + StopReportItem itemStop = result.iterator().next(); assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:05:00.000"), itemStop.getEndTime()); @@ -295,13 +295,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01); - Collection result = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection result = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(result); assertFalse(result.isEmpty()); - StopReport itemStop = result.iterator().next(); + StopReportItem itemStop = result.iterator().next(); assertEquals(date("2016-01-01 00:00:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:04:00.000"), itemStop.getEndTime()); @@ -322,13 +322,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01); - Collection result = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection result = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(result); assertFalse(result.isEmpty()); - StopReport itemStop = result.iterator().next(); + StopReportItem itemStop = result.iterator().next(); assertEquals(date("2016-01-01 00:02:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:05:00.000"), itemStop.getEndTime()); @@ -349,8 +349,8 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 300000, 200000, 900000, false, false, 0.01); - Collection result = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection result = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(result); assertTrue(result.isEmpty()); @@ -372,13 +372,13 @@ public class ReportUtilsTest extends BaseTest { TripsConfig tripsConfig = new TripsConfig(500, 200000, 200000, 900000, false, false, 0.01); - Collection trips = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, TripReport.class); + Collection trips = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, TripReportItem.class); assertNotNull(trips); assertFalse(trips.isEmpty()); - TripReport itemTrip = trips.iterator().next(); + TripReportItem itemTrip = trips.iterator().next(); assertEquals(date("2016-01-01 00:00:00.000"), itemTrip.getStartTime()); assertEquals(date("2016-01-01 00:04:00.000"), itemTrip.getEndTime()); @@ -387,13 +387,13 @@ public class ReportUtilsTest extends BaseTest { assertEquals(7, itemTrip.getMaxSpeed(), 0.01); assertEquals(600, itemTrip.getDistance(), 0.01); - Collection stops = ReportUtils.detectTripsAndStops( - mockIdentityManager(), null, data, tripsConfig, false, StopReport.class); + Collection stops = ReportUtils.detectTripsAndStops( + mockIdentityManager(), null, data, tripsConfig, false, StopReportItem.class); assertNotNull(stops); assertFalse(stops.isEmpty()); - StopReport itemStop = stops.iterator().next(); + StopReportItem itemStop = stops.iterator().next(); assertEquals(date("2016-01-01 00:04:00.000"), itemStop.getStartTime()); assertEquals(date("2016-01-01 00:24:00.000"), itemStop.getEndTime()); -- cgit v1.2.3 From 31c4ad41f4d91dec3c98af06614e9518d3689a14 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 4 Jun 2022 11:01:01 -0700 Subject: Inject report providers --- .../org/traccar/api/resource/ReportResource.java | 46 ++++-- src/main/java/org/traccar/reports/Events.java | 136 ------------------ .../org/traccar/reports/EventsReportProvider.java | 133 +++++++++++++++++ src/main/java/org/traccar/reports/Route.java | 86 ----------- .../org/traccar/reports/RouteReportProvider.java | 83 +++++++++++ src/main/java/org/traccar/reports/Stops.java | 103 -------------- .../org/traccar/reports/StopsReportProvider.java | 100 +++++++++++++ src/main/java/org/traccar/reports/Summary.java | 157 --------------------- .../org/traccar/reports/SummaryReportProvider.java | 155 ++++++++++++++++++++ src/main/java/org/traccar/reports/Trips.java | 101 ------------- .../org/traccar/reports/TripsReportProvider.java | 98 +++++++++++++ 11 files changed, 600 insertions(+), 598 deletions(-) delete mode 100644 src/main/java/org/traccar/reports/Events.java create mode 100644 src/main/java/org/traccar/reports/EventsReportProvider.java delete mode 100644 src/main/java/org/traccar/reports/Route.java create mode 100644 src/main/java/org/traccar/reports/RouteReportProvider.java delete mode 100644 src/main/java/org/traccar/reports/Stops.java create mode 100644 src/main/java/org/traccar/reports/StopsReportProvider.java delete mode 100644 src/main/java/org/traccar/reports/Summary.java create mode 100644 src/main/java/org/traccar/reports/SummaryReportProvider.java delete mode 100644 src/main/java/org/traccar/reports/Trips.java create mode 100644 src/main/java/org/traccar/reports/TripsReportProvider.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 5346df31b..38eb52685 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -23,6 +23,7 @@ import java.util.Date; import java.util.List; import javax.activation.DataHandler; +import javax.inject.Inject; import javax.mail.MessagingException; import javax.mail.internet.MimeBodyPart; import javax.mail.util.ByteArrayDataSource; @@ -43,14 +44,14 @@ import org.traccar.helper.LogAction; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.model.UserRestrictions; -import org.traccar.reports.Events; -import org.traccar.reports.Summary; -import org.traccar.reports.Trips; +import org.traccar.reports.EventsReportProvider; +import org.traccar.reports.SummaryReportProvider; +import org.traccar.reports.TripsReportProvider; import org.traccar.reports.model.StopReportItem; import org.traccar.reports.model.SummaryReportItem; import org.traccar.reports.model.TripReportItem; -import org.traccar.reports.Route; -import org.traccar.reports.Stops; +import org.traccar.reports.RouteReportProvider; +import org.traccar.reports.StopsReportProvider; import org.traccar.storage.StorageException; @Path("reports") @@ -63,6 +64,21 @@ public class ReportResource extends BaseResource { private static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; private static final String CONTENT_DISPOSITION_VALUE_XLSX = "attachment; filename=report.xlsx"; + @Inject + private EventsReportProvider eventsReportProvider; + + @Inject + private RouteReportProvider routeReportProvider; + + @Inject + private StopsReportProvider stopsReportProvider; + + @Inject + private SummaryReportProvider summaryReportProvider; + + @Inject + private TripsReportProvider tripsReportProvider; + private interface ReportExecutor { void execute(ByteArrayOutputStream stream) throws StorageException, IOException; } @@ -102,7 +118,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); - return Route.getObjects(getUserId(), deviceIds, groupIds, from, to); + return routeReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to); } @Path("route") @@ -115,7 +131,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); - Route.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); + routeReportProvider.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); }); } @@ -127,7 +143,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); - return Events.getObjects(storage, getUserId(), deviceIds, groupIds, types, from, to); + return eventsReportProvider.getObjects(storage, getUserId(), deviceIds, groupIds, types, from, to); } @Path("events") @@ -141,7 +157,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); - Events.getExcel(stream, storage, getUserId(), deviceIds, groupIds, types, from, to); + eventsReportProvider.getExcel(stream, storage, getUserId(), deviceIds, groupIds, types, from, to); }); } @@ -153,7 +169,7 @@ public class ReportResource extends BaseResource { throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); - return Summary.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); + return summaryReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); } @Path("summary") @@ -167,7 +183,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); - Summary.getExcel(stream, getUserId(), deviceIds, groupIds, from, to, daily); + summaryReportProvider.getExcel(stream, getUserId(), deviceIds, groupIds, from, to, daily); }); } @@ -179,7 +195,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); - return Trips.getObjects(getUserId(), deviceIds, groupIds, from, to); + return tripsReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to); } @Path("trips") @@ -192,7 +208,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); - Trips.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); + tripsReportProvider.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); }); } @@ -204,7 +220,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); - return Stops.getObjects(getUserId(), deviceIds, groupIds, from, to); + return stopsReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to); } @Path("stops") @@ -217,7 +233,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); - Stops.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); + stopsReportProvider.getExcel(stream, getUserId(), deviceIds, groupIds, from, to); }); } diff --git a/src/main/java/org/traccar/reports/Events.java b/src/main/java/org/traccar/reports/Events.java deleted file mode 100644 index 130fba724..000000000 --- a/src/main/java/org/traccar/reports/Events.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) - * Copyright 2016 - 2018 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.reports; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; - -import org.apache.poi.ss.util.WorkbookUtil; -import org.traccar.Context; -import org.traccar.model.Device; -import org.traccar.model.Event; -import org.traccar.model.Geofence; -import org.traccar.model.Group; -import org.traccar.model.Maintenance; -import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReportSection; -import org.traccar.storage.Storage; -import org.traccar.storage.StorageException; - -public final class Events { - - private Events() { - } - - public static Collection getObjects( - Storage storage, long userId, - Collection deviceIds, Collection groupIds, - Collection types, Date from, Date to) throws StorageException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection events = Context.getDataManager().getEvents(deviceId, from, to); - boolean all = types.isEmpty() || types.contains(Event.ALL_EVENTS); - for (Event event : events) { - if (all || types.contains(event.getType())) { - long geofenceId = event.getGeofenceId(); - long maintenanceId = event.getMaintenanceId(); - if ((geofenceId == 0 || ReportUtils.getObject(storage, userId, Geofence.class, geofenceId) != null) - && (maintenanceId == 0 - || ReportUtils.getObject(storage, userId, Maintenance.class, maintenanceId) != null)) { - result.add(event); - } - } - } - } - return result; - } - - public static void getExcel( - OutputStream outputStream, Storage storage, long userId, - Collection deviceIds, Collection groupIds, - Collection types, Date from, Date to) throws StorageException, IOException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesEvents = new ArrayList<>(); - ArrayList sheetNames = new ArrayList<>(); - HashMap geofenceNames = new HashMap<>(); - HashMap maintenanceNames = new HashMap<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection events = Context.getDataManager().getEvents(deviceId, from, to); - boolean all = types.isEmpty() || types.contains(Event.ALL_EVENTS); - for (Iterator iterator = events.iterator(); iterator.hasNext();) { - Event event = iterator.next(); - if (all || types.contains(event.getType())) { - long geofenceId = event.getGeofenceId(); - long maintenanceId = event.getMaintenanceId(); - if (geofenceId != 0) { - Geofence geofence = ReportUtils.getObject( - storage, userId, Geofence.class, geofenceId); - if (geofence != null) { - geofenceNames.put(geofenceId, geofence.getName()); - } else { - iterator.remove(); - } - } else if (maintenanceId != 0) { - Maintenance maintenance = ReportUtils.getObject( - storage, userId, Maintenance.class, maintenanceId); - if (maintenance != null) { - maintenanceNames.put(maintenanceId, maintenance.getName()); - } else { - iterator.remove(); - } - } - } else { - iterator.remove(); - } - } - DeviceReportSection deviceEvents = new DeviceReportSection(); - Device device = Context.getIdentityManager().getById(deviceId); - deviceEvents.setDeviceName(device.getName()); - sheetNames.add(WorkbookUtil.createSafeSheetName(deviceEvents.getDeviceName())); - if (device.getGroupId() != 0) { - Group group = Context.getGroupsManager().getById(device.getGroupId()); - if (group != null) { - deviceEvents.setGroupName(group.getName()); - } - } - deviceEvents.setObjects(events); - devicesEvents.add(deviceEvents); - } - String templatePath = Context.getConfig().getString("report.templatesPath", - "templates/export/"); - try (InputStream inputStream = new FileInputStream(templatePath + "/events.xlsx")) { - org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); - jxlsContext.putVar("devices", devicesEvents); - jxlsContext.putVar("sheetNames", sheetNames); - jxlsContext.putVar("geofenceNames", geofenceNames); - jxlsContext.putVar("maintenanceNames", maintenanceNames); - jxlsContext.putVar("from", from); - jxlsContext.putVar("to", to); - ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); - } - } -} diff --git a/src/main/java/org/traccar/reports/EventsReportProvider.java b/src/main/java/org/traccar/reports/EventsReportProvider.java new file mode 100644 index 000000000..c4b0aad86 --- /dev/null +++ b/src/main/java/org/traccar/reports/EventsReportProvider.java @@ -0,0 +1,133 @@ +/* + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2018 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.reports; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.poi.ss.util.WorkbookUtil; +import org.traccar.Context; +import org.traccar.model.Device; +import org.traccar.model.Event; +import org.traccar.model.Geofence; +import org.traccar.model.Group; +import org.traccar.model.Maintenance; +import org.traccar.reports.common.ReportUtils; +import org.traccar.reports.model.DeviceReportSection; +import org.traccar.storage.Storage; +import org.traccar.storage.StorageException; + +public class EventsReportProvider { + + public Collection getObjects( + Storage storage, long userId, + Collection deviceIds, Collection groupIds, + Collection types, Date from, Date to) throws StorageException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList result = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection events = Context.getDataManager().getEvents(deviceId, from, to); + boolean all = types.isEmpty() || types.contains(Event.ALL_EVENTS); + for (Event event : events) { + if (all || types.contains(event.getType())) { + long geofenceId = event.getGeofenceId(); + long maintenanceId = event.getMaintenanceId(); + if ((geofenceId == 0 || ReportUtils.getObject(storage, userId, Geofence.class, geofenceId) != null) + && (maintenanceId == 0 + || ReportUtils.getObject(storage, userId, Maintenance.class, maintenanceId) != null)) { + result.add(event); + } + } + } + } + return result; + } + + public void getExcel( + OutputStream outputStream, Storage storage, long userId, + Collection deviceIds, Collection groupIds, + Collection types, Date from, Date to) throws StorageException, IOException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList devicesEvents = new ArrayList<>(); + ArrayList sheetNames = new ArrayList<>(); + HashMap geofenceNames = new HashMap<>(); + HashMap maintenanceNames = new HashMap<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection events = Context.getDataManager().getEvents(deviceId, from, to); + boolean all = types.isEmpty() || types.contains(Event.ALL_EVENTS); + for (Iterator iterator = events.iterator(); iterator.hasNext();) { + Event event = iterator.next(); + if (all || types.contains(event.getType())) { + long geofenceId = event.getGeofenceId(); + long maintenanceId = event.getMaintenanceId(); + if (geofenceId != 0) { + Geofence geofence = ReportUtils.getObject( + storage, userId, Geofence.class, geofenceId); + if (geofence != null) { + geofenceNames.put(geofenceId, geofence.getName()); + } else { + iterator.remove(); + } + } else if (maintenanceId != 0) { + Maintenance maintenance = ReportUtils.getObject( + storage, userId, Maintenance.class, maintenanceId); + if (maintenance != null) { + maintenanceNames.put(maintenanceId, maintenance.getName()); + } else { + iterator.remove(); + } + } + } else { + iterator.remove(); + } + } + DeviceReportSection deviceEvents = new DeviceReportSection(); + Device device = Context.getIdentityManager().getById(deviceId); + deviceEvents.setDeviceName(device.getName()); + sheetNames.add(WorkbookUtil.createSafeSheetName(deviceEvents.getDeviceName())); + if (device.getGroupId() != 0) { + Group group = Context.getGroupsManager().getById(device.getGroupId()); + if (group != null) { + deviceEvents.setGroupName(group.getName()); + } + } + deviceEvents.setObjects(events); + devicesEvents.add(deviceEvents); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/events.xlsx")) { + org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); + jxlsContext.putVar("devices", devicesEvents); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("geofenceNames", geofenceNames); + jxlsContext.putVar("maintenanceNames", maintenanceNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); + } + } +} diff --git a/src/main/java/org/traccar/reports/Route.java b/src/main/java/org/traccar/reports/Route.java deleted file mode 100644 index 5b8629aad..000000000 --- a/src/main/java/org/traccar/reports/Route.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 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.reports; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; - -import org.apache.poi.ss.util.WorkbookUtil; -import org.traccar.Context; -import org.traccar.model.Device; -import org.traccar.model.Group; -import org.traccar.model.Position; -import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReportSection; -import org.traccar.storage.StorageException; - -public final class Route { - - private Route() { - } - - public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - result.addAll(Context.getDataManager().getPositions(deviceId, from, to)); - } - return result; - } - - public static void getExcel(OutputStream outputStream, - long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException, IOException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesRoutes = new ArrayList<>(); - ArrayList sheetNames = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection positions = Context.getDataManager() - .getPositions(deviceId, from, to); - DeviceReportSection deviceRoutes = new DeviceReportSection(); - Device device = Context.getIdentityManager().getById(deviceId); - deviceRoutes.setDeviceName(device.getName()); - sheetNames.add(WorkbookUtil.createSafeSheetName(deviceRoutes.getDeviceName())); - if (device.getGroupId() != 0) { - Group group = Context.getGroupsManager().getById(device.getGroupId()); - if (group != null) { - deviceRoutes.setGroupName(group.getName()); - } - } - deviceRoutes.setObjects(positions); - devicesRoutes.add(deviceRoutes); - } - String templatePath = Context.getConfig().getString("report.templatesPath", - "templates/export/"); - try (InputStream inputStream = new FileInputStream(templatePath + "/route.xlsx")) { - org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); - jxlsContext.putVar("devices", devicesRoutes); - jxlsContext.putVar("sheetNames", sheetNames); - jxlsContext.putVar("from", from); - jxlsContext.putVar("to", to); - ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); - } - } -} diff --git a/src/main/java/org/traccar/reports/RouteReportProvider.java b/src/main/java/org/traccar/reports/RouteReportProvider.java new file mode 100644 index 000000000..4c4a41405 --- /dev/null +++ b/src/main/java/org/traccar/reports/RouteReportProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) + * Copyright 2016 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.reports; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; + +import org.apache.poi.ss.util.WorkbookUtil; +import org.traccar.Context; +import org.traccar.model.Device; +import org.traccar.model.Group; +import org.traccar.model.Position; +import org.traccar.reports.common.ReportUtils; +import org.traccar.reports.model.DeviceReportSection; +import org.traccar.storage.StorageException; + +public class RouteReportProvider { + + public Collection getObjects(long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList result = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + result.addAll(Context.getDataManager().getPositions(deviceId, from, to)); + } + return result; + } + + public void getExcel(OutputStream outputStream, + long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException, IOException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList devicesRoutes = new ArrayList<>(); + ArrayList sheetNames = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection positions = Context.getDataManager() + .getPositions(deviceId, from, to); + DeviceReportSection deviceRoutes = new DeviceReportSection(); + Device device = Context.getIdentityManager().getById(deviceId); + deviceRoutes.setDeviceName(device.getName()); + sheetNames.add(WorkbookUtil.createSafeSheetName(deviceRoutes.getDeviceName())); + if (device.getGroupId() != 0) { + Group group = Context.getGroupsManager().getById(device.getGroupId()); + if (group != null) { + deviceRoutes.setGroupName(group.getName()); + } + } + deviceRoutes.setObjects(positions); + devicesRoutes.add(deviceRoutes); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/route.xlsx")) { + org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); + jxlsContext.putVar("devices", devicesRoutes); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); + } + } +} diff --git a/src/main/java/org/traccar/reports/Stops.java b/src/main/java/org/traccar/reports/Stops.java deleted file mode 100644 index e688d53da..000000000 --- a/src/main/java/org/traccar/reports/Stops.java +++ /dev/null @@ -1,103 +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.reports; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; - -import org.apache.poi.ss.util.WorkbookUtil; -import org.traccar.Context; -import org.traccar.Main; -import org.traccar.database.DeviceManager; -import org.traccar.database.IdentityManager; -import org.traccar.model.Device; -import org.traccar.model.Group; -import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReportSection; -import org.traccar.reports.model.StopReportItem; -import org.traccar.storage.StorageException; - -public final class Stops { - - private Stops() { - } - - private static Collection detectStops(long deviceId, Date from, Date to) throws StorageException { - boolean ignoreOdometer = Context.getDeviceManager() - .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); - - IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class); - DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class); - - return ReportUtils.detectTripsAndStops( - identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), - Context.getTripsConfig(), ignoreOdometer, StopReportItem.class); - } - - public static Collection getObjects( - long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - result.addAll(detectStops(deviceId, from, to)); - } - return result; - } - - public static void getExcel( - OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException, IOException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesStops = new ArrayList<>(); - ArrayList sheetNames = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection stops = detectStops(deviceId, from, to); - DeviceReportSection deviceStops = new DeviceReportSection(); - Device device = Context.getIdentityManager().getById(deviceId); - deviceStops.setDeviceName(device.getName()); - sheetNames.add(WorkbookUtil.createSafeSheetName(deviceStops.getDeviceName())); - if (device.getGroupId() != 0) { - Group group = Context.getGroupsManager().getById(device.getGroupId()); - if (group != null) { - deviceStops.setGroupName(group.getName()); - } - } - deviceStops.setObjects(stops); - devicesStops.add(deviceStops); - } - String templatePath = Context.getConfig().getString("report.templatesPath", - "templates/export/"); - try (InputStream inputStream = new FileInputStream(templatePath + "/stops.xlsx")) { - org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); - jxlsContext.putVar("devices", devicesStops); - jxlsContext.putVar("sheetNames", sheetNames); - jxlsContext.putVar("from", from); - jxlsContext.putVar("to", to); - ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); - } - } - -} diff --git a/src/main/java/org/traccar/reports/StopsReportProvider.java b/src/main/java/org/traccar/reports/StopsReportProvider.java new file mode 100644 index 000000000..8dedb9a24 --- /dev/null +++ b/src/main/java/org/traccar/reports/StopsReportProvider.java @@ -0,0 +1,100 @@ +/* + * Copyright 2017 - 2022 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.reports; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; + +import org.apache.poi.ss.util.WorkbookUtil; +import org.traccar.Context; +import org.traccar.Main; +import org.traccar.database.DeviceManager; +import org.traccar.database.IdentityManager; +import org.traccar.model.Device; +import org.traccar.model.Group; +import org.traccar.reports.common.ReportUtils; +import org.traccar.reports.model.DeviceReportSection; +import org.traccar.reports.model.StopReportItem; +import org.traccar.storage.StorageException; + +public class StopsReportProvider { + + private Collection detectStops(long deviceId, Date from, Date to) throws StorageException { + boolean ignoreOdometer = Context.getDeviceManager() + .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); + + IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class); + DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class); + + return ReportUtils.detectTripsAndStops( + identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), + Context.getTripsConfig(), ignoreOdometer, StopReportItem.class); + } + + public Collection getObjects( + long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList result = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + result.addAll(detectStops(deviceId, from, to)); + } + return result; + } + + public void getExcel( + OutputStream outputStream, long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException, IOException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList devicesStops = new ArrayList<>(); + ArrayList sheetNames = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection stops = detectStops(deviceId, from, to); + DeviceReportSection deviceStops = new DeviceReportSection(); + Device device = Context.getIdentityManager().getById(deviceId); + deviceStops.setDeviceName(device.getName()); + sheetNames.add(WorkbookUtil.createSafeSheetName(deviceStops.getDeviceName())); + if (device.getGroupId() != 0) { + Group group = Context.getGroupsManager().getById(device.getGroupId()); + if (group != null) { + deviceStops.setGroupName(group.getName()); + } + } + deviceStops.setObjects(stops); + devicesStops.add(deviceStops); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/stops.xlsx")) { + org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); + jxlsContext.putVar("devices", devicesStops); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); + } + } + +} diff --git a/src/main/java/org/traccar/reports/Summary.java b/src/main/java/org/traccar/reports/Summary.java deleted file mode 100644 index 30c4cb057..000000000 --- a/src/main/java/org/traccar/reports/Summary.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) - * Copyright 2016 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.reports; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; - -import org.jxls.util.JxlsHelper; -import org.traccar.Context; -import org.traccar.helper.UnitsConverter; -import org.traccar.model.Position; -import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.SummaryReportItem; -import org.traccar.storage.StorageException; - -public final class Summary { - - private Summary() { - } - - private static SummaryReportItem calculateSummaryResult(long deviceId, Collection positions) { - SummaryReportItem result = new SummaryReportItem(); - result.setDeviceId(deviceId); - result.setDeviceName(Context.getIdentityManager().getById(deviceId).getName()); - if (positions != null && !positions.isEmpty()) { - Position firstPosition = null; - Position previousPosition = null; - for (Position position : positions) { - if (firstPosition == null) { - firstPosition = position; - } - previousPosition = position; - if (position.getSpeed() > result.getMaxSpeed()) { - result.setMaxSpeed(position.getSpeed()); - } - } - boolean ignoreOdometer = Context.getDeviceManager() - .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); - result.setDistance(ReportUtils.calculateDistance(firstPosition, previousPosition, !ignoreOdometer)); - result.setSpentFuel(ReportUtils.calculateFuel(firstPosition, previousPosition)); - - long durationMilliseconds; - if (firstPosition.getAttributes().containsKey(Position.KEY_HOURS) - && previousPosition.getAttributes().containsKey(Position.KEY_HOURS)) { - durationMilliseconds = - previousPosition.getLong(Position.KEY_HOURS) - firstPosition.getLong(Position.KEY_HOURS); - result.setEngineHours(durationMilliseconds); - } else { - durationMilliseconds = - previousPosition.getFixTime().getTime() - firstPosition.getFixTime().getTime(); - } - - if (durationMilliseconds > 0) { - result.setAverageSpeed( - UnitsConverter.knotsFromMps(result.getDistance() * 1000 / durationMilliseconds)); - } - - if (!ignoreOdometer - && firstPosition.getDouble(Position.KEY_ODOMETER) != 0 - && previousPosition.getDouble(Position.KEY_ODOMETER) != 0) { - result.setStartOdometer(firstPosition.getDouble(Position.KEY_ODOMETER)); - result.setEndOdometer(previousPosition.getDouble(Position.KEY_ODOMETER)); - } else { - result.setStartOdometer(firstPosition.getDouble(Position.KEY_TOTAL_DISTANCE)); - result.setEndOdometer(previousPosition.getDouble(Position.KEY_TOTAL_DISTANCE)); - } - - result.setStartTime(firstPosition.getFixTime()); - result.setEndTime(previousPosition.getFixTime()); - } - return result; - } - - private static int getDay(long userId, Date date) { - Calendar calendar = Calendar.getInstance(ReportUtils.getTimezone(userId)); - calendar.setTime(date); - return calendar.get(Calendar.DAY_OF_MONTH); - } - - private static Collection calculateSummaryResults( - long userId, long deviceId, Date from, Date to, boolean daily) throws StorageException { - - ArrayList positions = new ArrayList<>(Context.getDataManager().getPositions(deviceId, from, to)); - - ArrayList results = new ArrayList<>(); - if (daily && !positions.isEmpty()) { - int startIndex = 0; - int startDay = getDay(userId, positions.iterator().next().getFixTime()); - for (int i = 0; i < positions.size(); i++) { - int currentDay = getDay(userId, positions.get(i).getFixTime()); - if (currentDay != startDay) { - results.add(calculateSummaryResult(deviceId, positions.subList(startIndex, i))); - startIndex = i; - startDay = currentDay; - } - } - results.add(calculateSummaryResult(deviceId, positions.subList(startIndex, positions.size()))); - } else { - results.add(calculateSummaryResult(deviceId, positions)); - } - - return results; - } - - public static Collection getObjects(long userId, Collection deviceIds, - Collection groupIds, Date from, Date to, boolean daily) throws StorageException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection deviceResults = calculateSummaryResults(userId, deviceId, from, to, daily); - for (SummaryReportItem summaryReport : deviceResults) { - if (summaryReport.getStartTime() != null && summaryReport.getEndTime() != null) { - result.add(summaryReport); - } - } - } - return result; - } - - public static void getExcel(OutputStream outputStream, - long userId, Collection deviceIds, Collection groupIds, - Date from, Date to, boolean daily) throws StorageException, IOException { - ReportUtils.checkPeriodLimit(from, to); - Collection summaries = getObjects(userId, deviceIds, groupIds, from, to, daily); - String templatePath = Context.getConfig().getString("report.templatesPath", - "templates/export/"); - try (InputStream inputStream = new FileInputStream(templatePath + "/summary.xlsx")) { - org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); - jxlsContext.putVar("summaries", summaries); - jxlsContext.putVar("from", from); - jxlsContext.putVar("to", to); - JxlsHelper.getInstance().setUseFastFormulaProcessor(false) - .processTemplate(inputStream, outputStream, jxlsContext); - } - } -} diff --git a/src/main/java/org/traccar/reports/SummaryReportProvider.java b/src/main/java/org/traccar/reports/SummaryReportProvider.java new file mode 100644 index 000000000..a2306f3d1 --- /dev/null +++ b/src/main/java/org/traccar/reports/SummaryReportProvider.java @@ -0,0 +1,155 @@ +/* + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) + * Copyright 2016 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.reports; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; + +import org.jxls.util.JxlsHelper; +import org.traccar.Context; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; +import org.traccar.reports.common.ReportUtils; +import org.traccar.reports.model.SummaryReportItem; +import org.traccar.storage.StorageException; + +public class SummaryReportProvider { + + private SummaryReportItem calculateSummaryResult(long deviceId, Collection positions) { + SummaryReportItem result = new SummaryReportItem(); + result.setDeviceId(deviceId); + result.setDeviceName(Context.getIdentityManager().getById(deviceId).getName()); + if (positions != null && !positions.isEmpty()) { + Position firstPosition = null; + Position previousPosition = null; + for (Position position : positions) { + if (firstPosition == null) { + firstPosition = position; + } + previousPosition = position; + if (position.getSpeed() > result.getMaxSpeed()) { + result.setMaxSpeed(position.getSpeed()); + } + } + boolean ignoreOdometer = Context.getDeviceManager() + .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); + result.setDistance(ReportUtils.calculateDistance(firstPosition, previousPosition, !ignoreOdometer)); + result.setSpentFuel(ReportUtils.calculateFuel(firstPosition, previousPosition)); + + long durationMilliseconds; + if (firstPosition.getAttributes().containsKey(Position.KEY_HOURS) + && previousPosition.getAttributes().containsKey(Position.KEY_HOURS)) { + durationMilliseconds = + previousPosition.getLong(Position.KEY_HOURS) - firstPosition.getLong(Position.KEY_HOURS); + result.setEngineHours(durationMilliseconds); + } else { + durationMilliseconds = + previousPosition.getFixTime().getTime() - firstPosition.getFixTime().getTime(); + } + + if (durationMilliseconds > 0) { + result.setAverageSpeed( + UnitsConverter.knotsFromMps(result.getDistance() * 1000 / durationMilliseconds)); + } + + if (!ignoreOdometer + && firstPosition.getDouble(Position.KEY_ODOMETER) != 0 + && previousPosition.getDouble(Position.KEY_ODOMETER) != 0) { + result.setStartOdometer(firstPosition.getDouble(Position.KEY_ODOMETER)); + result.setEndOdometer(previousPosition.getDouble(Position.KEY_ODOMETER)); + } else { + result.setStartOdometer(firstPosition.getDouble(Position.KEY_TOTAL_DISTANCE)); + result.setEndOdometer(previousPosition.getDouble(Position.KEY_TOTAL_DISTANCE)); + } + + result.setStartTime(firstPosition.getFixTime()); + result.setEndTime(previousPosition.getFixTime()); + } + return result; + } + + private int getDay(long userId, Date date) { + Calendar calendar = Calendar.getInstance(ReportUtils.getTimezone(userId)); + calendar.setTime(date); + return calendar.get(Calendar.DAY_OF_MONTH); + } + + private Collection calculateSummaryResults( + long userId, long deviceId, Date from, Date to, boolean daily) throws StorageException { + + ArrayList positions = new ArrayList<>(Context.getDataManager().getPositions(deviceId, from, to)); + + ArrayList results = new ArrayList<>(); + if (daily && !positions.isEmpty()) { + int startIndex = 0; + int startDay = getDay(userId, positions.iterator().next().getFixTime()); + for (int i = 0; i < positions.size(); i++) { + int currentDay = getDay(userId, positions.get(i).getFixTime()); + if (currentDay != startDay) { + results.add(calculateSummaryResult(deviceId, positions.subList(startIndex, i))); + startIndex = i; + startDay = currentDay; + } + } + results.add(calculateSummaryResult(deviceId, positions.subList(startIndex, positions.size()))); + } else { + results.add(calculateSummaryResult(deviceId, positions)); + } + + return results; + } + + public Collection getObjects( + long userId, Collection deviceIds, + Collection groupIds, Date from, Date to, boolean daily) throws StorageException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList result = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection deviceResults = calculateSummaryResults(userId, deviceId, from, to, daily); + for (SummaryReportItem summaryReport : deviceResults) { + if (summaryReport.getStartTime() != null && summaryReport.getEndTime() != null) { + result.add(summaryReport); + } + } + } + return result; + } + + public void getExcel(OutputStream outputStream, + long userId, Collection deviceIds, Collection groupIds, + Date from, Date to, boolean daily) throws StorageException, IOException { + ReportUtils.checkPeriodLimit(from, to); + Collection summaries = getObjects(userId, deviceIds, groupIds, from, to, daily); + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/summary.xlsx")) { + org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); + jxlsContext.putVar("summaries", summaries); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + JxlsHelper.getInstance().setUseFastFormulaProcessor(false) + .processTemplate(inputStream, outputStream, jxlsContext); + } + } +} diff --git a/src/main/java/org/traccar/reports/Trips.java b/src/main/java/org/traccar/reports/Trips.java deleted file mode 100644 index 74e24cf2f..000000000 --- a/src/main/java/org/traccar/reports/Trips.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2016 Anton Tananaev (anton@traccar.org) - * Copyright 2016 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.reports; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; - -import org.apache.poi.ss.util.WorkbookUtil; -import org.traccar.Context; -import org.traccar.Main; -import org.traccar.database.DeviceManager; -import org.traccar.database.IdentityManager; -import org.traccar.model.Device; -import org.traccar.model.Group; -import org.traccar.reports.common.ReportUtils; -import org.traccar.reports.model.DeviceReportSection; -import org.traccar.reports.model.TripReportItem; -import org.traccar.storage.StorageException; - -public final class Trips { - - private Trips() { - } - - private static Collection detectTrips(long deviceId, Date from, Date to) throws StorageException { - boolean ignoreOdometer = Context.getDeviceManager() - .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); - - IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class); - DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class); - - return ReportUtils.detectTripsAndStops( - identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), - Context.getTripsConfig(), ignoreOdometer, TripReportItem.class); - } - - public static Collection getObjects(long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList result = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - result.addAll(detectTrips(deviceId, from, to)); - } - return result; - } - - public static void getExcel(OutputStream outputStream, - long userId, Collection deviceIds, Collection groupIds, - Date from, Date to) throws StorageException, IOException { - ReportUtils.checkPeriodLimit(from, to); - ArrayList devicesTrips = new ArrayList<>(); - ArrayList sheetNames = new ArrayList<>(); - for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { - Context.getPermissionsManager().checkDevice(userId, deviceId); - Collection trips = detectTrips(deviceId, from, to); - DeviceReportSection deviceTrips = new DeviceReportSection(); - Device device = Context.getIdentityManager().getById(deviceId); - deviceTrips.setDeviceName(device.getName()); - sheetNames.add(WorkbookUtil.createSafeSheetName(deviceTrips.getDeviceName())); - if (device.getGroupId() != 0) { - Group group = Context.getGroupsManager().getById(device.getGroupId()); - if (group != null) { - deviceTrips.setGroupName(group.getName()); - } - } - deviceTrips.setObjects(trips); - devicesTrips.add(deviceTrips); - } - String templatePath = Context.getConfig().getString("report.templatesPath", - "templates/export/"); - try (InputStream inputStream = new FileInputStream(templatePath + "/trips.xlsx")) { - org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); - jxlsContext.putVar("devices", devicesTrips); - jxlsContext.putVar("sheetNames", sheetNames); - jxlsContext.putVar("from", from); - jxlsContext.putVar("to", to); - ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); - } - } - -} diff --git a/src/main/java/org/traccar/reports/TripsReportProvider.java b/src/main/java/org/traccar/reports/TripsReportProvider.java new file mode 100644 index 000000000..6aff08a1d --- /dev/null +++ b/src/main/java/org/traccar/reports/TripsReportProvider.java @@ -0,0 +1,98 @@ +/* + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) + * Copyright 2016 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.reports; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; + +import org.apache.poi.ss.util.WorkbookUtil; +import org.traccar.Context; +import org.traccar.Main; +import org.traccar.database.DeviceManager; +import org.traccar.database.IdentityManager; +import org.traccar.model.Device; +import org.traccar.model.Group; +import org.traccar.reports.common.ReportUtils; +import org.traccar.reports.model.DeviceReportSection; +import org.traccar.reports.model.TripReportItem; +import org.traccar.storage.StorageException; + +public class TripsReportProvider { + + private Collection detectTrips(long deviceId, Date from, Date to) throws StorageException { + boolean ignoreOdometer = Context.getDeviceManager() + .lookupAttributeBoolean(deviceId, "report.ignoreOdometer", false, false, true); + + IdentityManager identityManager = Main.getInjector().getInstance(IdentityManager.class); + DeviceManager deviceManager = Main.getInjector().getInstance(DeviceManager.class); + + return ReportUtils.detectTripsAndStops( + identityManager, deviceManager, Context.getDataManager().getPositions(deviceId, from, to), + Context.getTripsConfig(), ignoreOdometer, TripReportItem.class); + } + + public Collection getObjects(long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList result = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + result.addAll(detectTrips(deviceId, from, to)); + } + return result; + } + + public void getExcel(OutputStream outputStream, + long userId, Collection deviceIds, Collection groupIds, + Date from, Date to) throws StorageException, IOException { + ReportUtils.checkPeriodLimit(from, to); + ArrayList devicesTrips = new ArrayList<>(); + ArrayList sheetNames = new ArrayList<>(); + for (long deviceId: ReportUtils.getDeviceList(deviceIds, groupIds)) { + Context.getPermissionsManager().checkDevice(userId, deviceId); + Collection trips = detectTrips(deviceId, from, to); + DeviceReportSection deviceTrips = new DeviceReportSection(); + Device device = Context.getIdentityManager().getById(deviceId); + deviceTrips.setDeviceName(device.getName()); + sheetNames.add(WorkbookUtil.createSafeSheetName(deviceTrips.getDeviceName())); + if (device.getGroupId() != 0) { + Group group = Context.getGroupsManager().getById(device.getGroupId()); + if (group != null) { + deviceTrips.setGroupName(group.getName()); + } + } + deviceTrips.setObjects(trips); + devicesTrips.add(deviceTrips); + } + String templatePath = Context.getConfig().getString("report.templatesPath", + "templates/export/"); + try (InputStream inputStream = new FileInputStream(templatePath + "/trips.xlsx")) { + org.jxls.common.Context jxlsContext = ReportUtils.initializeContext(userId); + jxlsContext.putVar("devices", devicesTrips); + jxlsContext.putVar("sheetNames", sheetNames); + jxlsContext.putVar("from", from); + jxlsContext.putVar("to", to); + ReportUtils.processTemplateWithSheets(inputStream, outputStream, jxlsContext); + } + } + +} -- cgit v1.2.3 From b6ec84dbb4e1e2e212b0d6195920407a43919ab5 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 4 Jun 2022 11:03:59 -0700 Subject: Fix compilation issue --- src/main/java/org/traccar/api/resource/ReportResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 38eb52685..96b32a4f0 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -143,7 +143,7 @@ public class ReportResource extends BaseResource { @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); - return eventsReportProvider.getObjects(storage, getUserId(), deviceIds, groupIds, types, from, to); + return eventsReportProvider.getObjects(getUserId(), deviceIds, groupIds, types, from, to); } @Path("events") @@ -157,7 +157,7 @@ public class ReportResource extends BaseResource { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); - eventsReportProvider.getExcel(stream, storage, getUserId(), deviceIds, groupIds, types, from, to); + eventsReportProvider.getExcel(stream, getUserId(), deviceIds, groupIds, types, from, to); }); } -- cgit v1.2.3 From 8eecfdcf5c59f92158a6c339d1622e0e9d67968c Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 7 Jun 2022 06:48:53 -0700 Subject: Pass user to notificators --- .../java/org/traccar/api/resource/NotificationResource.java | 12 ++++++++---- src/main/java/org/traccar/api/resource/PasswordResource.java | 2 +- src/main/java/org/traccar/api/resource/ReportResource.java | 4 +++- .../java/org/traccar/api/security/PermissionsService.java | 4 ++-- src/main/java/org/traccar/database/MailManager.java | 10 ++++------ src/main/java/org/traccar/database/NotificationManager.java | 4 +++- .../java/org/traccar/notification/NotificationFormatter.java | 9 ++++----- src/main/java/org/traccar/notificators/Notificator.java | 9 +++++---- .../java/org/traccar/notificators/NotificatorFirebase.java | 11 +++++------ src/main/java/org/traccar/notificators/NotificatorMail.java | 9 +++++---- src/main/java/org/traccar/notificators/NotificatorNull.java | 7 ++++--- .../java/org/traccar/notificators/NotificatorPushover.java | 12 +++++------- src/main/java/org/traccar/notificators/NotificatorSms.java | 12 +++++------- .../java/org/traccar/notificators/NotificatorTelegram.java | 11 +++++------ src/main/java/org/traccar/notificators/NotificatorWeb.java | 7 ++++--- 15 files changed, 63 insertions(+), 60 deletions(-) (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/api/resource/NotificationResource.java b/src/main/java/org/traccar/api/resource/NotificationResource.java index cf4b66fa1..2fc103e20 100644 --- a/src/main/java/org/traccar/api/resource/NotificationResource.java +++ b/src/main/java/org/traccar/api/resource/NotificationResource.java @@ -31,7 +31,9 @@ import org.traccar.api.ExtendedObjectResource; import org.traccar.model.Event; import org.traccar.model.Notification; import org.traccar.model.Typed; +import org.traccar.model.User; import org.traccar.notification.MessageException; +import org.traccar.storage.StorageException; @Path("notifications") @Produces(MediaType.APPLICATION_JSON) @@ -56,10 +58,11 @@ public class NotificationResource extends ExtendedObjectResource { @POST @Path("test") - public Response testMessage() throws MessageException, InterruptedException { + public Response testMessage() throws MessageException, InterruptedException, StorageException { + User user = permissionsService.getUser(getUserId()); for (Typed method : Context.getNotificatorManager().getAllNotificatorTypes()) { Context.getNotificatorManager() - .getNotificator(method.getType()).sendSync(getUserId(), new Event("test", 0), null); + .getNotificator(method.getType()).sendSync(user, new Event("test", 0), null); } return Response.noContent().build(); } @@ -67,8 +70,9 @@ public class NotificationResource extends ExtendedObjectResource { @POST @Path("test/{notificator}") public Response testMessage(@PathParam("notificator") String notificator) - throws MessageException, InterruptedException { - Context.getNotificatorManager().getNotificator(notificator).sendSync(getUserId(), new Event("test", 0), null); + throws MessageException, InterruptedException, StorageException { + User user = permissionsService.getUser(getUserId()); + Context.getNotificatorManager().getNotificator(notificator).sendSync(user, new Event("test", 0), null); return Response.noContent().build(); } diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java index 0642ff3cc..ed7131718 100644 --- a/src/main/java/org/traccar/api/resource/PasswordResource.java +++ b/src/main/java/org/traccar/api/resource/PasswordResource.java @@ -55,7 +55,7 @@ public class PasswordResource extends BaseResource { velocityContext.put("token", token); NotificationMessage fullMessage = TextTemplateFormatter.formatMessage(velocityContext, "passwordReset", "full"); - Context.getMailManager().sendMessage(userId, fullMessage.getSubject(), fullMessage.getBody()); + Context.getMailManager().sendMessage(user, fullMessage.getSubject(), fullMessage.getBody()); break; } } diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 96b32a4f0..3c1b8f715 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -43,6 +43,7 @@ import org.traccar.api.BaseResource; import org.traccar.helper.LogAction; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.model.User; import org.traccar.model.UserRestrictions; import org.traccar.reports.EventsReportProvider; import org.traccar.reports.SummaryReportProvider; @@ -97,8 +98,9 @@ public class ReportResource extends BaseResource { attachment.setDataHandler(new DataHandler(new ByteArrayDataSource( stream.toByteArray(), "application/octet-stream"))); + User user = permissionsService.getUser(userId); Context.getMailManager().sendMessage( - userId, "Report", "The report is in the attachment.", attachment); + user, "Report", "The report is in the attachment.", attachment); } catch (StorageException | IOException | MessagingException e) { LOGGER.warn("Report failed", e); } diff --git a/src/main/java/org/traccar/api/security/PermissionsService.java b/src/main/java/org/traccar/api/security/PermissionsService.java index 12a2189e9..9ec3b43c1 100644 --- a/src/main/java/org/traccar/api/security/PermissionsService.java +++ b/src/main/java/org/traccar/api/security/PermissionsService.java @@ -46,7 +46,7 @@ public class PermissionsService { this.storage = storage; } - private Server getServer() throws StorageException { + public Server getServer() throws StorageException { if (server == null) { server = storage.getObject( Server.class, new Request(new Columns.All())); @@ -54,7 +54,7 @@ public class PermissionsService { return server; } - private User getUser(long userId) throws StorageException { + public User getUser(long userId) throws StorageException { if (user == null) { user = storage.getObject( User.class, new Request(new Columns.All(), new Condition.Equals("id", "id", userId))); diff --git a/src/main/java/org/traccar/database/MailManager.java b/src/main/java/org/traccar/database/MailManager.java index d94f55cda..21fee5ee7 100644 --- a/src/main/java/org/traccar/database/MailManager.java +++ b/src/main/java/org/traccar/database/MailManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -92,14 +92,12 @@ public final class MailManager { } public void sendMessage( - long userId, String subject, String body) throws MessagingException { - sendMessage(userId, subject, body, null); + User user, String subject, String body) throws MessagingException { + sendMessage(user, subject, body, null); } public void sendMessage( - long userId, String subject, String body, MimeBodyPart attachment) throws MessagingException { - User user = Context.getPermissionsManager().getUser(userId); - + User user, String subject, String body, MimeBodyPart attachment) throws MessagingException { Properties properties = null; if (!Context.getConfig().getBoolean("mail.smtp.ignoreUserConfig")) { properties = getProperties(new PropertiesProvider(user)); diff --git a/src/main/java/org/traccar/database/NotificationManager.java b/src/main/java/org/traccar/database/NotificationManager.java index 64f3b6775..f88b3b18c 100644 --- a/src/main/java/org/traccar/database/NotificationManager.java +++ b/src/main/java/org/traccar/database/NotificationManager.java @@ -35,6 +35,7 @@ import org.traccar.model.Event; import org.traccar.model.Notification; import org.traccar.model.Position; import org.traccar.model.Typed; +import org.traccar.model.User; import org.traccar.storage.StorageException; public class NotificationManager extends ExtendedObjectManager { @@ -106,8 +107,9 @@ public class NotificationManager extends ExtendedObjectManager { .getAddress(position.getLatitude(), position.getLongitude(), null)); } + User user = Context.getUsersManager().getById(userId); for (String notificator : notificators) { - Context.getNotificatorManager().getNotificator(notificator).sendAsync(userId, event, position); + Context.getNotificatorManager().getNotificator(notificator).sendAsync(user, event, position); } } if (Context.getEventForwarder() != null) { diff --git a/src/main/java/org/traccar/notification/NotificationFormatter.java b/src/main/java/org/traccar/notification/NotificationFormatter.java index 30a862372..c3e37c9e9 100644 --- a/src/main/java/org/traccar/notification/NotificationFormatter.java +++ b/src/main/java/org/traccar/notification/NotificationFormatter.java @@ -33,9 +33,8 @@ public final class NotificationFormatter { } public static NotificationMessage formatMessage( - CacheManager cacheManager, long userId, Event event, Position position, String templatePath) { + CacheManager cacheManager, User user, Event event, Position position, String templatePath) { - User user = cacheManager.getObject(User.class, userId); Device device = cacheManager.getObject(Device.class, event.getDeviceId()); VelocityContext velocityContext = TextTemplateFormatter.prepareContext(user); @@ -44,9 +43,9 @@ public final class NotificationFormatter { velocityContext.put("event", event); if (position != null) { velocityContext.put("position", position); - velocityContext.put("speedUnit", ReportUtils.getSpeedUnit(userId)); - velocityContext.put("distanceUnit", ReportUtils.getDistanceUnit(userId)); - velocityContext.put("volumeUnit", ReportUtils.getVolumeUnit(userId)); + velocityContext.put("speedUnit", ReportUtils.getSpeedUnit(user.getId())); + velocityContext.put("distanceUnit", ReportUtils.getDistanceUnit(user.getId())); + velocityContext.put("volumeUnit", ReportUtils.getVolumeUnit(user.getId())); } if (event.getGeofenceId() != 0) { velocityContext.put("geofence", cacheManager.getObject(Geofence.class, event.getGeofenceId())); diff --git a/src/main/java/org/traccar/notificators/Notificator.java b/src/main/java/org/traccar/notificators/Notificator.java index dd888bae9..3903f3008 100644 --- a/src/main/java/org/traccar/notificators/Notificator.java +++ b/src/main/java/org/traccar/notificators/Notificator.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,23 +20,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.model.User; import org.traccar.notification.MessageException; public abstract class Notificator { private static final Logger LOGGER = LoggerFactory.getLogger(Notificator.class); - public void sendAsync(final long userId, final Event event, final Position position) { + public void sendAsync(User user, Event event, Position position) { new Thread(() -> { try { - sendSync(userId, event, position); + sendSync(user, event, position); } catch (MessageException | InterruptedException error) { LOGGER.warn("Event send error", error); } }).start(); } - public abstract void sendSync(long userId, Event event, Position position) + public abstract void sendSync(User user, Event event, Position position) throws MessageException, InterruptedException; } diff --git a/src/main/java/org/traccar/notificators/NotificatorFirebase.java b/src/main/java/org/traccar/notificators/NotificatorFirebase.java index bcce9a4d8..ee22b3a22 100644 --- a/src/main/java/org/traccar/notificators/NotificatorFirebase.java +++ b/src/main/java/org/traccar/notificators/NotificatorFirebase.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -67,12 +67,11 @@ public class NotificatorFirebase extends Notificator { } @Override - public void sendSync(long userId, Event event, Position position) { - final User user = Context.getPermissionsManager().getUser(userId); + public void sendSync(User user, Event event, Position position) { if (user.getAttributes().containsKey("notificationTokens")) { NotificationMessage shortMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); + Main.getInjector().getInstance(CacheManager.class), user, event, position, "short"); Notification notification = new Notification(); notification.title = shortMessage.getSubject(); @@ -99,8 +98,8 @@ public class NotificatorFirebase extends Notificator { } @Override - public void sendAsync(long userId, Event event, Position position) { - sendSync(userId, event, position); + public void sendAsync(User user, Event event, Position position) { + sendSync(user, event, position); } } diff --git a/src/main/java/org/traccar/notificators/NotificatorMail.java b/src/main/java/org/traccar/notificators/NotificatorMail.java index eb7f399eb..7b85254be 100644 --- a/src/main/java/org/traccar/notificators/NotificatorMail.java +++ b/src/main/java/org/traccar/notificators/NotificatorMail.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ import org.traccar.Context; import org.traccar.Main; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.model.User; import org.traccar.notification.NotificationMessage; import org.traccar.notification.MessageException; import org.traccar.notification.NotificationFormatter; @@ -30,11 +31,11 @@ import javax.mail.MessagingException; public final class NotificatorMail extends Notificator { @Override - public void sendSync(long userId, Event event, Position position) throws MessageException { + public void sendSync(User user, Event event, Position position) throws MessageException { try { NotificationMessage fullMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), userId, event, position, "full"); - Context.getMailManager().sendMessage(userId, fullMessage.getSubject(), fullMessage.getBody()); + Main.getInjector().getInstance(CacheManager.class), user, event, position, "full"); + Context.getMailManager().sendMessage(user, fullMessage.getSubject(), fullMessage.getBody()); } catch (MessagingException e) { throw new MessageException(e); } diff --git a/src/main/java/org/traccar/notificators/NotificatorNull.java b/src/main/java/org/traccar/notificators/NotificatorNull.java index 9364336be..a03a6e2c9 100644 --- a/src/main/java/org/traccar/notificators/NotificatorNull.java +++ b/src/main/java/org/traccar/notificators/NotificatorNull.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,18 +20,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.model.User; public final class NotificatorNull extends Notificator { private static final Logger LOGGER = LoggerFactory.getLogger(NotificatorNull.class); @Override - public void sendAsync(long userId, Event event, Position position) { + public void sendAsync(User user, Event event, Position position) { LOGGER.warn("You are using null notificatior, please check your configuration, notification not sent"); } @Override - public void sendSync(long userId, Event event, Position position) { + public void sendSync(User user, Event event, Position position) { LOGGER.warn("You are using null notificatior, please check your configuration, notification not sent"); } diff --git a/src/main/java/org/traccar/notificators/NotificatorPushover.java b/src/main/java/org/traccar/notificators/NotificatorPushover.java index 73fad9bd2..ffd9b426f 100644 --- a/src/main/java/org/traccar/notificators/NotificatorPushover.java +++ b/src/main/java/org/traccar/notificators/NotificatorPushover.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2020 - 2022 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,9 +59,7 @@ public class NotificatorPushover extends Notificator { } @Override - public void sendSync(long userId, Event event, Position position) { - - final User user = Context.getPermissionsManager().getUser(userId); + public void sendSync(User user, Event event, Position position) { String device = ""; @@ -80,7 +78,7 @@ public class NotificatorPushover extends Notificator { } NotificationMessage shortMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); + Main.getInjector().getInstance(CacheManager.class), user, event, position, "short"); Message message = new Message(); message.token = token; @@ -103,8 +101,8 @@ public class NotificatorPushover extends Notificator { } @Override - public void sendAsync(long userId, Event event, Position position) { - sendSync(userId, event, position); + public void sendAsync(User user, Event event, Position position) { + sendSync(user, event, position); } } diff --git a/src/main/java/org/traccar/notificators/NotificatorSms.java b/src/main/java/org/traccar/notificators/NotificatorSms.java index 09eb65b0c..ae409c558 100644 --- a/src/main/java/org/traccar/notificators/NotificatorSms.java +++ b/src/main/java/org/traccar/notificators/NotificatorSms.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2017 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2017 - 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,11 +30,10 @@ import org.traccar.session.cache.CacheManager; public final class NotificatorSms extends Notificator { @Override - public void sendAsync(long userId, Event event, Position position) { - final User user = Context.getPermissionsManager().getUser(userId); + public void sendAsync(User user, Event event, Position position) { if (user.getPhone() != null) { NotificationMessage shortMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); + Main.getInjector().getInstance(CacheManager.class), user, event, position, "short"); Main.getInjector().getInstance(StatisticsManager.class).registerSms(); Context.getSmsManager().sendMessageAsync(user.getPhone(), shortMessage.getBody(), false); @@ -42,11 +41,10 @@ public final class NotificatorSms extends Notificator { } @Override - public void sendSync(long userId, Event event, Position position) throws MessageException, InterruptedException { - final User user = Context.getPermissionsManager().getUser(userId); + public void sendSync(User user, Event event, Position position) throws MessageException, InterruptedException { if (user.getPhone() != null) { NotificationMessage shortMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); + Main.getInjector().getInstance(CacheManager.class), user, event, position, "short"); Main.getInjector().getInstance(StatisticsManager.class).registerSms(); Context.getSmsManager().sendMessageSync(user.getPhone(), shortMessage.getBody(), false); diff --git a/src/main/java/org/traccar/notificators/NotificatorTelegram.java b/src/main/java/org/traccar/notificators/NotificatorTelegram.java index a8e69e77d..46e29559d 100644 --- a/src/main/java/org/traccar/notificators/NotificatorTelegram.java +++ b/src/main/java/org/traccar/notificators/NotificatorTelegram.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 - 2021 Anton Tananaev (anton@traccar.org) + * Copyright 2019 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2021 Rafael Miquelino (rafaelmiquelino@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -99,10 +99,9 @@ public class NotificatorTelegram extends Notificator { } @Override - public void sendSync(long userId, Event event, Position position) { - User user = Context.getPermissionsManager().getUser(userId); + public void sendSync(User user, Event event, Position position) { NotificationMessage shortMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), userId, event, position, "short"); + Main.getInjector().getInstance(CacheManager.class), user, event, position, "short"); TextMessage message = new TextMessage(); message.chatId = user.getString("telegramChatId"); @@ -117,8 +116,8 @@ public class NotificatorTelegram extends Notificator { } @Override - public void sendAsync(long userId, Event event, Position position) { - sendSync(userId, event, position); + public void sendAsync(User user, Event event, Position position) { + sendSync(user, event, position); } } diff --git a/src/main/java/org/traccar/notificators/NotificatorWeb.java b/src/main/java/org/traccar/notificators/NotificatorWeb.java index 1d11c0b46..c9ab93b6d 100644 --- a/src/main/java/org/traccar/notificators/NotificatorWeb.java +++ b/src/main/java/org/traccar/notificators/NotificatorWeb.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Anton Tananaev (anton@traccar.org) + * Copyright 2018 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2018 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,12 +19,13 @@ package org.traccar.notificators; import org.traccar.Context; import org.traccar.model.Event; import org.traccar.model.Position; +import org.traccar.model.User; public final class NotificatorWeb extends Notificator { @Override - public void sendSync(long userId, Event event, Position position) { - Context.getConnectionManager().updateEvent(userId, event); + public void sendSync(User user, Event event, Position position) { + Context.getConnectionManager().updateEvent(user.getId(), event); } } -- cgit v1.2.3 From c03b4a2ace925e6a0d7c43ce59e14ddb9cbf18a9 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 10 Jun 2022 07:06:43 -0700 Subject: Inject mail manager --- src/main/java/org/traccar/Context.java | 9 --------- .../org/traccar/api/resource/PasswordResource.java | 7 ++++++- .../java/org/traccar/api/resource/ReportResource.java | 8 +++++--- .../java/org/traccar/api/resource/ServerResource.java | 8 +++++++- src/main/java/org/traccar/database/MailManager.java | 16 ++++++++++++---- src/main/java/org/traccar/model/Server.java | 10 ++++++++-- .../org/traccar/notificators/NotificatorMail.java | 19 ++++++++++++++----- 7 files changed, 52 insertions(+), 25 deletions(-) (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/Context.java b/src/main/java/org/traccar/Context.java index 42a92f436..cba4c0a58 100644 --- a/src/main/java/org/traccar/Context.java +++ b/src/main/java/org/traccar/Context.java @@ -27,7 +27,6 @@ import org.traccar.database.DataManager; import org.traccar.database.DeviceManager; import org.traccar.database.GroupsManager; import org.traccar.database.IdentityManager; -import org.traccar.database.MailManager; import org.traccar.database.NotificationManager; import org.traccar.database.PermissionsManager; import org.traccar.database.UsersManager; @@ -80,12 +79,6 @@ public final class Context { return dataManager; } - private static MailManager mailManager; - - public static MailManager getMailManager() { - return mailManager; - } - private static UsersManager usersManager; public static UsersManager getUsersManager() { @@ -178,8 +171,6 @@ public final class Context { dataManager = new DataManager(config); } - mailManager = new MailManager(); - if (dataManager != null) { usersManager = new UsersManager(dataManager); groupsManager = new GroupsManager(dataManager); diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java index 91d994153..7df25c264 100644 --- a/src/main/java/org/traccar/api/resource/PasswordResource.java +++ b/src/main/java/org/traccar/api/resource/PasswordResource.java @@ -18,12 +18,14 @@ package org.traccar.api.resource; import org.apache.velocity.VelocityContext; import org.traccar.Context; import org.traccar.api.BaseResource; +import org.traccar.database.MailManager; import org.traccar.model.User; import org.traccar.notification.NotificationMessage; import org.traccar.notification.TextTemplateFormatter; import org.traccar.storage.StorageException; import javax.annotation.security.PermitAll; +import javax.inject.Inject; import javax.mail.MessagingException; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; @@ -41,6 +43,9 @@ public class PasswordResource extends BaseResource { private static final String PASSWORD_RESET_TOKEN = "passwordToken"; + @Inject + private MailManager mailManager; + @Path("reset") @PermitAll @POST @@ -56,7 +61,7 @@ public class PasswordResource extends BaseResource { velocityContext.put("token", token); NotificationMessage fullMessage = TextTemplateFormatter.formatMessage(velocityContext, "passwordReset", "full"); - Context.getMailManager().sendMessage(user, fullMessage.getSubject(), fullMessage.getBody()); + mailManager.sendMessage(user, fullMessage.getSubject(), fullMessage.getBody()); break; } } diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 3c1b8f715..3955f1d20 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -38,8 +38,8 @@ import javax.ws.rs.core.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Context; import org.traccar.api.BaseResource; +import org.traccar.database.MailManager; import org.traccar.helper.LogAction; import org.traccar.model.Event; import org.traccar.model.Position; @@ -80,6 +80,9 @@ public class ReportResource extends BaseResource { @Inject private TripsReportProvider tripsReportProvider; + @Inject + private MailManager mailManager; + private interface ReportExecutor { void execute(ByteArrayOutputStream stream) throws StorageException, IOException; } @@ -99,8 +102,7 @@ public class ReportResource extends BaseResource { stream.toByteArray(), "application/octet-stream"))); User user = permissionsService.getUser(userId); - Context.getMailManager().sendMessage( - user, "Report", "The report is in the attachment.", attachment); + mailManager.sendMessage(user, "Report", "The report is in the attachment.", attachment); } catch (StorageException | IOException | MessagingException e) { LOGGER.warn("Report failed", e); } diff --git a/src/main/java/org/traccar/api/resource/ServerResource.java b/src/main/java/org/traccar/api/resource/ServerResource.java index f238e8905..51a26825b 100644 --- a/src/main/java/org/traccar/api/resource/ServerResource.java +++ b/src/main/java/org/traccar/api/resource/ServerResource.java @@ -17,6 +17,7 @@ package org.traccar.api.resource; import org.traccar.Context; import org.traccar.api.BaseResource; +import org.traccar.database.MailManager; import org.traccar.helper.LogAction; import org.traccar.model.Server; import org.traccar.storage.Storage; @@ -46,10 +47,15 @@ public class ServerResource extends BaseResource { @Inject private Storage storage; + @Inject + private MailManager mailManager; + @PermitAll @GET public Server get() throws StorageException { - return storage.getObject(Server.class, new Request(new Columns.All())); + Server server = storage.getObject(Server.class, new Request(new Columns.All())); + server.setEmailEnabled(mailManager.getEmailEnabled()); + return server; } @PUT diff --git a/src/main/java/org/traccar/database/MailManager.java b/src/main/java/org/traccar/database/MailManager.java index 21fee5ee7..54f617d5f 100644 --- a/src/main/java/org/traccar/database/MailManager.java +++ b/src/main/java/org/traccar/database/MailManager.java @@ -18,11 +18,12 @@ package org.traccar.database; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.traccar.Context; import org.traccar.Main; +import org.traccar.config.Config; import org.traccar.model.User; import org.traccar.notification.PropertiesProvider; +import javax.inject.Inject; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; @@ -40,6 +41,13 @@ public final class MailManager { private static final Logger LOGGER = LoggerFactory.getLogger(MailManager.class); + private final Config config; + + @Inject + public MailManager(Config config) { + this.config = config; + } + private static Properties getProperties(PropertiesProvider provider) { Properties properties = new Properties(); String host = provider.getString("mail.smtp.host"); @@ -88,7 +96,7 @@ public final class MailManager { } public boolean getEmailEnabled() { - return Context.getConfig().hasKey("mail.smtp.host"); + return config.hasKey("mail.smtp.host"); } public void sendMessage( @@ -99,11 +107,11 @@ public final class MailManager { public void sendMessage( User user, String subject, String body, MimeBodyPart attachment) throws MessagingException { Properties properties = null; - if (!Context.getConfig().getBoolean("mail.smtp.ignoreUserConfig")) { + if (!config.getBoolean("mail.smtp.ignoreUserConfig")) { properties = getProperties(new PropertiesProvider(user)); } if (properties == null || !properties.containsKey("mail.smtp.host")) { - properties = getProperties(new PropertiesProvider(Context.getConfig())); + properties = getProperties(new PropertiesProvider(config)); } if (!properties.containsKey("mail.smtp.host")) { LOGGER.warn("No SMTP configuration found"); diff --git a/src/main/java/org/traccar/model/Server.java b/src/main/java/org/traccar/model/Server.java index 7cffd7eac..c5640fb97 100644 --- a/src/main/java/org/traccar/model/Server.java +++ b/src/main/java/org/traccar/model/Server.java @@ -16,7 +16,6 @@ package org.traccar.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.traccar.Context; import org.traccar.storage.QueryIgnore; import org.traccar.storage.StorageName; @@ -193,9 +192,16 @@ public class Server extends ExtendedModel implements UserRestrictions { return getClass().getPackage().getImplementationVersion(); } + private boolean emailEnabled; + + @QueryIgnore + public void setEmailEnabled(boolean emailEnabled) { + this.emailEnabled = emailEnabled; + } + @QueryIgnore public Boolean getEmailEnabled() { - return Context.getMailManager().getEmailEnabled(); + return emailEnabled; } } diff --git a/src/main/java/org/traccar/notificators/NotificatorMail.java b/src/main/java/org/traccar/notificators/NotificatorMail.java index fd7cae7c3..fe8d69af2 100644 --- a/src/main/java/org/traccar/notificators/NotificatorMail.java +++ b/src/main/java/org/traccar/notificators/NotificatorMail.java @@ -16,8 +16,7 @@ */ package org.traccar.notificators; -import org.traccar.Context; -import org.traccar.Main; +import org.traccar.database.MailManager; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.model.User; @@ -26,16 +25,26 @@ import org.traccar.notification.MessageException; import org.traccar.notification.NotificationFormatter; import org.traccar.session.cache.CacheManager; +import javax.inject.Inject; import javax.mail.MessagingException; -public final class NotificatorMail implements Notificator { +public class NotificatorMail implements Notificator { + + private final MailManager mailManager; + private final CacheManager cacheManager; + + @Inject + public NotificatorMail(MailManager mailManager, CacheManager cacheManager) { + this.mailManager = mailManager; + this.cacheManager = cacheManager; + } @Override public void send(User user, Event event, Position position) throws MessageException { try { NotificationMessage fullMessage = NotificationFormatter.formatMessage( - Main.getInjector().getInstance(CacheManager.class), user, event, position, "full"); - Context.getMailManager().sendMessage(user, fullMessage.getSubject(), fullMessage.getBody()); + cacheManager, user, event, position, "full"); + mailManager.sendMessage(user, fullMessage.getSubject(), fullMessage.getBody()); } catch (MessagingException e) { throw new MessageException(e); } -- cgit v1.2.3 From 0b463a40998baf05cc84cb4400ab58e6e11c909d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Mon, 4 Jul 2022 15:25:03 -0700 Subject: Additional report endpoints --- .../org/traccar/api/resource/ReportResource.java | 221 ++++++++++++++------- 1 file changed, 154 insertions(+), 67 deletions(-) (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 3955f1d20..6176013c1 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -16,26 +16,6 @@ */ package org.traccar.api.resource; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Collection; -import java.util.Date; -import java.util.List; - -import javax.activation.DataHandler; -import javax.inject.Inject; -import javax.mail.MessagingException; -import javax.mail.internet.MimeBodyPart; -import javax.mail.util.ByteArrayDataSource; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.api.BaseResource; @@ -46,15 +26,38 @@ import org.traccar.model.Position; import org.traccar.model.User; import org.traccar.model.UserRestrictions; import org.traccar.reports.EventsReportProvider; +import org.traccar.reports.RouteReportProvider; +import org.traccar.reports.StopsReportProvider; import org.traccar.reports.SummaryReportProvider; import org.traccar.reports.TripsReportProvider; import org.traccar.reports.model.StopReportItem; import org.traccar.reports.model.SummaryReportItem; import org.traccar.reports.model.TripReportItem; -import org.traccar.reports.RouteReportProvider; -import org.traccar.reports.StopsReportProvider; import org.traccar.storage.StorageException; +import javax.activation.DataHandler; +import javax.inject.Inject; +import javax.mail.MessagingException; +import javax.mail.internet.MimeBodyPart; +import javax.mail.util.ByteArrayDataSource; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collection; +import java.util.Date; +import java.util.List; + @Path("reports") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @@ -62,8 +65,7 @@ public class ReportResource extends BaseResource { private static final Logger LOGGER = LoggerFactory.getLogger(ReportResource.class); - private static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; - private static final String CONTENT_DISPOSITION_VALUE_XLSX = "attachment; filename=report.xlsx"; + private static final String EXCEL = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; @Inject private EventsReportProvider eventsReportProvider; @@ -84,19 +86,18 @@ public class ReportResource extends BaseResource { private MailManager mailManager; private interface ReportExecutor { - void execute(ByteArrayOutputStream stream) throws StorageException, IOException; + void execute(OutputStream stream) throws StorageException, IOException; } private Response executeReport( - long userId, boolean mail, ReportExecutor executor) throws StorageException, IOException { - final ByteArrayOutputStream stream = new ByteArrayOutputStream(); + long userId, boolean mail, ReportExecutor executor) { if (mail) { new Thread(() -> { try { + var stream = new ByteArrayOutputStream(); executor.execute(stream); MimeBodyPart attachment = new MimeBodyPart(); - attachment.setFileName("report.xlsx"); attachment.setDataHandler(new DataHandler(new ByteArrayDataSource( stream.toByteArray(), "application/octet-stream"))); @@ -109,17 +110,25 @@ public class ReportResource extends BaseResource { }).start(); return Response.noContent().build(); } else { - executor.execute(stream); - return Response.ok(stream.toByteArray()) - .header(HttpHeaders.CONTENT_DISPOSITION, CONTENT_DISPOSITION_VALUE_XLSX).build(); + StreamingOutput stream = output -> { + try { + executor.execute(output); + } catch (StorageException e) { + throw new WebApplicationException(e); + } + }; + return Response.ok(stream) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=report.xlsx").build(); } } @Path("route") @GET public Collection getRoute( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); return routeReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to); @@ -127,11 +136,13 @@ public class ReportResource extends BaseResource { @Path("route") @GET - @Produces(XLSX) + @Produces(EXCEL) public Response getRouteExcel( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws StorageException, IOException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("mail") boolean mail) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "route", from, to, deviceIds, groupIds); @@ -139,12 +150,26 @@ public class ReportResource extends BaseResource { }); } + @Path("route/{type:xlsx|mail}") + @GET + @Produces(EXCEL) + public Response getRouteExcel( + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") final List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @PathParam("type") String type) throws StorageException { + return getRouteExcel(deviceIds, groupIds, from, to, type.equals("mail")); + } + @Path("events") @GET public Collection getEvents( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("type") final List types, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("type") List types, + @QueryParam("from") Date from, + @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); return eventsReportProvider.getObjects(getUserId(), deviceIds, groupIds, types, from, to); @@ -152,12 +177,14 @@ public class ReportResource extends BaseResource { @Path("events") @GET - @Produces(XLSX) + @Produces(EXCEL) public Response getEventsExcel( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("type") final List types, - @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws StorageException, IOException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("type") List types, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("mail") boolean mail) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "events", from, to, deviceIds, groupIds); @@ -165,12 +192,27 @@ public class ReportResource extends BaseResource { }); } + @Path("events/{type:xlsx|mail}") + @GET + @Produces(EXCEL) + public Response getEventsExcel( + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("type") List types, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @PathParam("type") String type) throws StorageException { + return getEventsExcel(deviceIds, groupIds, types, from, to, type.equals("mail")); + } + @Path("summary") @GET public Collection getSummary( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily) - throws StorageException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("daily") boolean daily) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); return summaryReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to, daily); @@ -178,12 +220,14 @@ public class ReportResource extends BaseResource { @Path("summary") @GET - @Produces(XLSX) + @Produces(EXCEL) public Response getSummaryExcel( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("daily") boolean daily, - @QueryParam("mail") boolean mail) - throws StorageException, IOException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("daily") boolean daily, + @QueryParam("mail") boolean mail) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "summary", from, to, deviceIds, groupIds); @@ -191,12 +235,26 @@ public class ReportResource extends BaseResource { }); } + @Path("summary/{type:xlsx|mail}") + @GET + @Produces(EXCEL) + public Response getSummaryExcel( + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("daily") boolean daily, + @PathParam("type") String type) throws StorageException { + return getSummaryExcel(deviceIds, groupIds, from, to, daily, type.equals("mail")); + } + @Path("trips") @GET - @Produces(MediaType.APPLICATION_JSON) public Collection getTrips( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); return tripsReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to); @@ -204,11 +262,13 @@ public class ReportResource extends BaseResource { @Path("trips") @GET - @Produces(XLSX) + @Produces(EXCEL) public Response getTripsExcel( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws StorageException, IOException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("mail") boolean mail) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "trips", from, to, deviceIds, groupIds); @@ -216,12 +276,25 @@ public class ReportResource extends BaseResource { }); } + @Path("trips/{type:xlsx|mail}") + @GET + @Produces(EXCEL) + public Response getTripsExcel( + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @PathParam("type") String type) throws StorageException { + return getTripsExcel(deviceIds, groupIds, from, to, type.equals("mail")); + } + @Path("stops") @GET - @Produces(MediaType.APPLICATION_JSON) public Collection getStops( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to) throws StorageException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); return stopsReportProvider.getObjects(getUserId(), deviceIds, groupIds, from, to); @@ -229,11 +302,13 @@ public class ReportResource extends BaseResource { @Path("stops") @GET - @Produces(XLSX) + @Produces(EXCEL) public Response getStopsExcel( - @QueryParam("deviceId") final List deviceIds, @QueryParam("groupId") final List groupIds, - @QueryParam("from") Date from, @QueryParam("to") Date to, @QueryParam("mail") boolean mail) - throws StorageException, IOException { + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @QueryParam("mail") boolean mail) throws StorageException { permissionsService.checkRestriction(getUserId(), UserRestrictions::getDisableReports); return executeReport(getUserId(), mail, stream -> { LogAction.logReport(getUserId(), "stops", from, to, deviceIds, groupIds); @@ -241,4 +316,16 @@ public class ReportResource extends BaseResource { }); } + @Path("stops/{type:xlsx|mail}") + @GET + @Produces(EXCEL) + public Response getStopsExcel( + @QueryParam("deviceId") List deviceIds, + @QueryParam("groupId") List groupIds, + @QueryParam("from") Date from, + @QueryParam("to") Date to, + @PathParam("type") String type) throws StorageException { + return getStopsExcel(deviceIds, groupIds, from, to, type.equals("mail")); + } + } -- cgit v1.2.3 From 8f129e2a70abbea66f33213c84b7e63f9e96035a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 26 Jul 2022 17:12:51 -0700 Subject: Testing mail manager --- debug.xml | 2 + src/main/java/org/traccar/MainModule.java | 12 ++++++ .../org/traccar/api/resource/PasswordResource.java | 2 +- .../org/traccar/api/resource/ReportResource.java | 2 +- .../org/traccar/api/resource/ServerResource.java | 2 +- src/main/java/org/traccar/config/Keys.java | 7 ++++ src/main/java/org/traccar/mail/LogMailManager.java | 44 ++++++++++++++++++++++ src/main/java/org/traccar/mail/MailManager.java | 31 +++++++++++++++ .../java/org/traccar/mail/SmtpMailManager.java | 2 - .../org/traccar/notificators/NotificatorMail.java | 2 +- 10 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/traccar/mail/LogMailManager.java create mode 100644 src/main/java/org/traccar/mail/MailManager.java (limited to 'src/main/java/org/traccar/api/resource/ReportResource.java') diff --git a/debug.xml b/debug.xml index a597d83c5..b38b4f9ac 100644 --- a/debug.xml +++ b/debug.xml @@ -16,6 +16,8 @@ true true + true + org.h2.Driver jdbc:h2:./target/database sa diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index b9543af25..b8ff21472 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -63,6 +63,9 @@ import org.traccar.handler.GeocoderHandler; import org.traccar.handler.GeolocationHandler; import org.traccar.handler.SpeedLimitHandler; import org.traccar.helper.SanitizerModule; +import org.traccar.mail.LogMailManager; +import org.traccar.mail.MailManager; +import org.traccar.mail.SmtpMailManager; import org.traccar.notification.EventForwarder; import org.traccar.session.cache.CacheManager; import org.traccar.sms.HttpSmsClient; @@ -128,6 +131,15 @@ public class MainModule extends AbstractModule { return null; } + @Provides + public static MailManager provideMailManager(Config config, StatisticsManager statisticsManager) { + if (config.getBoolean(Keys.MAIL_DEBUG)) { + return new LogMailManager(); + } else { + return new SmtpMailManager(config, statisticsManager); + } + } + @Singleton @Provides public static LdapProvider provideLdapProvider(Config config) { diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java index 643471797..88906e7e6 100644 --- a/src/main/java/org/traccar/api/resource/PasswordResource.java +++ b/src/main/java/org/traccar/api/resource/PasswordResource.java @@ -16,7 +16,7 @@ package org.traccar.api.resource; import org.traccar.api.BaseResource; -import org.traccar.database.MailManager; +import org.traccar.mail.MailManager; import org.traccar.model.User; import org.traccar.notification.TextTemplateFormatter; import org.traccar.storage.StorageException; diff --git a/src/main/java/org/traccar/api/resource/ReportResource.java b/src/main/java/org/traccar/api/resource/ReportResource.java index 6176013c1..70177dd4d 100644 --- a/src/main/java/org/traccar/api/resource/ReportResource.java +++ b/src/main/java/org/traccar/api/resource/ReportResource.java @@ -19,7 +19,7 @@ package org.traccar.api.resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.traccar.api.BaseResource; -import org.traccar.database.MailManager; +import org.traccar.mail.MailManager; import org.traccar.helper.LogAction; import org.traccar.model.Event; import org.traccar.model.Position; diff --git a/src/main/java/org/traccar/api/resource/ServerResource.java b/src/main/java/org/traccar/api/resource/ServerResource.java index 4fc76a0d7..e35cd7d95 100644 --- a/src/main/java/org/traccar/api/resource/ServerResource.java +++ b/src/main/java/org/traccar/api/resource/ServerResource.java @@ -16,7 +16,7 @@ package org.traccar.api.resource; import org.traccar.api.BaseResource; -import org.traccar.database.MailManager; +import org.traccar.mail.MailManager; import org.traccar.geocoder.Geocoder; import org.traccar.helper.Log; import org.traccar.helper.LogAction; diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 2190f82f7..e97e104a1 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -800,6 +800,13 @@ public final class Keys { List.of(KeyType.CONFIG), "templates"); + /** + * Log emails instead of sending them via SMTP. Intended for testing purposes only. + */ + public static final ConfigKey MAIL_DEBUG = new BooleanConfigKey( + "mail.debug", + List.of(KeyType.CONFIG)); + /** * Force SMTP settings from the config file and ignore user attributes. */ diff --git a/src/main/java/org/traccar/mail/LogMailManager.java b/src/main/java/org/traccar/mail/LogMailManager.java new file mode 100644 index 000000000..b6b912d6c --- /dev/null +++ b/src/main/java/org/traccar/mail/LogMailManager.java @@ -0,0 +1,44 @@ +/* + * Copyright 2022 Anton Tananaev (anton@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.mail; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.traccar.model.User; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeBodyPart; + +public class LogMailManager implements MailManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(LogMailManager.class); + + @Override + public boolean getEmailEnabled() { + return true; + } + + @Override + public void sendMessage(User user, String subject, String body) throws MessagingException { + sendMessage(user, subject, body, null); + } + + @Override + public void sendMessage(User user, String subject, String body, MimeBodyPart attachment) throws MessagingException { + LOGGER.info("\nTo: " + user.getEmail() + "\nSubject: " + subject + "\nBody:\n" + body); + } + +} diff --git a/src/main/java/org/traccar/mail/MailManager.java b/src/main/java/org/traccar/mail/MailManager.java new file mode 100644 index 000000000..69efbed32 --- /dev/null +++ b/src/main/java/org/traccar/mail/MailManager.java @@ -0,0 +1,31 @@ +/* + * Copyright 2022 Anton Tananaev (anton@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.mail; + +import org.traccar.model.User; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeBodyPart; + +public interface MailManager { + + boolean getEmailEnabled(); + + void sendMessage(User user, String subject, String body) throws MessagingException; + + void sendMessage(User user, String subject, String body, MimeBodyPart attachment) throws MessagingException; + +} diff --git a/src/main/java/org/traccar/mail/SmtpMailManager.java b/src/main/java/org/traccar/mail/SmtpMailManager.java index 7763c86cc..4a0b7048f 100644 --- a/src/main/java/org/traccar/mail/SmtpMailManager.java +++ b/src/main/java/org/traccar/mail/SmtpMailManager.java @@ -23,7 +23,6 @@ import org.traccar.database.StatisticsManager; import org.traccar.model.User; import org.traccar.notification.PropertiesProvider; -import javax.inject.Inject; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; @@ -45,7 +44,6 @@ public final class SmtpMailManager implements MailManager { private final Config config; private final StatisticsManager statisticsManager; - @Inject public SmtpMailManager(Config config, StatisticsManager statisticsManager) { this.config = config; this.statisticsManager = statisticsManager; diff --git a/src/main/java/org/traccar/notificators/NotificatorMail.java b/src/main/java/org/traccar/notificators/NotificatorMail.java index 647832166..75571cfc4 100644 --- a/src/main/java/org/traccar/notificators/NotificatorMail.java +++ b/src/main/java/org/traccar/notificators/NotificatorMail.java @@ -16,7 +16,7 @@ */ package org.traccar.notificators; -import org.traccar.database.MailManager; +import org.traccar.mail.MailManager; import org.traccar.model.Event; import org.traccar.model.Position; import org.traccar.model.User; -- cgit v1.2.3