mirror of
https://github.com/traccar/traccar.git
synced 2025-01-07 03:07:01 +08:00
Remove users manager
This commit is contained in:
parent
0d5c7606c7
commit
63ecf80c11
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)));
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user