From 6c17f85d04b224ff2a09265918765c9f4fc8cf94 Mon Sep 17 00:00:00 2001 From: Abyss777 Date: Wed, 10 May 2017 13:27:49 +0500 Subject: Implement computed attributes --- src/org/traccar/database/AttributesManager.java | 199 +++++++++++++++++++++++ src/org/traccar/database/DataManager.java | 84 ++++++++++ src/org/traccar/database/PermissionsManager.java | 12 ++ 3 files changed, 295 insertions(+) create mode 100644 src/org/traccar/database/AttributesManager.java (limited to 'src/org/traccar/database') diff --git a/src/org/traccar/database/AttributesManager.java b/src/org/traccar/database/AttributesManager.java new file mode 100644 index 000000000..362d6130f --- /dev/null +++ b/src/org/traccar/database/AttributesManager.java @@ -0,0 +1,199 @@ +/* + * Copyright 2017 Anton Tananaev (anton@traccar.org) + * Copyright 2017 Andrey Kunitsyn (andrey@traccar.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.database; + +import java.sql.SQLException; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.traccar.Context; +import org.traccar.helper.Log; +import org.traccar.model.AttributePermission; +import org.traccar.model.Attribute; +import org.traccar.model.Device; +import org.traccar.model.DeviceAttribute; +import org.traccar.model.GroupAttribute; + +public class AttributesManager { + + private final DataManager dataManager; + + private final Map attributes = new ConcurrentHashMap<>(); + private final Map> deviceAttributes = new ConcurrentHashMap<>(); + private final Map> deviceAttributesWithGroups = new ConcurrentHashMap<>(); + private final Map> groupAttributes = new ConcurrentHashMap<>(); + private final Map> userAttributes = new ConcurrentHashMap<>(); + + public AttributesManager(DataManager dataManager) { + this.dataManager = dataManager; + refreshAttributes(); + } + + public Set getUserAttributes(long userId) { + if (!userAttributes.containsKey(userId)) { + userAttributes.put(userId, new HashSet()); + } + return userAttributes.get(userId); + } + + public Set getGroupAttributes(long groupId) { + if (!groupAttributes.containsKey(groupId)) { + groupAttributes.put(groupId, new HashSet()); + } + return groupAttributes.get(groupId); + } + + public Set getDeviceAttributes(long deviceId) { + return getDeviceAttributes(deviceAttributes, deviceId); + } + + public Set getAllDeviceAttributes(long deviceId) { + return getDeviceAttributes(deviceAttributesWithGroups, deviceId); + } + + private Set getDeviceAttributes(Map> deviceAttributes, long deviceId) { + if (!deviceAttributes.containsKey(deviceId)) { + deviceAttributes.put(deviceId, new HashSet()); + } + return deviceAttributes.get(deviceId); + } + + public final void refreshAttributes() { + if (dataManager != null) { + try { + attributes.clear(); + for (Attribute attribute : dataManager.getAttributes()) { + attributes.put(attribute.getId(), attribute); + } + } catch (SQLException error) { + Log.warning(error); + } + } + refreshUserAttributes(); + refresh(); + } + + public final void refreshUserAttributes() { + if (dataManager != null) { + try { + userAttributes.clear(); + for (AttributePermission attributePermission : dataManager.getAttributePermissions()) { + getUserAttributes(attributePermission.getUserId()).add(attributePermission.getAttributeId()); + } + } catch (SQLException error) { + Log.warning(error); + } + } + } + + public final void refresh() { + if (dataManager != null) { + try { + + Collection databaseGroupAttributes = dataManager.getGroupAttributes(); + + groupAttributes.clear(); + for (GroupAttribute groupAttribute : databaseGroupAttributes) { + getGroupAttributes(groupAttribute.getGroupId()).add(groupAttribute.getAttributeId()); + } + + Collection databaseDeviceAttributes = dataManager.getDeviceAttributes(); + Collection allDevices = Context.getDeviceManager().getAllDevices(); + + deviceAttributes.clear(); + deviceAttributesWithGroups.clear(); + + for (DeviceAttribute deviceAttribute : databaseDeviceAttributes) { + getDeviceAttributes(deviceAttribute.getDeviceId()) + .add(deviceAttribute.getAttributeId()); + getAllDeviceAttributes(deviceAttribute.getDeviceId()) + .add(deviceAttribute.getAttributeId()); + } + + for (Device device : allDevices) { + long groupId = device.getGroupId(); + while (groupId != 0) { + getAllDeviceAttributes(device.getId()).addAll(getGroupAttributes(groupId)); + if (Context.getDeviceManager().getGroupById(groupId) != null) { + groupId = Context.getDeviceManager().getGroupById(groupId).getGroupId(); + } else { + groupId = 0; + } + } + } + + } catch (SQLException error) { + Log.warning(error); + } + } + } + + public void addAttribute(Attribute attribute) throws SQLException { + dataManager.addAttribute(attribute); + attributes.put(attribute.getId(), attribute); + } + + public void updateAttribute(Attribute attribute) throws SQLException { + dataManager.updateAttribute(attribute); + Attribute cachedAttribute = attributes.get(attribute.getId()); + cachedAttribute.setDescription(attribute.getDescription()); + cachedAttribute.setAttribute(attribute.getAttribute()); + cachedAttribute.setExpression(attribute.getExpression()); + cachedAttribute.setType(attribute.getType()); + } + + public void removeAttribute(long computedAttributeId) throws SQLException { + dataManager.removeAttribute(computedAttributeId); + attributes.remove(computedAttributeId); + refreshUserAttributes(); + refresh(); + } + + public boolean checkAttribute(long userId, long attributeId) { + return getUserAttributes(userId).contains(attributeId); + } + + public Attribute getAttribute(long id) { + return attributes.get(id); + } + + public final Collection getAttributes(Set attributeIds) { + Collection result = new LinkedList<>(); + for (long attributeId : attributeIds) { + result.add(getAttribute(attributeId)); + } + return result; + } + + public final Set getAllAttributes() { + return attributes.keySet(); + } + + public final Set getManagedAttributes(long userId) { + Set attributes = new HashSet<>(); + attributes.addAll(getUserAttributes(userId)); + for (long managedUserId : Context.getPermissionsManager().getUserPermissions(userId)) { + attributes.addAll(getUserAttributes(managedUserId)); + } + return attributes; + } + +} diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java index 0c5f458a2..acbaac17b 100644 --- a/src/org/traccar/database/DataManager.java +++ b/src/org/traccar/database/DataManager.java @@ -37,13 +37,17 @@ import liquibase.resource.ResourceAccessor; import org.traccar.Config; import org.traccar.helper.Log; import org.traccar.model.AttributeAlias; +import org.traccar.model.AttributePermission; import org.traccar.model.Calendar; import org.traccar.model.CalendarPermission; +import org.traccar.model.Attribute; import org.traccar.model.Device; +import org.traccar.model.DeviceAttribute; import org.traccar.model.DevicePermission; import org.traccar.model.Event; import org.traccar.model.Geofence; import org.traccar.model.Group; +import org.traccar.model.GroupAttribute; import org.traccar.model.GroupGeofence; import org.traccar.model.GroupPermission; import org.traccar.model.Notification; @@ -548,4 +552,84 @@ public class DataManager { .executeUpdate(); } + public Collection getAttributes() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectAttributes")) + .executeQuery(Attribute.class); + } + + public void addAttribute(Attribute attribute) throws SQLException { + attribute.setId(QueryBuilder.create(dataSource, getQuery("database.insertAttribute"), true) + .setObject(attribute) + .executeUpdate()); + } + + public void updateAttribute(Attribute attribute) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.updateAttribute")) + .setObject(attribute) + .executeUpdate(); + } + + public void removeAttribute(long computedAttributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.deleteAttribute")) + .setLong("id", computedAttributeId) + .executeUpdate(); + } + + public Collection getAttributePermissions() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectAttributePermissions")) + .executeQuery(AttributePermission.class); + } + + public void linkAttribute(long userId, long attributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkAttribute")) + .setLong("userId", userId) + .setLong("attributeId", attributeId) + .executeUpdate(); + } + + public void unlinkAttribute(long userId, long attributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkAttribute")) + .setLong("userId", userId) + .setLong("attributeId", attributeId) + .executeUpdate(); + } + + public Collection getGroupAttributes() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectGroupAttributes")) + .executeQuery(GroupAttribute.class); + } + + public void linkGroupAttribute(long groupId, long attributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkGroupAttribute")) + .setLong("groupId", groupId) + .setLong("attributeId", attributeId) + .executeUpdate(); + } + + public void unlinkGroupAttribute(long groupId, long attributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkGroupAttribute")) + .setLong("groupId", groupId) + .setLong("attributeId", attributeId) + .executeUpdate(); + } + + public Collection getDeviceAttributes() throws SQLException { + return QueryBuilder.create(dataSource, getQuery("database.selectDeviceAttributes")) + .executeQuery(DeviceAttribute.class); + } + + public void linkDeviceAttribute(long deviceId, long attributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.linkDeviceAttribute")) + .setLong("deviceId", deviceId) + .setLong("attributeId", attributeId) + .executeUpdate(); + } + + public void unlinkDeviceAttribute(long deviceId, long attributeId) throws SQLException { + QueryBuilder.create(dataSource, getQuery("database.unlinkDeviceAttribute")) + .setLong("deviceId", deviceId) + .setLong("attributeId", attributeId) + .executeUpdate(); + } + } diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java index e4bd6f5db..11f147c7c 100644 --- a/src/org/traccar/database/PermissionsManager.java +++ b/src/org/traccar/database/PermissionsManager.java @@ -310,6 +310,18 @@ public class PermissionsManager { } } + public void checkAttribute(long userId, long attributeId) throws SecurityException { + if (!Context.getAttributesManager().checkAttribute(userId, attributeId) && !isAdmin(userId)) { + checkManager(userId); + for (long managedUserId : getUserPermissions(userId)) { + if (Context.getAttributesManager().checkAttribute(managedUserId, attributeId)) { + return; + } + } + throw new SecurityException("Attribute access denied"); + } + } + public void checkCalendar(long userId, long calendarId) throws SecurityException { if (!Context.getCalendarManager().checkCalendar(userId, calendarId) && !isAdmin(userId)) { checkManager(userId); -- cgit v1.2.3