mirror of
https://github.com/traccar/traccar.git
synced 2026-05-19 14:18:23 -04:00
Initial manager implementation
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
57
src/org/traccar/api/resource/UserPermissionResource.java
Normal file
57
src/org/traccar/api/resource/UserPermissionResource.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
41
src/org/traccar/model/UserPermission.java
Normal file
41
src/org/traccar/model/UserPermission.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user