Remove users manager

This commit is contained in:
Anton Tananaev 2022-06-15 09:55:50 -07:00
parent 0d5c7606c7
commit 63ecf80c11
14 changed files with 153 additions and 359 deletions

View File

@ -16,6 +16,18 @@
<column name="uniqueid" />
</createIndex>
<createIndex tableName="tc_users" indexName="idx_users_email">
<column name="email" />
</createIndex>
<createIndex tableName="tc_users" indexName="idx_users_login">
<column name="login" />
</createIndex>
<createIndex tableName="tc_users" indexName="idx_users_token">
<column name="token" />
</createIndex>
<addColumn tableName="tc_servers">
<column name="overlayurl" type="VARCHAR(512)" />
</addColumn>

View File

@ -23,12 +23,10 @@ import org.traccar.database.DeviceManager;
import org.traccar.database.GroupsManager;
import org.traccar.database.IdentityManager;
import org.traccar.database.PermissionsManager;
import org.traccar.database.UsersManager;
import org.traccar.helper.Log;
import org.traccar.model.BaseModel;
import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.model.User;
import org.traccar.session.ConnectionManager;
public final class Context {
@ -54,12 +52,6 @@ public final class Context {
return dataManager;
}
private static UsersManager usersManager;
public static UsersManager getUsersManager() {
return usersManager;
}
private static GroupsManager groupsManager;
public static GroupsManager getGroupsManager() {
@ -94,7 +86,6 @@ public final class Context {
}
if (dataManager != null) {
usersManager = new UsersManager(dataManager);
groupsManager = new GroupsManager(dataManager);
deviceManager = new DeviceManager(
config, dataManager, Main.getInjector().getInstance(ConnectionManager.class));
@ -102,7 +93,7 @@ public final class Context {
identityManager = deviceManager;
permissionsManager = new PermissionsManager(dataManager, usersManager);
permissionsManager = new PermissionsManager(dataManager, dataManager.getStorage());
}
@ -111,8 +102,6 @@ public final class Context {
return (BaseObjectManager<T>) deviceManager;
} else if (clazz.equals(Group.class)) {
return (BaseObjectManager<T>) groupsManager;
} else if (clazz.equals(User.class)) {
return (BaseObjectManager<T>) usersManager;
}
return null;
}

View File

@ -31,7 +31,6 @@ import org.traccar.broadcast.BroadcastService;
import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.database.LdapProvider;
import org.traccar.database.UsersManager;
import org.traccar.helper.SanitizerModule;
import org.traccar.notification.EventForwarder;
import org.traccar.database.DataManager;
@ -118,11 +117,6 @@ public class MainModule extends AbstractModule {
return Context.getDataManager();
}
@Provides
public static UsersManager provideUsersManager() {
return Context.getUsersManager();
}
@Provides
public static IdentityManager provideIdentityManager() {
return Context.getIdentityManager();
@ -292,8 +286,7 @@ public class MainModule extends AbstractModule {
}
@Provides
public static EventForwarder provideEventForwarder(
Config config, Client client, CacheManager cacheManager, UsersManager usersManager) {
public static EventForwarder provideEventForwarder(Config config, Client client, CacheManager cacheManager) {
if (config.hasKey(Keys.EVENT_FORWARD_URL)) {
return new EventForwarder(config, client, cacheManager);
}

View File

@ -19,7 +19,6 @@ package org.traccar.api;
import org.traccar.Context;
import org.traccar.database.BaseObjectManager;
import org.traccar.database.ExtendedObjectManager;
import org.traccar.database.SimpleObjectManager;
import org.traccar.helper.LogAction;
import org.traccar.model.BaseModel;
import org.traccar.model.Device;
@ -82,9 +81,7 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
cacheManager.invalidate(User.class, getUserId(), baseClass, entity.getId());
LogAction.link(getUserId(), User.class, getUserId(), baseClass, entity.getId());
if (manager instanceof SimpleObjectManager) {
((SimpleObjectManager<T>) manager).refreshUserItems();
} else if (baseClass.equals(Group.class) || baseClass.equals(Device.class)) {
if (baseClass.equals(Group.class) || baseClass.equals(Device.class)) {
Context.getPermissionsManager().refreshDeviceAndGroupPermissions();
}
return Response.ok(entity).build();
@ -95,6 +92,11 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
public Response update(T entity) throws StorageException {
permissionsService.checkEdit(getUserId(), entity, false);
permissionsService.checkPermission(baseClass, getUserId(), entity.getId());
if (entity instanceof User) {
User before = storage.getObject(User.class, new Request(
new Columns.All(), new Condition.Equals("id", "id", entity.getId())));
permissionsService.checkUserUpdate(getUserId(), before, (User) entity);
}
BaseObjectManager<T> manager = Context.getManager(baseClass);
if (manager != null) {
@ -123,11 +125,8 @@ public abstract class BaseObjectResource<T extends BaseModel> extends BaseResour
BaseObjectManager<T> manager = Context.getManager(baseClass);
if (manager != null) {
manager.removeItem(id);
if (manager instanceof SimpleObjectManager) {
((SimpleObjectManager<T>) manager).refreshUserItems();
if (manager instanceof ExtendedObjectManager) {
((ExtendedObjectManager<T>) manager).refreshExtendedPermissions();
}
if (manager instanceof ExtendedObjectManager) {
((ExtendedObjectManager<T>) manager).refreshExtendedPermissions();
}
} else {
storage.removeObject(baseClass, new Request(new Condition.Equals("id", "id", id)));

View File

@ -49,7 +49,7 @@ public class DeviceResource extends BaseObjectResource<Device> {
public Collection<Device> get(
@QueryParam("all") boolean all, @QueryParam("userId") long userId,
@QueryParam("uniqueId") List<String> uniqueIds,
@QueryParam("id") List<Long> deviceIds) {
@QueryParam("id") List<Long> deviceIds) throws StorageException {
DeviceManager deviceManager = Context.getDeviceManager();
Set<Long> result;
if (all) {
@ -57,13 +57,13 @@ public class DeviceResource extends BaseObjectResource<Device> {
result = deviceManager.getAllItems();
} else {
Context.getPermissionsManager().checkManager(getUserId());
result = deviceManager.getManagedItems(getUserId());
result = deviceManager.getUserItems(getUserId());
}
} else if (uniqueIds.isEmpty() && deviceIds.isEmpty()) {
if (userId == 0) {
userId = getUserId();
}
Context.getPermissionsManager().checkUser(getUserId(), userId);
permissionsService.checkUser(getUserId(), userId);
if (Context.getPermissionsManager().getUserAdmin(getUserId())) {
result = deviceManager.getAllUserItems(userId);
} else {
@ -73,11 +73,11 @@ public class DeviceResource extends BaseObjectResource<Device> {
result = new HashSet<>();
for (String uniqueId : uniqueIds) {
Device device = deviceManager.getByUniqueId(uniqueId);
Context.getPermissionsManager().checkDevice(getUserId(), device.getId());
permissionsService.checkPermission(Device.class, getUserId(), device.getId());
result.add(device.getId());
}
for (Long deviceId : deviceIds) {
Context.getPermissionsManager().checkDevice(getUserId(), deviceId);
permissionsService.checkPermission(Device.class, getUserId(), deviceId);
result.add(deviceId);
}
}
@ -87,9 +87,9 @@ public class DeviceResource extends BaseObjectResource<Device> {
@Path("{id}/accumulators")
@PUT
public Response updateAccumulators(DeviceAccumulators entity) throws StorageException {
if (!Context.getPermissionsManager().getUserAdmin(getUserId())) {
Context.getPermissionsManager().checkManager(getUserId());
Context.getPermissionsManager().checkPermission(Device.class, getUserId(), entity.getDeviceId());
if (permissionsService.notAdmin(getUserId())) {
permissionsService.checkManager(getUserId());
permissionsService.checkPermission(Device.class, getUserId(), entity.getDeviceId());
}
Context.getDeviceManager().resetDeviceAccumulators(entity);
LogAction.resetDeviceAccumulators(getUserId(), entity.getDeviceId());

View File

@ -15,12 +15,14 @@
*/
package org.traccar.api.resource;
import org.traccar.Context;
import org.traccar.api.BaseResource;
import org.traccar.database.MailManager;
import org.traccar.model.User;
import org.traccar.notification.TextTemplateFormatter;
import org.traccar.storage.StorageException;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
import org.traccar.storage.query.Request;
import javax.annotation.security.PermitAll;
import javax.inject.Inject;
@ -51,18 +53,17 @@ public class PasswordResource extends BaseResource {
@PermitAll
@POST
public Response reset(@FormParam("email") String email) throws StorageException, MessagingException {
for (long userId : Context.getUsersManager().getAllItems()) {
User user = Context.getUsersManager().getById(userId);
if (email.equals(user.getEmail())) {
String token = UUID.randomUUID().toString().replaceAll("-", "");
user.set(PASSWORD_RESET_TOKEN, token);
Context.getUsersManager().updateItem(user);
var velocityContext = textTemplateFormatter.prepareContext(permissionsService.getServer(), user);
velocityContext.put("token", token);
var fullMessage = textTemplateFormatter.formatMessage(velocityContext, "passwordReset", "full");
mailManager.sendMessage(user, fullMessage.getSubject(), fullMessage.getBody());
break;
}
User user = storage.getObject(User.class, new Request(
new Columns.All(), new Condition.Equals("email", "email", email)));
if (user != null) {
String token = UUID.randomUUID().toString().replaceAll("-", "");
user.set(PASSWORD_RESET_TOKEN, token);
storage.updateObject(user, new Request(new Columns.Exclude("id"), new Condition.Equals("id", "id")));
var velocityContext = textTemplateFormatter.prepareContext(permissionsService.getServer(), user);
velocityContext.put("token", token);
var fullMessage = textTemplateFormatter.formatMessage(velocityContext, "passwordReset", "full");
mailManager.sendMessage(user, fullMessage.getSubject(), fullMessage.getBody());
}
return Response.ok().build();
}
@ -72,14 +73,14 @@ public class PasswordResource extends BaseResource {
@POST
public Response update(
@FormParam("token") String token, @FormParam("password") String password) throws StorageException {
for (long userId : Context.getUsersManager().getAllItems()) {
User user = Context.getUsersManager().getById(userId);
if (token.equals(user.getString(PASSWORD_RESET_TOKEN))) {
user.getAttributes().remove(PASSWORD_RESET_TOKEN);
user.setPassword(password);
Context.getUsersManager().updateItem(user);
return Response.ok().build();
}
User user = storage.getObjects(User.class, new Request(new Columns.All())).stream()
.filter(it -> token.equals(it.getString(PASSWORD_RESET_TOKEN)))
.findFirst().orElse(null);
if (user != null) {
user.getAttributes().remove(PASSWORD_RESET_TOKEN);
user.setPassword(password);
storage.updateObject(user, new Request(new Columns.Exclude("id"), new Condition.Equals("id", "id")));
return Response.ok().build();
}
return Response.status(Response.Status.NOT_FOUND).build();
}

View File

@ -22,6 +22,9 @@ import org.traccar.helper.ServletHelper;
import org.traccar.helper.LogAction;
import org.traccar.model.User;
import org.traccar.storage.StorageException;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
import org.traccar.storage.query.Request;
import javax.annotation.security.PermitAll;
import javax.servlet.http.Cookie;
@ -59,7 +62,8 @@ public class SessionResource extends BaseResource {
public User get(@QueryParam("token") String token) throws StorageException, UnsupportedEncodingException {
if (token != null) {
User user = Context.getUsersManager().getUserByToken(token);
User user = storage.getObject(User.class, new Request(
new Columns.All(), new Condition.Equals("token", "token", token)));
if (user != null) {
Context.getPermissionsManager().checkUserEnabled(user.getId());
request.getSession().setAttribute(USER_ID_KEY, user.getId());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015 - 2017 Anton Tananaev (anton@traccar.org)
* Copyright 2015 - 2022 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.
@ -15,17 +15,20 @@
*/
package org.traccar.api.resource;
import org.traccar.Context;
import org.traccar.api.BaseObjectResource;
import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.database.UsersManager;
import org.traccar.helper.LogAction;
import org.traccar.model.ManagedUser;
import org.traccar.model.Permission;
import org.traccar.model.User;
import org.traccar.storage.StorageException;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
import org.traccar.storage.query.Request;
import javax.annotation.security.PermitAll;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@ -34,63 +37,77 @@ 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;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
@Path("users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserResource extends BaseObjectResource<User> {
@Inject
private Config config;
public UserResource() {
super(User.class);
}
@GET
public Collection<User> get(@QueryParam("userId") long userId) throws SQLException {
UsersManager usersManager = Context.getUsersManager();
Set<Long> result;
if (Context.getPermissionsManager().getUserAdmin(getUserId())) {
if (userId != 0) {
result = usersManager.getUserItems(userId);
} else {
result = usersManager.getAllItems();
}
} else if (Context.getPermissionsManager().getUserManager(getUserId())) {
result = usersManager.getManagedItems(getUserId());
public Collection<User> get(@QueryParam("userId") long userId) throws StorageException {
permissionsService.checkUser(getUserId(), userId);
if (userId > 0) {
return storage.getObjects(baseClass, new Request(
new Columns.All(),
new Condition.Permission(User.class, userId, ManagedUser.class).excludeGroups()));
} else if (permissionsService.notAdmin(getUserId())) {
return storage.getObjects(baseClass, new Request(
new Columns.All(),
new Condition.Permission(User.class, getUserId(), ManagedUser.class).excludeGroups()));
} else {
throw new SecurityException("Admin or manager access required");
return storage.getObjects(baseClass, new Request(new Columns.All()));
}
return usersManager.getItems(result);
}
@Override
@PermitAll
@POST
public Response add(User entity) throws StorageException {
if (!Context.getPermissionsManager().getUserAdmin(getUserId())) {
Context.getPermissionsManager().checkUserUpdate(getUserId(), new User(), entity);
if (Context.getPermissionsManager().getUserManager(getUserId())) {
Context.getPermissionsManager().checkUserLimit(getUserId());
User currentUser = permissionsService.getUser(getUserId());
if (permissionsService.notAdmin(getUserId())) {
permissionsService.checkUserUpdate(getUserId(), new User(), entity);
if (currentUser != null && currentUser.getUserLimit() != 0) {
int userLimit = currentUser.getUserLimit();
if (userLimit > 0) {
int userCount = storage.getObjects(baseClass, new Request(
new Columns.All(),
new Condition.Permission(User.class, getUserId(), ManagedUser.class).excludeGroups()))
.size();
if (userCount >= userLimit) {
throw new SecurityException("Manager user limit reached");
}
}
} else {
Context.getPermissionsManager().checkRegistration(getUserId());
entity.setDeviceLimit(Context.getConfig().getInteger(Keys.USERS_DEFAULT_DEVICE_LIMIT));
int expirationDays = Context.getConfig().getInteger(Keys.USERS_DEFAULT_EXPIRATION_DAYS);
if (!permissionsService.getServer().getRegistration()) {
throw new SecurityException("Registration disabled");
}
entity.setDeviceLimit(config.getInteger(Keys.USERS_DEFAULT_DEVICE_LIMIT));
int expirationDays = config.getInteger(Keys.USERS_DEFAULT_EXPIRATION_DAYS);
if (expirationDays > 0) {
entity.setExpirationTime(
new Date(System.currentTimeMillis() + (long) expirationDays * 24 * 3600 * 1000));
entity.setExpirationTime(new Date(System.currentTimeMillis() + expirationDays * 86400000L));
}
}
}
Context.getUsersManager().addItem(entity);
entity.setId(storage.addObject(entity, new Request(new Columns.Exclude("id"))));
storage.updateObject(entity, new Request(
new Columns.Include("hashedPassword", "salt"), new Condition.Equals("id", "id")));
LogAction.create(getUserId(), entity);
if (Context.getPermissionsManager().getUserManager(getUserId())) {
if (currentUser != null && currentUser.getUserLimit() != 0) {
storage.addPermission(new Permission(User.class, getUserId(), ManagedUser.class, entity.getId()));
LogAction.link(getUserId(), User.class, getUserId(), ManagedUser.class, entity.getId());
}
Context.getUsersManager().refreshUserItems();
return Response.ok(entity).build();
}

View File

@ -57,7 +57,7 @@ public class PermissionsService {
}
public User getUser(long userId) throws StorageException {
if (user == null) {
if (user == null && userId > 0) {
user = storage.getObject(
User.class, new Request(new Columns.All(), new Condition.Equals("id", "id", userId)));
}
@ -74,6 +74,12 @@ public class PermissionsService {
}
}
public void checkManager(long userId) throws StorageException, SecurityException {
if (!getUser(userId).getAdministrator() && getUser(userId).getUserLimit() == 0) {
throw new SecurityException("Manager access required");
}
}
public interface CheckRestrictionCallback {
boolean denied(UserRestrictions userRestrictions);
}
@ -137,6 +143,31 @@ public class PermissionsService {
}
}
public void checkUserUpdate(long userId, User before, User after) throws StorageException, SecurityException {
if (before.getAdministrator() != after.getAdministrator()
|| before.getDeviceLimit() != after.getDeviceLimit()
|| before.getUserLimit() != after.getUserLimit()) {
checkAdmin(userId);
}
User user = getUser(userId);
if (user != null && user.getExpirationTime() != null
&& (after.getExpirationTime() == null
|| user.getExpirationTime().compareTo(after.getExpirationTime()) < 0)) {
checkAdmin(userId);
}
if (before.getReadonly() != after.getReadonly()
|| before.getDeviceReadonly() != after.getDeviceReadonly()
|| before.getDisabled() != after.getDisabled()
|| before.getLimitCommands() != after.getLimitCommands()
|| before.getDisableReports() != after.getDisableReports()) {
if (userId == after.getId()) {
checkAdmin(userId);
} else {
checkUser(userId, after.getId());
}
}
}
public <T extends BaseModel> void checkPermission(
Class<T> clazz, long userId, long objectId) throws StorageException, SecurityException {
if (!getUser(userId).getAdministrator() && !(clazz.equals(User.class) && userId == objectId)) {

View File

@ -25,7 +25,6 @@ import liquibase.database.DatabaseFactory;
import liquibase.exception.LiquibaseException;
import liquibase.resource.FileSystemResourceAccessor;
import liquibase.resource.ResourceAccessor;
import org.traccar.Context;
import org.traccar.Main;
import org.traccar.config.Config;
import org.traccar.config.Keys;
@ -155,7 +154,7 @@ public class DataManager {
} else {
if (ldapProvider != null && ldapProvider.login(email, password)) {
user = ldapProvider.getUser(email);
Context.getUsersManager().addItem(user);
user.setId(storage.addObject(user, new Request(new Columns.Exclude("id"))));
return user;
}
}

View File

@ -177,22 +177,6 @@ public class DeviceManager extends BaseObjectManager<Device> implements Identity
}
}
public Set<Long> getAllManagedItems(long userId) {
Set<Long> result = new HashSet<>(getAllUserItems(userId));
for (long managedUserId : Context.getUsersManager().getUserItems(userId)) {
result.addAll(getAllUserItems(managedUserId));
}
return result;
}
public Set<Long> getManagedItems(long userId) {
Set<Long> result = new HashSet<>(getUserItems(userId));
for (long managedUserId : Context.getUsersManager().getUserItems(userId)) {
result.addAll(getUserItems(managedUserId));
}
return result;
}
private void addByUniqueId(Device device) {
try {
writeLock();

View File

@ -18,14 +18,17 @@ package org.traccar.database;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.Context;
import org.traccar.model.BaseModel;
import org.traccar.api.security.PermissionsService;
import org.traccar.model.Device;
import org.traccar.model.Group;
import org.traccar.model.ManagedUser;
import org.traccar.model.Permission;
import org.traccar.model.Server;
import org.traccar.model.User;
import org.traccar.storage.Storage;
import org.traccar.storage.StorageException;
import org.traccar.storage.query.Columns;
import org.traccar.storage.query.Condition;
import org.traccar.storage.query.Request;
import java.util.HashMap;
import java.util.HashSet;
@ -39,7 +42,7 @@ public class PermissionsManager {
private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsManager.class);
private final DataManager dataManager;
private final UsersManager usersManager;
private final Storage storage;
private volatile Server server;
@ -50,9 +53,9 @@ public class PermissionsManager {
private final Map<Long, Set<Long>> deviceUsers = new HashMap<>();
private final Map<Long, Set<Long>> groupDevices = new HashMap<>();
public PermissionsManager(DataManager dataManager, UsersManager usersManager) {
public PermissionsManager(DataManager dataManager, Storage storage) {
this.dataManager = dataManager;
this.usersManager = usersManager;
this.storage = storage;
refreshServer();
refreshDeviceAndGroupPermissions();
}
@ -74,11 +77,11 @@ public class PermissionsManager {
}
public User getUser(long userId) {
readLock();
try {
return usersManager.getById(userId);
} finally {
readUnlock();
return storage.getObject(User.class, new Request(
new Columns.All(), new Condition.Equals("id", "id", userId)));
} catch (StorageException e) {
throw new RuntimeException(e);
}
}
@ -222,20 +225,6 @@ public class PermissionsManager {
}
}
public void checkManager(long userId, long managedUserId) throws SecurityException {
checkManager(userId);
if (!usersManager.getUserItems(userId).contains(managedUserId)) {
throw new SecurityException("User access denied");
}
}
public void checkUserLimit(long userId) throws SecurityException {
int userLimit = getUser(userId).getUserLimit();
if (userLimit != -1 && usersManager.getUserItems(userId).size() >= userLimit) {
throw new SecurityException("Manager user limit reached");
}
}
public boolean getUserReadonly(long userId) {
User user = getUser(userId);
return user != null && user.getReadonly();
@ -260,64 +249,11 @@ public class PermissionsManager {
}
}
public void checkUserUpdate(long userId, User before, User after) throws SecurityException {
if (before.getAdministrator() != after.getAdministrator()
|| before.getDeviceLimit() != after.getDeviceLimit()
|| before.getUserLimit() != after.getUserLimit()) {
checkAdmin(userId);
}
User user = getUser(userId);
if (user != null && user.getExpirationTime() != null
&& (after.getExpirationTime() == null
|| user.getExpirationTime().compareTo(after.getExpirationTime()) < 0)) {
checkAdmin(userId);
}
if (before.getReadonly() != after.getReadonly()
|| before.getDeviceReadonly() != after.getDeviceReadonly()
|| before.getDisabled() != after.getDisabled()
|| before.getLimitCommands() != after.getLimitCommands()
|| before.getDisableReports() != after.getDisableReports()) {
if (userId == after.getId()) {
checkAdmin(userId);
}
if (!getUserAdmin(userId)) {
checkManager(userId);
}
}
}
public void checkUser(long userId, long managedUserId) throws SecurityException {
if (userId != managedUserId && !getUserAdmin(userId)) {
checkManager(userId, managedUserId);
}
}
public void checkDevice(long userId, long deviceId) throws SecurityException {
if (!Context.getDeviceManager().getUserItems(userId).contains(deviceId) && !getUserAdmin(userId)) {
checkManager(userId);
for (long managedUserId : usersManager.getUserItems(userId)) {
if (Context.getDeviceManager().getUserItems(managedUserId).contains(deviceId)) {
return;
}
}
throw new SecurityException("Device access denied");
}
}
public void checkRegistration(long userId) {
if (!server.getRegistration() && !getUserAdmin(userId)) {
throw new SecurityException("Registration disabled");
}
}
public void checkPermission(Class<?> object, long userId, long objectId)
throws SecurityException {
SimpleObjectManager<? extends BaseModel> manager = null;
if (object.equals(Device.class)) {
checkDevice(userId, objectId);
} else {
throw new IllegalArgumentException("Unknown object type");
try {
new PermissionsService(storage).checkPermission(Device.class, userId, deviceId);
} catch (StorageException e) {
throw new RuntimeException(e);
}
}
@ -326,8 +262,6 @@ public class PermissionsManager {
if (permission.getPropertyClass().equals(Device.class)
|| permission.getPropertyClass().equals(Group.class)) {
refreshDeviceAndGroupPermissions();
} else if (permission.getPropertyClass().equals(ManagedUser.class)) {
usersManager.refreshUserItems();
}
}
}

View File

@ -16,82 +16,12 @@
*/
package org.traccar.database;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.Context;
import org.traccar.model.BaseModel;
import org.traccar.model.Permission;
import org.traccar.model.User;
import org.traccar.storage.StorageException;
public abstract class SimpleObjectManager<T extends BaseModel> extends BaseObjectManager<T> {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleObjectManager.class);
private Map<Long, Set<Long>> userItems;
protected SimpleObjectManager(DataManager dataManager, Class<T> baseClass) {
super(dataManager, baseClass);
}
public final Set<Long> getUserItems(long userId) {
try {
readLock();
Set<Long> result = userItems.get(userId);
if (result != null) {
return new HashSet<>(result);
} else {
return new HashSet<>();
}
} finally {
readUnlock();
}
}
public Set<Long> getManagedItems(long userId) {
Set<Long> result = getUserItems(userId);
for (long managedUserId : Context.getUsersManager().getUserItems(userId)) {
result.addAll(getUserItems(managedUserId));
}
return result;
}
public final boolean checkItemPermission(long userId, long itemId) {
return getUserItems(userId).contains(itemId);
}
@Override
public void refreshItems() {
super.refreshItems();
refreshUserItems();
}
public final void refreshUserItems() {
if (getDataManager() != null) {
try {
writeLock();
userItems = new ConcurrentHashMap<>();
for (Permission permission : getDataManager().getPermissions(User.class, getBaseClass())) {
Set<Long> items = userItems.computeIfAbsent(permission.getOwnerId(), key -> new HashSet<>());
items.add(permission.getPropertyId());
}
} catch (StorageException | ClassNotFoundException error) {
LOGGER.warn("Error getting permissions", error);
} finally {
writeUnlock();
}
}
}
@Override
public void removeItem(long itemId) throws StorageException {
super.removeItem(itemId);
refreshUserItems();
}
}

View File

@ -1,99 +0,0 @@
/*
* Copyright 2017 - 2020 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.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.traccar.model.User;
import org.traccar.storage.StorageException;
public class UsersManager extends SimpleObjectManager<User> {
private Map<String, User> usersTokens;
public UsersManager(DataManager dataManager) {
super(dataManager, User.class);
if (usersTokens == null) {
usersTokens = new ConcurrentHashMap<>();
}
}
private void putToken(User user) {
if (usersTokens == null) {
usersTokens = new ConcurrentHashMap<>();
}
if (user.getToken() != null) {
usersTokens.put(user.getToken(), user);
}
}
@Override
protected void addNewItem(User user) {
super.addNewItem(user);
putToken(user);
}
@Override
protected void updateCachedItem(User user) {
User cachedUser = getById(user.getId());
super.updateCachedItem(user);
putToken(user);
if (cachedUser.getToken() != null && !cachedUser.getToken().equals(user.getToken())) {
usersTokens.remove(cachedUser.getToken());
}
}
@Override
public void addItem(User user) throws StorageException {
super.addItem(user);
getDataManager().updateUserPassword(user);
}
@Override
public void updateItem(User user) throws StorageException {
if (user.getHashedPassword() != null) {
getDataManager().updateUserPassword(user);
}
super.updateItem(user);
}
@Override
protected void removeCachedItem(long userId) {
User cachedUser = getById(userId);
if (cachedUser != null) {
String userToken = cachedUser.getToken();
super.removeCachedItem(userId);
if (userToken != null) {
usersTokens.remove(userToken);
}
}
}
@Override
public Set<Long> getManagedItems(long userId) {
Set<Long> result = getUserItems(userId);
result.add(userId);
return result;
}
public User getUserByToken(String token) {
return usersTokens.get(token);
}
}