Initial manager implementation

This commit is contained in:
Abyss777
2017-01-13 09:26:52 +05:00
parent 3533a7c900
commit cffbce4b3b
18 changed files with 401 additions and 59 deletions

View File

@@ -48,5 +48,21 @@
<column name="network" type="VARCHAR(4000)" />
</addColumn>
<addColumn tableName="users">
<column name="userlimit" type="INT" defaultValueNumeric="0" />
</addColumn>
<createTable tableName="user_user">
<column name="userid" type="INT">
<constraints nullable="false" />
</column>
<column name="otheruserid" type="INT">
<constraints nullable="false" />
</column>
</createTable>
<addForeignKeyConstraint baseTableName="user_user" baseColumnNames="userid" constraintName="fk_user_user_userid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
<addForeignKeyConstraint baseTableName="user_user" baseColumnNames="otheruserid" constraintName="fk_user_user_otheruserid" referencedTableName="users" referencedColumnNames="id" onDelete="CASCADE" />
</changeSet>
</databaseChangeLog>

View File

@@ -64,14 +64,15 @@
</entry>
<entry key='database.insertUser'>
INSERT INTO users (name, email, hashedPassword, salt, admin, map, distanceUnit, speedUnit, latitude, longitude, zoom, twelveHourFormat, coordinateFormat, disabled, expirationTime, deviceLimit, token, attributes)
VALUES (:name, :email, :hashedPassword, :salt, :admin, :map, :distanceUnit, :speedUnit, :latitude, :longitude, :zoom, :twelveHourFormat, :coordinateFormat, :disabled, :expirationTime, :deviceLimit, :token, :attributes)
INSERT INTO users (name, email, hashedPassword, salt, readonly, admin, map, distanceUnit, speedUnit, latitude, longitude, zoom, twelveHourFormat, coordinateFormat, disabled, expirationTime, deviceLimit, userLimit, token, attributes)
VALUES (:name, :email, :hashedPassword, :salt, :readonly, :admin, :map, :distanceUnit, :speedUnit, :latitude, :longitude, :zoom, :twelveHourFormat, :coordinateFormat, :disabled, :expirationTime, :deviceLimit, :userLimit, :token, :attributes)
</entry>
<entry key='database.updateUser'>
UPDATE users SET
name = :name,
email = :email,
readonly = :readonly,
admin = :admin,
map = :map,
distanceUnit = :distanceUnit,
@@ -84,6 +85,7 @@
disabled = :disabled,
expirationTime = :expirationTime,
deviceLimit = :deviceLimit,
userLimit = :userLimit,
token = :token,
attributes = :attributes
WHERE id = :id
@@ -349,6 +351,18 @@
<entry key='database.unlinkCalendar'>
DELETE FROM user_calendar WHERE userId = :userId AND calendarId = :calendarId
</entry>
<entry key='database.selectUserPermissions'>
SELECT userId, otherUserId FROM user_user
</entry>
<entry key='database.linkUser'>
INSERT INTO user_user (userId, otherUserId) VALUES (:userId, :otherUserId)
</entry>
<entry key='database.unlinkUser'>
DELETE FROM user_user WHERE userId = :userId AND otherUserId = :otherUserId
</entry>
<!-- PROTOCOL CONFIG -->

View File

