From 1f2328bd8f4e341dda897fcd52418beb6cf1b83a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 8 Mar 2016 22:05:40 +1300 Subject: Add new and update old data models --- src/org/traccar/database/DataManager.java | 6 +++--- src/org/traccar/database/PermissionsManager.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 73984952e..f040ecd20 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -39,7 +39,7 @@ import org.traccar.Config; import org.traccar.helper.Log; import org.traccar.model.Device; import org.traccar.model.MiscFormatter; -import org.traccar.model.Permission; +import org.traccar.model.DevicePermission; import org.traccar.model.Position; import org.traccar.model.Server; import org.traccar.model.User; @@ -221,9 +221,9 @@ public class DataManager implements IdentityManager { .executeUpdate(); } - public Collection getPermissions() throws SQLException { + public Collection getPermissions() throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.getPermissionsAll")) - .executeQuery(Permission.class); + .executeQuery(DevicePermission.class); } public Collection getAllDevices() throws SQLException { diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index c676dea23..29228ceeb 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -22,7 +22,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import org.traccar.helper.Log; -import org.traccar.model.Permission; +import org.traccar.model.DevicePermission; import org.traccar.model.Server; import org.traccar.model.User; @@ -56,7 +56,7 @@ public class PermissionsManager { for (User user : dataManager.getUsers()) { users.put(user.getId(), user); } - for (Permission permission : dataManager.getPermissions()) { + for (DevicePermission permission : dataManager.getPermissions()) { getPermissions(permission.getUserId()).add(permission.getDeviceId()); } } catch (SQLException error) { -- cgit v1.2.3 From 8cd4f224572e55cd3c87119db24b8adcf1f0351a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 8 Mar 2016 22:41:32 +1300 Subject: Start refactoring permissions manager --- src/org/traccar/database/PermissionsManager.java | 32 ++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 29228ceeb..854732fa2 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2015 - 2016 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,13 +34,21 @@ public class PermissionsManager { private final Map users = new HashMap<>(); - private final Map> permissions = new HashMap<>(); + private final Map> groupPermissions = new HashMap<>(); + private final Map> devicePermissions = new HashMap<>(); - private Set getPermissions(long userId) { - if (!permissions.containsKey(userId)) { - permissions.put(userId, new HashSet()); + private Set getGroupPermissions(long userId) { + if (!groupPermissions.containsKey(userId)) { + groupPermissions.put(userId, new HashSet()); } - return permissions.get(userId); + return groupPermissions.get(userId); + } + + private Set getDevicePermissions(long userId) { + if (!devicePermissions.containsKey(userId)) { + devicePermissions.put(userId, new HashSet()); + } + return devicePermissions.get(userId); } public PermissionsManager(DataManager dataManager) { @@ -50,14 +58,14 @@ public class PermissionsManager { public final void refresh() { users.clear(); - permissions.clear(); + devicePermissions.clear(); try { server = dataManager.getServer(); for (User user : dataManager.getUsers()) { users.put(user.getId(), user); } for (DevicePermission permission : dataManager.getPermissions()) { - getPermissions(permission.getUserId()).add(permission.getDeviceId()); + getDevicePermissions(permission.getUserId()).add(permission.getDeviceId()); } } catch (SQLException error) { Log.warning(error); @@ -80,12 +88,16 @@ public class PermissionsManager { } } + public Collection allowedGroups(long userId) { + return getGroupPermissions(userId); + } + public Collection allowedDevices(long userId) { - return getPermissions(userId); + return getDevicePermissions(userId); } public void checkDevice(long userId, long deviceId) throws SecurityException { - if (!getPermissions(userId).contains(deviceId)) { + if (!getDevicePermissions(userId).contains(deviceId)) { throw new SecurityException("Device access denied"); } } -- cgit v1.2.3 From 3e76be5531f89fb906598435096e3eff54f86944 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 8 Mar 2016 23:31:06 +1300 Subject: Add group queries and recourse --- debug.xml | 20 +++++++++ .../api/resource/GroupPermissionResource.java | 52 ++++++++++++++++++++++ src/org/traccar/database/DataManager.java | 35 ++++++++++++++- 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/org/traccar/api/resource/GroupPermissionResource.java (limited to 'src/org/traccar/database') diff --git a/debug.xml b/debug.xml index eb2038cd5..102272cb3 100644 --- a/debug.xml +++ b/debug.xml @@ -149,6 +149,26 @@ DELETE FROM user_device WHERE userId = :userId AND deviceId = :deviceId; + + INSERT INTO groups (name) VALUES (:name); + + + + UPDATE groups SET name = :name WHERE id = :id; + + + + DELETE FROM groups WHERE id = :id; + + + + INSERT INTO user_group (userId, groupId) VALUES (:userId, :groupId); + + + + DELETE FROM user_group WHERE userId = :userId AND groupId = :groupId; + + SELECT * FROM positions WHERE deviceId = :deviceId AND fixTime BETWEEN :from AND :to ORDER BY fixTime; diff --git a/src/org/traccar/api/resource/GroupPermissionResource.java b/src/org/traccar/api/resource/GroupPermissionResource.java new file mode 100644 index 000000000..b8ec4ae3c --- /dev/null +++ b/src/org/traccar/api/resource/GroupPermissionResource.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * 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.resource; + +import org.traccar.Context; +import org.traccar.api.BaseResource; +import org.traccar.model.GroupPermission; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +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; + +@Path("permissions/groups") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class GroupPermissionResource extends BaseResource { + + @POST + public Response add(GroupPermission entity) throws SQLException { + Context.getPermissionsManager().checkAdmin(getUserId()); + Context.getDataManager().linkGroup(entity.getUserId(), entity.getGroupId()); + Context.getPermissionsManager().refresh(); + return Response.ok(entity).build(); + } + + @DELETE + public Response remove(GroupPermission entity) throws SQLException { + Context.getPermissionsManager().checkAdmin(getUserId()); + Context.getDataManager().unlinkGroup(entity.getUserId(), entity.getGroupId()); + Context.getPermissionsManager().refresh(); + return Response.noContent().build(); + } + +} diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index f040ecd20..5b4524f2e 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2012 - 2016 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,7 @@ import liquibase.resource.ResourceAccessor; import org.traccar.Config; import org.traccar.helper.Log; import org.traccar.model.Device; +import org.traccar.model.Group; import org.traccar.model.MiscFormatter; import org.traccar.model.DevicePermission; import org.traccar.model.Position; @@ -286,6 +287,38 @@ public class DataManager implements IdentityManager { AsyncServlet.sessionRefreshUser(userId); } + public void addGroup(Group group) throws SQLException { + group.setId(QueryBuilder.create(dataSource, getQuery("database.insertGroup"), true) + .setObject(group) + .executeUpdate()); + } + + public void updateGroup(Group group) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.updateGroup")) + .setObject(group) + .executeUpdate(); + } + + public void removeGroup(long groupId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.deleteGroup")) + .setLong("id", groupId) + .executeUpdate(); + } + + public void linkGroup(long userId, long groupId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkGroup")) + .setLong("userId", userId) + .setLong("groupId", groupId) + .executeUpdate(); + } + + public void unlinkGroup(long userId, long groupId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkGroup")) + .setLong("userId", userId) + .setLong("groupId", groupId) + .executeUpdate(); + } + public Collection getPositions(long deviceId, Date from, Date to) throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.selectPositions")) .setLong("deviceId", deviceId) -- cgit v1.2.3 From 2879646bc58467939349c367a7763cd1eb11fde2 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 8 Mar 2016 23:38:48 +1300 Subject: Add select group permissions query --- debug.xml | 6 +++++- src/org/traccar/database/DataManager.java | 10 ++++++++-- src/org/traccar/database/PermissionsManager.java | 6 +++++- 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src/org/traccar/database') diff --git a/debug.xml b/debug.xml index 102272cb3..413c020eb 100644 --- a/debug.xml +++ b/debug.xml @@ -113,10 +113,14 @@ DELETE FROM users WHERE id = :id; - + SELECT userId, deviceId FROM user_device; + + SELECT userId, groupId FROM user_group; + + SELECT * FROM devices; diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 5b4524f2e..9a8a14615 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -39,6 +39,7 @@ import org.traccar.Config; import org.traccar.helper.Log; import org.traccar.model.Device; import org.traccar.model.Group; +import org.traccar.model.GroupPermission; import org.traccar.model.MiscFormatter; import org.traccar.model.DevicePermission; import org.traccar.model.Position; @@ -222,11 +223,16 @@ public class DataManager implements IdentityManager { .executeUpdate(); } - public Collection getPermissions() throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.getPermissionsAll")) + public Collection getDevicePermissions() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectDevicePermissions")) .executeQuery(DevicePermission.class); } + public Collection getGroupPermissions() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGroupPermissions")) + .executeQuery(GroupPermission.class); + } + public Collection getAllDevices() throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.selectDevicesAll")) .executeQuery(Device.class); diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 854732fa2..0ed8227b4 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; import org.traccar.helper.Log; import org.traccar.model.DevicePermission; +import org.traccar.model.GroupPermission; import org.traccar.model.Server; import org.traccar.model.User; @@ -64,9 +65,12 @@ public class PermissionsManager { for (User user : dataManager.getUsers()) { users.put(user.getId(), user); } - for (DevicePermission permission : dataManager.getPermissions()) { + for (DevicePermission permission : dataManager.getDevicePermissions()) { getDevicePermissions(permission.getUserId()).add(permission.getDeviceId()); } + for (GroupPermission permission : dataManager.getGroupPermissions()) { + getGroupPermissions(permission.getUserId()).add(permission.getGroupId()); + } } catch (SQLException error) { Log.warning(error); } -- cgit v1.2.3 From d4825d57fc27384288d9f3e1c1dd9e4bd7e29160 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 9 Mar 2016 16:09:00 +1300 Subject: Implement API resource for groups --- debug.xml | 8 +- src/org/traccar/api/AsyncSocket.java | 2 +- src/org/traccar/api/resource/GroupResource.java | 85 ++++++++++++++++++++++ src/org/traccar/api/resource/PositionResource.java | 2 +- src/org/traccar/database/DataManager.java | 52 +++++++++++-- src/org/traccar/database/PermissionsManager.java | 14 ++-- src/org/traccar/web/AsyncServlet.java | 2 +- 7 files changed, 144 insertions(+), 21 deletions(-) create mode 100644 src/org/traccar/api/resource/GroupResource.java (limited to 'src/org/traccar/database') diff --git a/debug.xml b/debug.xml index 413c020eb..2266a1eea 100644 --- a/debug.xml +++ b/debug.xml @@ -125,10 +125,6 @@ SELECT * FROM devices; - - SELECT * FROM devices d INNER JOIN user_device ud ON d.id = ud.deviceId WHERE ud.userId = :userId; - - INSERT INTO devices (name, uniqueId) VALUES (:name, :uniqueId); @@ -153,6 +149,10 @@ DELETE FROM user_device WHERE userId = :userId AND deviceId = :deviceId; + + SELECT * FROM groups; + + INSERT INTO groups (name) VALUES (:name); diff --git a/src/org/traccar/api/AsyncSocket.java b/src/org/traccar/api/AsyncSocket.java index 96ad2c450..c289367ea 100644 --- a/src/org/traccar/api/AsyncSocket.java +++ b/src/org/traccar/api/AsyncSocket.java @@ -36,7 +36,7 @@ public class AsyncSocket extends WebSocketAdapter implements ConnectionManager.U private Collection devices; public AsyncSocket(long userId) { - devices = Context.getPermissionsManager().allowedDevices(userId); + devices = Context.getPermissionsManager().getDevicePermissions(userId); } @Override diff --git a/src/org/traccar/api/resource/GroupResource.java b/src/org/traccar/api/resource/GroupResource.java new file mode 100644 index 000000000..49f839499 --- /dev/null +++ b/src/org/traccar/api/resource/GroupResource.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * 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.resource; + +import org.traccar.Context; +import org.traccar.api.BaseResource; +import org.traccar.model.Device; +import org.traccar.model.Group; + +import javax.ws.rs.Consumes; +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.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; + +@Path("groups") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class GroupResource extends BaseResource { + + @GET + public Collection get( + @QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException { + if (all) { + Context.getPermissionsManager().checkAdmin(getUserId()); + return Context.getDataManager().getAllGroups(); + } else { + if (userId == 0) { + userId = getUserId(); + } + Context.getPermissionsManager().checkUser(getUserId(), userId); + return Context.getDataManager().getGroups(userId); + } + } + + @POST + public Response add(Group entity) throws SQLException { + Context.getPermissionsManager().checkReadonly(getUserId()); + Context.getDataManager().addGroup(entity); + Context.getDataManager().linkGroup(getUserId(), entity.getId()); + Context.getPermissionsManager().refresh(); + return Response.ok(entity).build(); + } + + @Path("{id}") + @PUT + public Response update(@PathParam("id") long id, Group entity) throws SQLException { + Context.getPermissionsManager().checkReadonly(getUserId()); + Context.getPermissionsManager().checkGroup(getUserId(), id); + Context.getDataManager().updateGroup(entity); + return Response.ok(entity).build(); + } + + @Path("{id}") + @DELETE + public Response remove(@PathParam("id") long id) throws SQLException { + Context.getPermissionsManager().checkReadonly(getUserId()); + Context.getPermissionsManager().checkGroup(getUserId(), id); + Context.getDataManager().removeGroup(id); + Context.getPermissionsManager().refresh(); + return Response.noContent().build(); + } + +} diff --git a/src/org/traccar/api/resource/PositionResource.java b/src/org/traccar/api/resource/PositionResource.java index b9e8e877e..9c174625c 100644 --- a/src/org/traccar/api/resource/PositionResource.java +++ b/src/org/traccar/api/resource/PositionResource.java @@ -40,7 +40,7 @@ public class PositionResource extends BaseResource { throws SQLException { if (deviceId == 0) { return Context.getConnectionManager().getInitialState( - Context.getPermissionsManager().allowedDevices(getUserId())); + Context.getPermissionsManager().getDevicePermissions(getUserId())); } else { Context.getPermissionsManager().checkDevice(getUserId(), deviceId); return Context.getDataManager().getPositions( diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 9a8a14615..d2da4e701 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; @@ -36,6 +37,7 @@ import liquibase.exception.LiquibaseException; import liquibase.resource.FileSystemResourceAccessor; import liquibase.resource.ResourceAccessor; import org.traccar.Config; +import org.traccar.Context; import org.traccar.helper.Log; import org.traccar.model.Device; import org.traccar.model.Group; @@ -55,10 +57,14 @@ public class DataManager implements IdentityManager { private DataSource dataSource; + private final long dataRefreshDelay; + private final Map devicesById = new HashMap<>(); private final Map devicesByUniqueId = new HashMap<>(); private long devicesLastUpdate; - private final long devicesRefreshDelay; + + private final Map groupsById = new HashMap<>(); + private long groupsLastUpdate; public DataManager(Config config) throws Exception { this.config = config; @@ -66,7 +72,7 @@ public class DataManager implements IdentityManager { initDatabase(); initDatabaseSchema(); - devicesRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000; + dataRefreshDelay = config.getLong("database.refreshDelay", DEFAULT_REFRESH_DELAY) * 1000; } public DataSource getDataSource() { @@ -114,7 +120,7 @@ public class DataManager implements IdentityManager { } private void updateDeviceCache(boolean force) throws SQLException { - if (System.currentTimeMillis() - devicesLastUpdate > devicesRefreshDelay || force) { + if (System.currentTimeMillis() - devicesLastUpdate > dataRefreshDelay || force) { devicesById.clear(); devicesByUniqueId.clear(); for (Device device : getAllDevices()) { @@ -142,6 +148,25 @@ public class DataManager implements IdentityManager { return devicesByUniqueId.get(uniqueId); } + private void updateGroupCache(boolean force) throws SQLException { + if (System.currentTimeMillis() - groupsLastUpdate > dataRefreshDelay || force) { + groupsById.clear(); + for (Group group : getAllGroups()) { + groupsById.put(group.getId(), group); + } + groupsLastUpdate = System.currentTimeMillis(); + } + } + + public Group getGroupById(long id) { + try { + updateGroupCache(!groupsById.containsKey(id)); + } catch (SQLException e) { + Log.warning(e); + } + return groupsById.get(id); + } + private String getQuery(String key) { String query = config.getString(key); if (query == null) { @@ -239,9 +264,11 @@ public class DataManager implements IdentityManager { } public Collection getDevices(long userId) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectDevices")) - .setLong("userId", userId) - .executeQuery(Device.class); + Collection devices = new ArrayList<>(); + for (long id : Context.getPermissionsManager().getDevicePermissions(userId)) { + devices.add(getDeviceById(id)); + } + return devices; } public void addDevice(Device device) throws SQLException { @@ -293,6 +320,19 @@ public class DataManager implements IdentityManager { AsyncServlet.sessionRefreshUser(userId); } + public Collection getAllGroups() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGroupsAll")) + .executeQuery(Group.class); + } + + public Collection getGroups(long userId) throws SQLException { + Collection groups = new ArrayList<>(); + for (long id : Context.getPermissionsManager().getGroupPermissions(userId)) { + groups.add(getGroupById(id)); + } + return groups; + } + public void addGroup(Group group) throws SQLException { group.setId(QueryBuilder.create(dataSource, getQuery("database.insertGroup"), true) .setObject(group) diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 0ed8227b4..5d6430764 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -38,14 +38,14 @@ public class PermissionsManager { private final Map> groupPermissions = new HashMap<>(); private final Map> devicePermissions = new HashMap<>(); - private Set getGroupPermissions(long userId) { + public Set getGroupPermissions(long userId) { if (!groupPermissions.containsKey(userId)) { groupPermissions.put(userId, new HashSet()); } return groupPermissions.get(userId); } - private Set getDevicePermissions(long userId) { + public Set getDevicePermissions(long userId) { if (!devicePermissions.containsKey(userId)) { devicePermissions.put(userId, new HashSet()); } @@ -92,12 +92,10 @@ public class PermissionsManager { } } - public Collection allowedGroups(long userId) { - return getGroupPermissions(userId); - } - - public Collection allowedDevices(long userId) { - return getDevicePermissions(userId); + public void checkGroup(long userId, long groupId) throws SecurityException { + if (!getGroupPermissions(userId).contains(groupId)) { + throw new SecurityException("Group access denied"); + } } public void checkDevice(long userId, long deviceId) throws SecurityException { diff --git a/src/org/traccar/web/AsyncServlet.java b/src/org/traccar/web/AsyncServlet.java index b10df5408..e4cb64c57 100644 --- a/src/org/traccar/web/AsyncServlet.java +++ b/src/org/traccar/web/AsyncServlet.java @@ -226,7 +226,7 @@ public class AsyncServlet extends BaseServlet { synchronized (ASYNC_SESSIONS) { if (Boolean.parseBoolean(req.getParameter("first")) || !ASYNC_SESSIONS.containsKey(userId)) { - Collection devices = Context.getPermissionsManager().allowedDevices(userId); + Collection devices = Context.getPermissionsManager().getDevicePermissions(userId); ASYNC_SESSIONS.put(userId, new AsyncSession(userId, devices)); } -- cgit v1.2.3 From c22cc6982a18eb3601fdc8fb8447b5a2ba73690a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 9 Mar 2016 21:48:59 +1300 Subject: Implement group editing dialog --- debug.xml | 2 +- src/org/traccar/database/PermissionsManager.java | 1 + web/app/view/GroupDialog.js | 36 ++++++++++++++++++++++++ web/app/view/GroupsController.js | 32 ++++++++++----------- web/l10n/en.json | 1 + 5 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 web/app/view/GroupDialog.js (limited to 'src/org/traccar/database') diff --git a/debug.xml b/debug.xml index 2266a1eea..ce7c3190a 100644 --- a/debug.xml +++ b/debug.xml @@ -14,7 +14,7 @@ web true true - 10000 + 30000 true nominatim diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 5d6430764..022691b1b 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -59,6 +59,7 @@ public class PermissionsManager { public final void refresh() { users.clear(); + groupPermissions.clear(); devicePermissions.clear(); try { server = dataManager.getServer(); diff --git a/web/app/view/GroupDialog.js b/web/app/view/GroupDialog.js new file mode 100644 index 000000000..a34e33aa0 --- /dev/null +++ b/web/app/view/GroupDialog.js @@ -0,0 +1,36 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * 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. + */ + +Ext.define('Traccar.view.GroupDialog', { + extend: 'Traccar.view.BaseEditDialog', + + requires: [ + 'Traccar.view.BaseEditDialogController' + ], + + controller: 'baseEditDialog', + title: Strings.groupDialog, + + items: { + xtype: 'form', + items: [{ + xtype: 'textfield', + name: 'name', + fieldLabel: Strings.sharedName, + allowBlank: false + }] + } +}); diff --git a/web/app/view/GroupsController.js b/web/app/view/GroupsController.js index 619e0c50e..34b259658 100644 --- a/web/app/view/GroupsController.js +++ b/web/app/view/GroupsController.js @@ -23,25 +23,26 @@ Ext.define('Traccar.view.GroupsController', { }, onAddClick: function () { - /*var user, dialog; - user = Ext.create('Traccar.model.User'); - dialog = Ext.create('Traccar.view.UserDialog'); - dialog.down('form').loadRecord(user); - dialog.show();*/ + var group, dialog; + group = Ext.create('Traccar.model.Group'); + group.store = this.getView().getStore(); + dialog = Ext.create('Traccar.view.GroupDialog'); + dialog.down('form').loadRecord(group); + dialog.show(); }, onEditClick: function () { - /*var user, dialog; - user = this.getView().getSelectionModel().getSelection()[0]; - dialog = Ext.create('Traccar.view.UserDialog'); - dialog.down('form').loadRecord(user); - dialog.show();*/ + var group, dialog; + group = this.getView().getSelectionModel().getSelection()[0]; + dialog = Ext.create('Traccar.view.GroupDialog'); + dialog.down('form').loadRecord(group); + dialog.show(); }, onRemoveClick: function () { - /*var user = this.getView().getSelectionModel().getSelection()[0]; + var group = this.getView().getSelectionModel().getSelection()[0]; Ext.Msg.show({ - title: Strings.settingsUser, + title: Strings.groupDialog, message: Strings.sharedRemoveConfirm, buttons: Ext.Msg.YESNO, buttonText: { @@ -49,19 +50,18 @@ Ext.define('Traccar.view.GroupsController', { no: Strings.sharedCancel }, fn: function (btn) { - var store = Ext.getStore('Users'); + var store = Ext.getStore('Groups'); if (btn === 'yes') { - store.remove(user); + store.remove(group); store.sync(); } } - });*/ + }); }, onSelectionChange: function (selected) { var disabled = selected.length > 0; this.lookupReference('toolbarEditButton').setDisabled(disabled); this.lookupReference('toolbarRemoveButton').setDisabled(disabled); - this.lookupReference('userDevicesButton').setDisabled(disabled); } }); diff --git a/web/l10n/en.json b/web/l10n/en.json index 259d54b1a..715dce3a7 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -34,6 +34,7 @@ "deviceLastUpdate": "Last Update", "deviceCommand": "Command", "deviceFollow": "Follow", + "groupDialog": "Group", "settingsTitle": "Settings", "settingsUser": "Account", "settingsGroups": "Groups", -- cgit v1.2.3 From 222265e0c884d06158426e7d0ca033127cecb22f Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 10 Mar 2016 15:29:26 +1300 Subject: Implement group tree structure --- src/org/traccar/database/GroupTree.java | 106 +++++++++++++++++++++++++++ test/org/traccar/database/GroupTreeTest.java | 37 ++++++++++ 2 files changed, 143 insertions(+) create mode 100644 src/org/traccar/database/GroupTree.java create mode 100644 test/org/traccar/database/GroupTreeTest.java (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/GroupTree.java b/src/org/traccar/database/GroupTree.java new file mode 100644 index 000000000..7263a6331 --- /dev/null +++ b/src/org/traccar/database/GroupTree.java @@ -0,0 +1,106 @@ +/* + * Copyright 2016 Anton Tananaev (anton.tananaev@gmail.com) + * + * 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.Group; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class GroupTree { + + private static class GroupNode { + + private Group group; + private GroupNode parent; + private Collection children = new HashSet<>(); + + public GroupNode(Group group) { + this.group = group; + } + + @Override + public int hashCode() { + return (int) group.getId(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof GroupNode)) { + return false; + } + return obj == this || group.getId() == ((GroupNode) obj).group.getId(); + } + + public Group getGroup() { + return group; + } + + public void setParent(GroupNode parent) { + this.parent = parent; + if (parent != null) { + parent.children.add(this); + } + } + + public GroupNode getParent() { + return parent; + } + + public Collection getChildren() { + return children; + } + + } + + private final Map groupMap = new HashMap<>(); + + public GroupTree(Collection groups) { + + for (Group group : groups) { + groupMap.put(group.getId(), new GroupNode(group)); + } + + for (GroupNode node : groupMap.values()) { + if (node.getGroup().getGroupId() != 0) { + node.setParent(groupMap.get(node.getGroup().getGroupId())); + } + } + + } + + public Collection getDescendants(long groupId) { + Set results = new HashSet<>(); + getDescendants(results, groupMap.get(groupId)); + Collection groups = new ArrayList<>(); + for (GroupNode node : results) { + groups.add(node.getGroup()); + } + return groups; + } + + private void getDescendants(Set results, GroupNode node) { + for (GroupNode child : node.getChildren()) { + results.add(child); + getDescendants(results, child); + } + } + +} diff --git a/test/org/traccar/database/GroupTreeTest.java b/test/org/traccar/database/GroupTreeTest.java new file mode 100644 index 000000000..26ac595f8 --- /dev/null +++ b/test/org/traccar/database/GroupTreeTest.java @@ -0,0 +1,37 @@ +package org.traccar.database; + +import org.junit.Assert; +import org.junit.Test; +import org.traccar.model.Group; + +import java.util.ArrayList; +import java.util.Collection; + +public class GroupTreeTest { + + private static Group createGroup(long id, String name, long parent) { + Group group = new Group(); + group.setId(id); + group.setName(name); + group.setGroupId(parent); + return group; + } + + @Test + public void testGetDescendants() { + Collection groups = new ArrayList<>(); + groups.add(createGroup(1, "First", 0)); + groups.add(createGroup(2, "Second", 1)); + groups.add(createGroup(3, "Third", 2)); + groups.add(createGroup(4, "Fourth", 2)); + groups.add(createGroup(5, "Fifth", 4)); + + GroupTree groupTree = new GroupTree(groups); + + Assert.assertEquals(4, groupTree.getDescendants(1).size()); + Assert.assertEquals(3, groupTree.getDescendants(2).size()); + Assert.assertEquals(0, groupTree.getDescendants(3).size()); + Assert.assertEquals(1, groupTree.getDescendants(4).size()); + } + +} -- cgit v1.2.3 From d940a84da87bcf4c164344fa7018cbf96ca1a920 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 10 Mar 2016 17:03:37 +1300 Subject: Expand group permissions in manager --- src/org/traccar/database/PermissionsManager.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 022691b1b..0aefb9605 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -22,7 +22,9 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import org.traccar.helper.Log; +import org.traccar.model.Device; import org.traccar.model.DevicePermission; +import org.traccar.model.Group; import org.traccar.model.GroupPermission; import org.traccar.model.Server; import org.traccar.model.User; @@ -66,12 +68,24 @@ public class PermissionsManager { for (User user : dataManager.getUsers()) { users.put(user.getId(), user); } + + GroupTree groupTree = new GroupTree(dataManager.getAllGroups()); + for (GroupPermission permission : dataManager.getGroupPermissions()) { + Set userGroupPermissions = getGroupPermissions(permission.getUserId()); + userGroupPermissions.add(permission.getGroupId()); + for (Group group : groupTree.getDescendants(permission.getGroupId())) { + userGroupPermissions.add(group.getId()); + } + } + for (DevicePermission permission : dataManager.getDevicePermissions()) { getDevicePermissions(permission.getUserId()).add(permission.getDeviceId()); } - for (GroupPermission permission : dataManager.getGroupPermissions()) { - getGroupPermissions(permission.getUserId()).add(permission.getGroupId()); + + for (Device device : dataManager.getAllDevices()) { + // TODO } + } catch (SQLException error) { Log.warning(error); } -- cgit v1.2.3 From 5e2ad583f62db56fe81ec4c41756fb3fc28747a5 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 11 Mar 2016 16:22:40 +1300 Subject: Add devices to group tree --- src/org/traccar/database/GroupTree.java | 99 +++++++++++++++++------- src/org/traccar/database/PermissionsManager.java | 13 ++-- test/org/traccar/database/GroupTreeTest.java | 30 +++++-- 3 files changed, 103 insertions(+), 39 deletions(-) (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/GroupTree.java b/src/org/traccar/database/GroupTree.java index 7263a6331..b383b1501 100644 --- a/src/org/traccar/database/GroupTree.java +++ b/src/org/traccar/database/GroupTree.java @@ -15,6 +15,7 @@ */ package org.traccar.database; +import org.traccar.model.Device; import org.traccar.model.Group; import java.util.ArrayList; @@ -26,80 +27,126 @@ import java.util.Set; public class GroupTree { - private static class GroupNode { + private static class TreeNode { private Group group; - private GroupNode parent; - private Collection children = new HashSet<>(); + private Device device; + private Collection children = new HashSet<>(); - public GroupNode(Group group) { + public TreeNode(Group group) { this.group = group; } + public TreeNode(Device device) { + this.device = device; + } + @Override public int hashCode() { - return (int) group.getId(); + if (group != null) { + return (int) group.getId(); + } else { + return (int) device.getId(); + } } @Override public boolean equals(Object obj) { - if (!(obj instanceof GroupNode)) { + if (!(obj instanceof TreeNode)) { return false; } - return obj == this || group.getId() == ((GroupNode) obj).group.getId(); + TreeNode other = (TreeNode) obj; + if (other == this) { + return true; + } + if (group != null) { + if (other.group != null) { + return group.getId() == other.group.getId(); + } + } else if (device != null) { + if (other.device != null) { + return device.getId() == other.device.getId(); + } + } + return false; } public Group getGroup() { return group; } - public void setParent(GroupNode parent) { - this.parent = parent; + public Device getDevice() { + return device; + } + + public void setParent(TreeNode parent) { if (parent != null) { parent.children.add(this); } } - public GroupNode getParent() { - return parent; - } - - public Collection getChildren() { + public Collection getChildren() { return children; } } - private final Map groupMap = new HashMap<>(); + private final Map groupMap = new HashMap<>(); - public GroupTree(Collection groups) { + public GroupTree(Collection groups, Collection devices) { for (Group group : groups) { - groupMap.put(group.getId(), new GroupNode(group)); + groupMap.put(group.getId(), new TreeNode(group)); } - for (GroupNode node : groupMap.values()) { + for (TreeNode node : groupMap.values()) { if (node.getGroup().getGroupId() != 0) { node.setParent(groupMap.get(node.getGroup().getGroupId())); } } + Map deviceMap = new HashMap<>(); + + for (Device device : devices) { + deviceMap.put(device.getId(), new TreeNode(device)); + } + + for (TreeNode node : deviceMap.values()) { + if (node.getDevice().getGroupId() != 0) { + node.setParent(groupMap.get(node.getDevice().getGroupId())); + } + } + } - public Collection getDescendants(long groupId) { - Set results = new HashSet<>(); - getDescendants(results, groupMap.get(groupId)); + public Collection getGroups(long groupId) { + Set results = new HashSet<>(); + getNodes(results, groupMap.get(groupId)); Collection groups = new ArrayList<>(); - for (GroupNode node : results) { - groups.add(node.getGroup()); + for (TreeNode node : results) { + if (node.getGroup() != null) { + groups.add(node.getGroup()); + } } return groups; } - private void getDescendants(Set results, GroupNode node) { - for (GroupNode child : node.getChildren()) { + public Collection getDevices(long groupId) { + Set results = new HashSet<>(); + getNodes(results, groupMap.get(groupId)); + Collection devices = new ArrayList<>(); + for (TreeNode node : results) { + if (node.getDevice() != null) { + devices.add(node.getDevice()); + } + } + return devices; + } + + private void getNodes(Set results, TreeNode node) { + for (TreeNode child : node.getChildren()) { results.add(child); - getDescendants(results, child); + getNodes(results, child); } } diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index 0aefb9605..dc37bbc84 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -16,7 +16,6 @@ package org.traccar.database; import java.sql.SQLException; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -69,23 +68,23 @@ public class PermissionsManager { users.put(user.getId(), user); } - GroupTree groupTree = new GroupTree(dataManager.getAllGroups()); + GroupTree groupTree = new GroupTree(dataManager.getAllGroups(), dataManager.getAllDevices()); for (GroupPermission permission : dataManager.getGroupPermissions()) { Set userGroupPermissions = getGroupPermissions(permission.getUserId()); + Set userDevicePermissions = getDevicePermissions(permission.getUserId()); userGroupPermissions.add(permission.getGroupId()); - for (Group group : groupTree.getDescendants(permission.getGroupId())) { + for (Group group : groupTree.getGroups(permission.getGroupId())) { userGroupPermissions.add(group.getId()); } + for (Device device : groupTree.getDevices(permission.getGroupId())) { + userDevicePermissions.add(device.getId()); + } } for (DevicePermission permission : dataManager.getDevicePermissions()) { getDevicePermissions(permission.getUserId()).add(permission.getDeviceId()); } - for (Device device : dataManager.getAllDevices()) { - // TODO - } - } catch (SQLException error) { Log.warning(error); } diff --git a/test/org/traccar/database/GroupTreeTest.java b/test/org/traccar/database/GroupTreeTest.java index 26ac595f8..f73cb75b6 100644 --- a/test/org/traccar/database/GroupTreeTest.java +++ b/test/org/traccar/database/GroupTreeTest.java @@ -2,6 +2,7 @@ package org.traccar.database; import org.junit.Assert; import org.junit.Test; +import org.traccar.model.Device; import org.traccar.model.Group; import java.util.ArrayList; @@ -16,7 +17,15 @@ public class GroupTreeTest { group.setGroupId(parent); return group; } - + + private static Device createDevice(long id, String name, long parent) { + Device device = new Device(); + device.setId(id); + device.setName(name); + device.setGroupId(parent); + return device; + } + @Test public void testGetDescendants() { Collection groups = new ArrayList<>(); @@ -26,12 +35,21 @@ public class GroupTreeTest { groups.add(createGroup(4, "Fourth", 2)); groups.add(createGroup(5, "Fifth", 4)); - GroupTree groupTree = new GroupTree(groups); + Collection devices = new ArrayList<>(); + devices.add(createDevice(1, "One", 3)); + devices.add(createDevice(2, "Two", 5)); + devices.add(createDevice(3, "One", 5)); + + GroupTree groupTree = new GroupTree(groups, devices); + + Assert.assertEquals(4, groupTree.getGroups(1).size()); + Assert.assertEquals(3, groupTree.getGroups(2).size()); + Assert.assertEquals(0, groupTree.getGroups(3).size()); + Assert.assertEquals(1, groupTree.getGroups(4).size()); - Assert.assertEquals(4, groupTree.getDescendants(1).size()); - Assert.assertEquals(3, groupTree.getDescendants(2).size()); - Assert.assertEquals(0, groupTree.getDescendants(3).size()); - Assert.assertEquals(1, groupTree.getDescendants(4).size()); + Assert.assertEquals(3, groupTree.getDevices(1).size()); + Assert.assertEquals(1, groupTree.getDevices(3).size()); + Assert.assertEquals(2, groupTree.getDevices(4).size()); } } -- cgit v1.2.3