diff options
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r-- | src/org/traccar/database/DataManager.java | 101 | ||||
-rw-r--r-- | src/org/traccar/database/GroupTree.java | 153 | ||||
-rw-r--r-- | src/org/traccar/database/PermissionsManager.java | 56 |
3 files changed, 285 insertions, 25 deletions
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 73984952e..d2da4e701 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. @@ -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,10 +37,13 @@ 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; +import org.traccar.model.GroupPermission; 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; @@ -53,10 +57,14 @@ public class DataManager implements IdentityManager { private DataSource dataSource; + private final long dataRefreshDelay; + private final Map<Long, Device> devicesById = new HashMap<>(); private final Map<String, Device> devicesByUniqueId = new HashMap<>(); private long devicesLastUpdate; - private final long devicesRefreshDelay; + + private final Map<Long, Group> groupsById = new HashMap<>(); + private long groupsLastUpdate; public DataManager(Config config) throws Exception { this.config = config; @@ -64,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() { @@ -112,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()) { @@ -140,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) { @@ -221,9 +248,14 @@ public class DataManager implements IdentityManager { .executeUpdate(); } - public Collection<Permission> getPermissions() throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.getPermissionsAll")) - .executeQuery(Permission.class); + public Collection<DevicePermission> getDevicePermissions() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectDevicePermissions")) + .executeQuery(DevicePermission.class); + } + + public Collection<GroupPermission> getGroupPermissions() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGroupPermissions")) + .executeQuery(GroupPermission.class); } public Collection<Device> getAllDevices() throws SQLException { @@ -232,9 +264,11 @@ public class DataManager implements IdentityManager { } public Collection<Device> getDevices(long userId) throws SQLException { - return QueryBuilder.create(dataSource, getQuery("database.selectDevices")) - .setLong("userId", userId) - .executeQuery(Device.class); + Collection<Device> devices = new ArrayList<>(); + for (long id : Context.getPermissionsManager().getDevicePermissions(userId)) { + devices.add(getDeviceById(id)); + } + return devices; } public void addDevice(Device device) throws SQLException { @@ -286,6 +320,51 @@ public class DataManager implements IdentityManager { AsyncServlet.sessionRefreshUser(userId); } + public Collection<Group> getAllGroups() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGroupsAll")) + .executeQuery(Group.class); + } + + public Collection<Group> getGroups(long userId) throws SQLException { + Collection<Group> 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) + .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<Position> getPositions(long deviceId, Date from, Date to) throws SQLException { return QueryBuilder.create(dataSource, getQuery("database.selectPositions")) .setLong("deviceId", deviceId) diff --git a/src/org/traccar/database/GroupTree.java b/src/org/traccar/database/GroupTree.java new file mode 100644 index 000000000..b383b1501 --- /dev/null +++ b/src/org/traccar/database/GroupTree.java @@ -0,0 +1,153 @@ +/* + * 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.Device; +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 TreeNode { + + private Group group; + private Device device; + private Collection<TreeNode> children = new HashSet<>(); + + public TreeNode(Group group) { + this.group = group; + } + + public TreeNode(Device device) { + this.device = device; + } + + @Override + public int hashCode() { + if (group != null) { + return (int) group.getId(); + } else { + return (int) device.getId(); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TreeNode)) { + return false; + } + 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 Device getDevice() { + return device; + } + + public void setParent(TreeNode parent) { + if (parent != null) { + parent.children.add(this); + } + } + + public Collection<TreeNode> getChildren() { + return children; + } + + } + + private final Map<Long, TreeNode> groupMap = new HashMap<>(); + + public GroupTree(Collection<Group> groups, Collection<Device> devices) { + + for (Group group : groups) { + groupMap.put(group.getId(), new TreeNode(group)); + } + + for (TreeNode node : groupMap.values()) { + if (node.getGroup().getGroupId() != 0) { + node.setParent(groupMap.get(node.getGroup().getGroupId())); + } + } + + Map<Long, TreeNode> 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<Group> getGroups(long groupId) { + Set<TreeNode> results = new HashSet<>(); + getNodes(results, groupMap.get(groupId)); + Collection<Group> groups = new ArrayList<>(); + for (TreeNode node : results) { + if (node.getGroup() != null) { + groups.add(node.getGroup()); + } + } + return groups; + } + + public Collection<Device> getDevices(long groupId) { + Set<TreeNode> results = new HashSet<>(); + getNodes(results, groupMap.get(groupId)); + Collection<Device> devices = new ArrayList<>(); + for (TreeNode node : results) { + if (node.getDevice() != null) { + devices.add(node.getDevice()); + } + } + return devices; + } + + private void getNodes(Set<TreeNode> results, TreeNode node) { + for (TreeNode child : node.getChildren()) { + results.add(child); + getNodes(results, child); + } + } + +} diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index c676dea23..dc37bbc84 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. @@ -16,13 +16,15 @@ package org.traccar.database; import java.sql.SQLException; -import java.util.Collection; import java.util.HashMap; 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.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; @@ -34,13 +36,21 @@ public class PermissionsManager { private final Map<Long, User> users = new HashMap<>(); - private final Map<Long, Set<Long>> permissions = new HashMap<>(); + private final Map<Long, Set<Long>> groupPermissions = new HashMap<>(); + private final Map<Long, Set<Long>> devicePermissions = new HashMap<>(); - private Set<Long> getPermissions(long userId) { - if (!permissions.containsKey(userId)) { - permissions.put(userId, new HashSet<Long>()); + public Set<Long> getGroupPermissions(long userId) { + if (!groupPermissions.containsKey(userId)) { + groupPermissions.put(userId, new HashSet<Long>()); } - return permissions.get(userId); + return groupPermissions.get(userId); + } + + public Set<Long> getDevicePermissions(long userId) { + if (!devicePermissions.containsKey(userId)) { + devicePermissions.put(userId, new HashSet<Long>()); + } + return devicePermissions.get(userId); } public PermissionsManager(DataManager dataManager) { @@ -50,15 +60,31 @@ public class PermissionsManager { public final void refresh() { users.clear(); - permissions.clear(); + groupPermissions.clear(); + devicePermissions.clear(); try { server = dataManager.getServer(); for (User user : dataManager.getUsers()) { users.put(user.getId(), user); } - for (Permission permission : dataManager.getPermissions()) { - getPermissions(permission.getUserId()).add(permission.getDeviceId()); + + GroupTree groupTree = new GroupTree(dataManager.getAllGroups(), dataManager.getAllDevices()); + for (GroupPermission permission : dataManager.getGroupPermissions()) { + Set<Long> userGroupPermissions = getGroupPermissions(permission.getUserId()); + Set<Long> userDevicePermissions = getDevicePermissions(permission.getUserId()); + userGroupPermissions.add(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()); } + } catch (SQLException error) { Log.warning(error); } @@ -80,12 +106,14 @@ public class PermissionsManager { } } - public Collection<Long> allowedDevices(long userId) { - return getPermissions(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 { - if (!getPermissions(userId).contains(deviceId)) { + if (!getDevicePermissions(userId).contains(deviceId)) { throw new SecurityException("Device access denied"); } } |