aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/database
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2017-01-18 00:33:59 +1300
committerGitHub <noreply@github.com>2017-01-18 00:33:59 +1300
commit2cdc0c93b759dfbdaff0c5577862b151d9aadf7f (patch)
treeb397ec630e858c76d7ea3ca29305def271f08f62 /src/org/traccar/database
parent09a5ceb7b1681cb50338f37f775e13a5121e4385 (diff)
parent68abcc05ddd3633167f4e1c45d0ae9cf05dbcc43 (diff)
downloadtraccar-server-2cdc0c93b759dfbdaff0c5577862b151d9aadf7f.tar.gz
traccar-server-2cdc0c93b759dfbdaff0c5577862b151d9aadf7f.tar.bz2
traccar-server-2cdc0c93b759dfbdaff0c5577862b151d9aadf7f.zip
Merge pull request #2801 from Abyss777/manager
Implement user management
Diffstat (limited to 'src/org/traccar/database')
-rw-r--r--src/org/traccar/database/CalendarManager.java14
-rw-r--r--src/org/traccar/database/DataManager.java22
-rw-r--r--src/org/traccar/database/DeviceManager.java20
-rw-r--r--src/org/traccar/database/GeofenceManager.java11
-rw-r--r--src/org/traccar/database/PermissionsManager.java123
5 files changed, 175 insertions, 15 deletions
diff --git a/src/org/traccar/database/CalendarManager.java b/src/org/traccar/database/CalendarManager.java
index 3e95f6698..31d484327 100644
--- a/src/org/traccar/database/CalendarManager.java
+++ b/src/org/traccar/database/CalendarManager.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2016 Anton Tananaev (anton@traccar.org)
- * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ * Copyright 2016 - 2017 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.
@@ -24,6 +24,7 @@ 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.Calendar;
import org.traccar.model.CalendarPermission;
@@ -69,6 +70,15 @@ public class CalendarManager {
return result;
}
+ public Collection<Calendar> getManagedCalendars(long userId) {
+ ArrayList<Calendar> result = new ArrayList<>();
+ result.addAll(getUserCalendars(userId));
+ for (long managedUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
+ result.addAll(getUserCalendars(managedUserId));
+ }
+ return result;
+ }
+
public final void refreshUserCalendars() {
if (dataManager != null) {
try {
diff --git a/src/org/traccar/database/DataManager.java b/src/org/traccar/database/DataManager.java
index 278109229..8337762f7 100644
--- a/src/org/traccar/database/DataManager.java
+++ b/src/org/traccar/database/DataManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2012 - 2017 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.
@@ -51,6 +51,7 @@ import org.traccar.model.Position;
import org.traccar.model.Server;
import org.traccar.model.Statistics;
import org.traccar.model.User;
+import org.traccar.model.UserPermission;
import org.traccar.model.DeviceGeofence;
import org.traccar.model.GeofencePermission;
@@ -527,4 +528,23 @@ public class DataManager {
.setLong("calendarId", calendarId)
.executeUpdate();
}
+
+ public Collection<UserPermission> getUserPermissions() throws SQLException {
+ return QueryBuilder.create(dataSource, getQuery("database.selectUserPermissions"))
+ .executeQuery(UserPermission.class);
+ }
+
+ public void linkUser(long userId, long managedUserId) throws SQLException {
+ QueryBuilder.create(dataSource, getQuery("database.linkUser"))
+ .setLong("userId", userId)
+ .setLong("managedUserId", managedUserId)
+ .executeUpdate();
+ }
+
+ public void unlinkUser(long userId, long managedUserId) throws SQLException {
+ QueryBuilder.create(dataSource, getQuery("database.unlinkUser"))
+ .setLong("userId", userId)
+ .setLong("managedUserId", managedUserId)
+ .executeUpdate();
+ }
}
diff --git a/src/org/traccar/database/DeviceManager.java b/src/org/traccar/database/DeviceManager.java
index c70e67231..8e75903db 100644
--- a/src/org/traccar/database/DeviceManager.java
+++ b/src/org/traccar/database/DeviceManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 - 2017 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.
@@ -160,6 +160,15 @@ public class DeviceManager implements IdentityManager {
return devices;
}
+ public Collection<Device> getManagedDevices(long userId) throws SQLException {
+ Collection<Device> devices = new ArrayList<>();
+ devices.addAll(getDevices(userId));
+ for (long managedUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
+ devices.addAll(getDevices(managedUserId));
+ }
+ return devices;
+ }
+
public void addDevice(Device device) throws SQLException {
dataManager.addDevice(device);
@@ -289,6 +298,15 @@ public class DeviceManager implements IdentityManager {
return groups;
}
+ public Collection<Group> getManagedGroups(long userId) throws SQLException {
+ Collection<Group> groups = new ArrayList<>();
+ groups.addAll(getGroups(userId));
+ for (long managedUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
+ groups.addAll(getGroups(managedUserId));
+ }
+ return groups;
+ }
+
private void checkGroupCycles(Group group) {
Set<Long> groups = new HashSet<>();
while (group != null) {
diff --git a/src/org/traccar/database/GeofenceManager.java b/src/org/traccar/database/GeofenceManager.java
index e2e0c12d4..b8e6a5d73 100644
--- a/src/org/traccar/database/GeofenceManager.java
+++ b/src/org/traccar/database/GeofenceManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 - 2017 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.
@@ -242,6 +242,15 @@ public class GeofenceManager {
}
}
+ public final Set<Long> getManagedGeofencesIds(long userId) {
+ Set<Long> geofences = new HashSet<>();
+ geofences.addAll(getUserGeofencesIds(userId));
+ for (long managedUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
+ geofences.addAll(getUserGeofencesIds(managedUserId));
+ }
+ return geofences;
+ }
+
public final Collection<Geofence> getGeofences(Set<Long> geofencesIds) {
geofencesLock.readLock().lock();
try {
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java
index 6c0610655..4a5f759a8 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/org/traccar/database/PermissionsManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2015 - 2017 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.
@@ -23,8 +23,10 @@ import org.traccar.model.Group;
import org.traccar.model.GroupPermission;
import org.traccar.model.Server;
import org.traccar.model.User;
+import org.traccar.model.UserPermission;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -47,6 +49,8 @@ public class PermissionsManager {
private final Map<Long, Set<Long>> deviceUsers = new HashMap<>();
private final Map<Long, Set<Long>> groupDevices = new HashMap<>();
+ private final Map<Long, Set<Long>> userPermissions = new HashMap<>();
+
public Set<Long> getGroupPermissions(long userId) {
if (!groupPermissions.containsKey(userId)) {
groupPermissions.put(userId, new HashSet<Long>());
@@ -75,10 +79,18 @@ public class PermissionsManager {
return groupDevices.get(groupId);
}
+ public Set<Long> getUserPermissions(long userId) {
+ if (!userPermissions.containsKey(userId)) {
+ userPermissions.put(userId, new HashSet<Long>());
+ }
+ return userPermissions.get(userId);
+ }
+
public PermissionsManager(DataManager dataManager) {
this.dataManager = dataManager;
refreshUsers();
refreshPermissions();
+ refreshUserPermissions();
}
public final void refreshUsers() {
@@ -97,6 +109,17 @@ public class PermissionsManager {
}
}
+ public final void refreshUserPermissions() {
+ userPermissions.clear();
+ try {
+ for (UserPermission permission : dataManager.getUserPermissions()) {
+ getUserPermissions(permission.getUserId()).add(permission.getManagedUserId());
+ }
+ } catch (SQLException error) {
+ Log.warning(error);
+ }
+ }
+
public final void refreshPermissions() {
groupPermissions.clear();
devicePermissions.clear();
@@ -146,6 +169,39 @@ public class PermissionsManager {
}
}
+ public boolean isManager(long userId) {
+ return users.containsKey(userId) && users.get(userId).getUserLimit() > 0;
+ }
+
+ public void checkManager(long userId) throws SecurityException {
+ if (!isManager(userId)) {
+ throw new SecurityException("Manager access required");
+ }
+ }
+
+ public void checkManager(long userId, long managedUserId) throws SecurityException {
+ checkManager(userId);
+ if (!userPermissions.get(userId).contains(managedUserId)) {
+ throw new SecurityException("User access denied");
+ }
+ }
+
+ public void checkUserLimit(long userId) throws SecurityException {
+ if (!isAdmin(userId) && userPermissions.get(userId).size() >= users.get(userId).getUserLimit()) {
+ throw new SecurityException("Manager user limit reached");
+ }
+ }
+
+ public void checkDeviceLimit(long userId) throws SecurityException {
+ int deviceLimit = users.get(userId).getDeviceLimit();
+ if (deviceLimit != 0) {
+ int deviceCount = getDevicePermissions(userId).size();
+ if (deviceCount >= deviceLimit) {
+ throw new SecurityException("User device limit reached");
+ }
+ }
+ }
+
public boolean isReadonly(long userId) {
return users.containsKey(userId) && users.get(userId).getReadonly();
}
@@ -168,29 +224,49 @@ public class PermissionsManager {
public void checkUserUpdate(long userId, User before, User after) throws SecurityException {
if (before.getAdmin() != after.getAdmin()
- || before.getReadonly() != after.getReadonly()
- || before.getDisabled() != after.getDisabled()
|| before.getDeviceLimit() != after.getDeviceLimit()
+ || before.getUserLimit() != after.getUserLimit()) {
+ checkAdmin(userId);
+ }
+ if (before.getReadonly() != after.getReadonly()
+ || before.getDisabled() != after.getDisabled()
|| !Objects.equals(before.getExpirationTime(), after.getExpirationTime())
|| !Objects.equals(before.getToken(), after.getToken())) {
- checkAdmin(userId);
+ if (userId == after.getId()) {
+ checkAdmin(userId);
+ }
+ if (!isAdmin(userId)) {
+ checkManager(userId);
+ }
}
}
- public void checkUser(long userId, long otherUserId) throws SecurityException {
- if (userId != otherUserId) {
- checkAdmin(userId);
+ public void checkUser(long userId, long managedUserId) throws SecurityException {
+ if (userId != managedUserId && !isAdmin(userId)) {
+ checkManager(userId, managedUserId);
}
}
public void checkGroup(long userId, long groupId) throws SecurityException {
- if (!getGroupPermissions(userId).contains(groupId)) {
+ if (!getGroupPermissions(userId).contains(groupId) && !isAdmin(userId)) {
+ checkManager(userId);
+ for (long managedUserId : getUserPermissions(userId)) {
+ if (getGroupPermissions(managedUserId).contains(groupId)) {
+ return;
+ }
+ }
throw new SecurityException("Group access denied");
}
}
public void checkDevice(long userId, long deviceId) throws SecurityException {
- if (!getDevicePermissions(userId).contains(deviceId)) {
+ if (!getDevicePermissions(userId).contains(deviceId) && !isAdmin(userId)) {
+ checkManager(userId);
+ for (long managedUserId : getUserPermissions(userId)) {
+ if (getDevicePermissions(managedUserId).contains(deviceId)) {
+ return;
+ }
+ }
throw new SecurityException("Device access denied");
}
}
@@ -203,12 +279,24 @@ public class PermissionsManager {
public void checkGeofence(long userId, long geofenceId) throws SecurityException {
if (!Context.getGeofenceManager().checkGeofence(userId, geofenceId) && !isAdmin(userId)) {
+ checkManager(userId);
+ for (long managedUserId : getUserPermissions(userId)) {
+ if (Context.getGeofenceManager().checkGeofence(managedUserId, geofenceId)) {
+ return;
+ }
+ }
throw new SecurityException("Geofence access denied");
}
}
public void checkCalendar(long userId, long calendarId) throws SecurityException {
if (!Context.getCalendarManager().checkCalendar(userId, calendarId) && !isAdmin(userId)) {
+ checkManager(userId);
+ for (long managedUserId : getUserPermissions(userId)) {
+ if (Context.getCalendarManager().checkCalendar(managedUserId, calendarId)) {
+ return;
+ }
+ }
throw new SecurityException("Calendar access denied");
}
}
@@ -222,10 +310,24 @@ public class PermissionsManager {
this.server = server;
}
- public Collection<User> getUsers() {
+ public Collection<User> getAllUsers() {
return users.values();
}
+ public Collection<User> getUsers(long userId) {
+ Collection<User> result = new ArrayList<>();
+ for (long managedUserId : getUserPermissions(userId)) {
+ result.add(users.get(managedUserId));
+ }
+ return result;
+ }
+
+ public Collection<User> getManagedUsers(long userId) {
+ Collection<User> result = getUsers(userId);
+ result.add(users.get(userId));
+ return result;
+ }
+
public User getUser(long userId) {
return users.get(userId);
}
@@ -257,6 +359,7 @@ public class PermissionsManager {
usersTokens.remove(users.get(userId).getToken());
users.remove(userId);
refreshPermissions();
+ refreshUserPermissions();
}
public User login(String email, String password) throws SQLException {