@@ -92,8 +92,8 @@ public class MainEventHandler extends IdleStateAwareChannelHandler {
closeChannel(e.getChannel());
BaseProtocolDecoder protocolDecoder = (BaseProtocolDecoder) ctx.getPipeline().get("objectDecoder");
if (ctx.getPipeline().get("httpDecoder") == null &&
!connectionlessProtocols.contains(protocolDecoder.getProtocolName())) {
if (ctx.getPipeline().get("httpDecoder") == null
&& !connectionlessProtocols.contains(protocolDecoder.getProtocolName())) {
Context.getConnectionManager().removeActiveDevice(e.getChannel());
}
}

View File

@@ -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.
@@ -45,8 +45,12 @@ public class CalendarResource extends BaseResource {
@QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException {
if (all) {
Context.getPermissionsManager().checkAdmin(getUserId());
return Context.getCalendarManager().getAllCalendars();
if (Context.getPermissionsManager().isAdmin(getUserId())) {
return Context.getCalendarManager().getAllCalendars();
} else {
Context.getPermissionsManager().checkManager(getUserId());
return Context.getCalendarManager().getManagedCalendars(getUserId());
}
} else {
if (userId == 0) {
userId = getUserId();

View File

@@ -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.
@@ -35,7 +35,12 @@ public class DevicePermissionResource extends BaseResource {
@POST
public Response add(DevicePermission entity) throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkUser(getUserId(), entity.getUserId());
Context.getPermissionsManager().checkDevice(getUserId(), entity.getDeviceId());
if (!Context.getPermissionsManager().isAdmin(getUserId())) {
Context.getPermissionsManager().checkDeviceLimit(entity.getUserId());
}
Context.getDataManager().linkDevice(entity.getUserId(), entity.getDeviceId());
Context.getPermissionsManager().refreshPermissions();
if (Context.getGeofenceManager() != null) {
@@ -46,7 +51,9 @@ public class DevicePermissionResource extends BaseResource {
@DELETE
public Response remove(DevicePermission entity) throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkUser(getUserId(), entity.getUserId());
Context.getPermissionsManager().checkDevice(getUserId(), entity.getDeviceId());
Context.getDataManager().unlinkDevice(entity.getUserId(), entity.getDeviceId());
Context.getPermissionsManager().refreshPermissions();
if (Context.getGeofenceManager() != null) {

View File

@@ -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.
@@ -44,8 +44,12 @@ public class DeviceResource extends BaseResource {
public Collection<Device> get(
@QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException {
if (all) {
Context.getPermissionsManager().checkAdmin(getUserId());
return Context.getDeviceManager().getAllDevices();
if (Context.getPermissionsManager().isAdmin(getUserId())) {
return Context.getDeviceManager().getAllDevices();
} else {
Context.getPermissionsManager().checkManager(getUserId());
return Context.getDeviceManager().getManagedDevices(getUserId());
}
} else {
if (userId == 0) {
userId = getUserId();
@@ -58,13 +62,7 @@ public class DeviceResource extends BaseResource {
@POST
public Response add(Device entity) throws SQLException {
Context.getPermissionsManager().checkReadonly(getUserId());
int deviceLimit = Context.getPermissionsManager().getUser(getUserId()).getDeviceLimit();
if (deviceLimit != 0) {
int deviceCount = Context.getPermissionsManager().getDevicePermissions(getUserId()).size();
if (deviceCount >= deviceLimit) {
throw new SecurityException("User device limit reached");
}
}
Context.getPermissionsManager().checkDeviceLimit(getUserId());
Context.getDeviceManager().addDevice(entity);
Context.getDataManager().linkDevice(getUserId(), entity.getId());
Context.getPermissionsManager().refreshPermissions();

View File

@@ -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.
@@ -54,8 +54,12 @@ public class GeofenceResource extends BaseResource {
Set<Long> result;
if (all) {
Context.getPermissionsManager().checkAdmin(getUserId());
result = new HashSet<>(geofenceManager.getAllGeofencesIds());
if (Context.getPermissionsManager().isAdmin(getUserId())) {
result = new HashSet<>(geofenceManager.getAllGeofencesIds());
} else {
Context.getPermissionsManager().checkManager(getUserId());
result = new HashSet<>(geofenceManager.getManagedGeofencesIds(getUserId()));
}
} else {
if (userId == 0) {
userId = getUserId();

View File

@@ -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.
@@ -35,7 +35,9 @@ public class GroupPermissionResource extends BaseResource {
@POST
public Response add(GroupPermission entity) throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkUser(getUserId(), entity.getUserId());
Context.getPermissionsManager().checkGroup(getUserId(), entity.getGroupId());
Context.getDataManager().linkGroup(entity.getUserId(), entity.getGroupId());
Context.getPermissionsManager().refreshPermissions();
if (Context.getGeofenceManager() != null) {
@@ -46,7 +48,9 @@ public class GroupPermissionResource extends BaseResource {
@DELETE
public Response remove(GroupPermission entity) throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
Context.getPermissionsManager().checkReadonly(getUserId());
Context.getPermissionsManager().checkUser(getUserId(), entity.getUserId());
Context.getPermissionsManager().checkGroup(getUserId(), entity.getGroupId());
Context.getDataManager().unlinkGroup(entity.getUserId(), entity.getGroupId());
Context.getPermissionsManager().refreshPermissions();
if (Context.getGeofenceManager() != null) {

View File

@@ -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.
@@ -42,8 +42,12 @@ public class GroupResource extends BaseResource {
public Collection<Group> get(
@QueryParam("all") boolean all, @QueryParam("userId") long userId) throws SQLException {
if (all) {
Context.getPermissionsManager().checkAdmin(getUserId());
return Context.getDeviceManager().getAllGroups();
if (Context.getPermissionsManager().isAdmin(getUserId())) {
return Context.getDeviceManager().getAllGroups();
} else {
Context.getPermissionsManager().checkManager(getUserId());
return Context.getDeviceManager().getManagedGroups(getUserId());
}
} else {
if (userId == 0) {
userId = getUserId();

View File

@@ -0,0 +1,57 @@
/*
* 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.api.resource;
import java.sql.SQLException;
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 org.traccar.Context;
import org.traccar.api.BaseResource;
import org.traccar.model.UserPermission;
@Path("permissions/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserPermissionResource extends BaseResource {
@POST
public Response add(UserPermission entity) throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
if (entity.getUserId() == entity.getOtherUserId()) {
throw new SecurityException("Selfmanagement prohibited");
}
Context.getDataManager().linkUser(entity.getUserId(), entity.getOtherUserId());
Context.getPermissionsManager().refreshUserPermissions();
return Response.ok(entity).build();
}
@DELETE
public Response remove(UserPermission entity) throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
Context.getDataManager().unlinkUser(entity.getUserId(), entity.getOtherUserId());
Context.getPermissionsManager().refreshUserPermissions();
return Response.noContent().build();
}
}

View File

@@ -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.
@@ -28,6 +28,7 @@ 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;
@@ -40,25 +41,42 @@ import java.util.Date;
public class UserResource extends BaseResource {
@GET
public Collection<User> get() throws SQLException {
Context.getPermissionsManager().checkAdmin(getUserId());
return Context.getPermissionsManager().getUsers();
public Collection<User> get(@QueryParam("userId") long userId) throws SQLException {
if (Context.getPermissionsManager().isAdmin(getUserId())) {
if (userId != 0) {
return Context.getPermissionsManager().getUsers(userId);
} else {
return Context.getPermissionsManager().getAllUsers();
}
} else if (Context.getPermissionsManager().isManager(getUserId())) {
return Context.getPermissionsManager().getManagedUsers(getUserId());
} else {
throw new SecurityException("Admin or manager access required");
}
}
@PermitAll
@POST
public Response add(User entity) throws SQLException {
if (!Context.getPermissionsManager().isAdmin(getUserId())) {
Context.getPermissionsManager().checkRegistration(getUserId());
Context.getPermissionsManager().checkUserUpdate(getUserId(), new User(), entity);
entity.setDeviceLimit(Context.getConfig().getInteger("users.defaultDeviceLimit"));
int expirationDays = Context.getConfig().getInteger("users.defaultExpirationDays");
if (expirationDays > 0) {
entity.setExpirationTime(
new Date(System.currentTimeMillis() + (long) expirationDays * 24 * 3600 * 1000));
if (Context.getPermissionsManager().isManager(getUserId())) {
Context.getPermissionsManager().checkUserLimit(getUserId());
} else {
Context.getPermissionsManager().checkRegistration(getUserId());
entity.setDeviceLimit(Context.getConfig().getInteger("users.defaultDeviceLimit"));
int expirationDays = Context.getConfig().getInteger("users.defaultExpirationDays");
if (expirationDays > 0) {
entity.setExpirationTime(
new Date(System.currentTimeMillis() + (long) expirationDays * 24 * 3600 * 1000));
}
}
}
Context.getPermissionsManager().addUser(entity);
if (Context.getPermissionsManager().isManager(getUserId())) {
Context.getDataManager().linkUser(getUserId(), entity.getId());
}
Context.getPermissionsManager().refreshUserPermissions();
if (Context.getNotificationManager() != null) {
Context.getNotificationManager().refresh();
}

View File

@@ -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 otherUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
result.addAll(getUserCalendars(otherUserId));
}
return result;
}
public final void refreshUserCalendars() {
if (dataManager != null) {
try {

View File

@@ -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 otherUserId) throws SQLException {
QueryBuilder.create(dataSource, getQuery("database.linkUser"))
.setLong("userId", userId)
.setLong("otherUserId", otherUserId)
.executeUpdate();
}
public void unlinkUser(long userId, long otherUserId) throws SQLException {
QueryBuilder.create(dataSource, getQuery("database.unlinkUser"))
.setLong("userId", userId)
.setLong("otherUserId", otherUserId)
.executeUpdate();
}
}

View File

@@ -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 otherUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
devices.addAll(getDevices(otherUserId));
}
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 otherUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
groups.addAll(getGroups(otherUserId));
}
return groups;
}
private void checkGroupCycles(Group group) {
Set<Long> groups = new HashSet<>();
while (group != null) {

View File

@@ -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 otherUserId : Context.getPermissionsManager().getUserPermissions(userId)) {
geofences.addAll(getUserGeofencesIds(otherUserId));
}
return geofences;
}
public final Collection<Geofence> getGeofences(Set<Long> geofencesIds) {
geofencesLock.readLock().lock();
try {

View File

@@ -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,11 +23,14 @@ 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;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -47,6 +50,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 +80,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 +110,17 @@ public class PermissionsManager {
}
}
public final void refreshUserPermissions() {
userPermissions.clear();
try {
for (UserPermission permission : dataManager.getUserPermissions()) {
getUserPermissions(permission.getUserId()).add(permission.getOtherUserId());
}
} catch (SQLException error) {
Log.warning(error);
}
}
public final void refreshPermissions() {
groupPermissions.clear();
devicePermissions.clear();
@@ -146,6 +170,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 otherUserId) throws SecurityException {
checkManager(userId);
if (!userPermissions.get(userId).contains(otherUserId)) {
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,30 +225,52 @@ 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);
if (userId != otherUserId && !isAdmin(userId)) {
checkManager(userId, otherUserId);
}
}
public void checkGroup(long userId, long groupId) throws SecurityException {
if (!getGroupPermissions(userId).contains(groupId)) {
throw new SecurityException("Group access denied");
if (!getGroupPermissions(userId).contains(groupId) && !isAdmin(userId)) {
Iterator<Long> iterator = getUserPermissions(userId).iterator();
boolean managed = false;
while (!managed && iterator.hasNext()) {
managed = getGroupPermissions(iterator.next()).contains(groupId);
}
if (!managed) {
throw new SecurityException("Group access denied");
}
}
}
public void checkDevice(long userId, long deviceId) throws SecurityException {
if (!getDevicePermissions(userId).contains(deviceId)) {
throw new SecurityException("Device access denied");
if (!getDevicePermissions(userId).contains(deviceId) && !isAdmin(userId)) {
Iterator<Long> iterator = getUserPermissions(userId).iterator();
boolean managed = false;
while (!managed && iterator.hasNext()) {
managed = getDevicePermissions(iterator.next()).contains(deviceId);
}
if (!managed) {
throw new SecurityException("Device access denied");
}
}
}
@@ -203,13 +282,27 @@ public class PermissionsManager {
public void checkGeofence(long userId, long geofenceId) throws SecurityException {
if (!Context.getGeofenceManager().checkGeofence(userId, geofenceId) && !isAdmin(userId)) {
throw new SecurityException("Geofence access denied");
Iterator<Long> iterator = getUserPermissions(userId).iterator();
boolean managed = false;
while (!managed && iterator.hasNext()) {
managed = Context.getGeofenceManager().checkGeofence(iterator.next(), geofenceId);
}
if (!managed) {
throw new SecurityException("Geofence access denied");
}
}
}
public void checkCalendar(long userId, long calendarId) throws SecurityException {
if (!Context.getCalendarManager().checkCalendar(userId, calendarId) && !isAdmin(userId)) {
throw new SecurityException("Calendar access denied");
Iterator<Long> iterator = getUserPermissions(userId).iterator();
boolean managed = false;
while (!managed && iterator.hasNext()) {
managed = Context.getCalendarManager().checkCalendar(iterator.next(), calendarId);
}
if (!managed) {
throw new SecurityException("Calendar access denied");
}
}
}
@@ -222,10 +315,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 otherUserId : getUserPermissions(userId)) {
result.add(users.get(otherUserId));
}
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 +364,7 @@ public class PermissionsManager {
usersTokens.remove(users.get(userId).getToken());
users.remove(userId);
refreshPermissions();
refreshUserPermissions();
}
public User login(String email, String password) throws SQLException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 - 2016 Anton Tananaev (anton@traccar.org)
* Copyright 2013 - 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.
@@ -180,6 +180,16 @@ public class User extends Extensible {
this.deviceLimit = deviceLimit;
}
private int userLimit;
public int getUserLimit() {
return userLimit;
}
public void setUserLimit(int userLimit) {
this.userLimit = userLimit;
}
private String token;
public String getToken() {

View File

@@ -0,0 +1,41 @@
/*
* 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.model;
public class UserPermission {
private long userId;
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
private long otherUserId;
public long getOtherUserId() {
return otherUserId;
}
public void setOtherUserId(long otherUserId) {
this.otherUserId = otherUserId;
}
}