aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/database
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r--src/org/traccar/database/DataManager.java101
-rw-r--r--src/org/traccar/database/GroupTree.java153
-rw-r--r--src/org/traccar/database/PermissionsManager.java56
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");
}
}