aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/api')
-rw-r--r--src/main/java/org/traccar/api/BaseObjectResource.java17
-rw-r--r--src/main/java/org/traccar/api/resource/DeviceResource.java16
-rw-r--r--src/main/java/org/traccar/api/resource/PasswordResource.java43
-rw-r--r--src/main/java/org/traccar/api/resource/SessionResource.java6
-rw-r--r--src/main/java/org/traccar/api/resource/UserResource.java77
-rw-r--r--src/main/java/org/traccar/api/security/PermissionsService.java33
6 files changed, 122 insertions, 70 deletions
diff --git a/src/main/java/org/traccar/api/BaseObjectResource.java b/src/main/java/org/traccar/api/BaseObjectResource.java
index aa777f3f6..f8545a5d7 100644
--- a/src/main/java/org/traccar/api/BaseObjectResource.java
+++ b/src/main/java/org/traccar/api/BaseObjectResource.java
@@ -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)));
diff --git a/src/main/java/org/traccar/api/resource/DeviceResource.java b/src/main/java/org/traccar/api/resource/DeviceResource.java
index 309308e75..cd5ebf0c5 100644
--- a/src/main/java/org/traccar/api/resource/DeviceResource.java
+++ b/src/main/java/org/traccar/api/resource/DeviceResource.java
@@ -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());
diff --git a/src/main/java/org/traccar/api/resource/PasswordResource.java b/src/main/java/org/traccar/api/resource/PasswordResource.java
index c7244f41c..643471797 100644
--- a/src/main/java/org/traccar/api/resource/PasswordResource.java
+++ b/src/main/java/org/traccar/api/resource/PasswordResource.java
@@ -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();
}
diff --git a/src/main/java/org/traccar/api/resource/SessionResource.java b/src/main/java/org/traccar/api/resource/SessionResource.java
index 1ccba1270..a0bf0cba5 100644
--- a/src/main/java/org/traccar/api/resource/SessionResource.java
+++ b/src/main/java/org/traccar/api/resource/SessionResource.java
@@ -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());
diff --git a/src/main/java/org/traccar/api/resource/UserResource.java b/src/main/java/org/traccar/api/resource/UserResource.java
index 84f41ca1a..20fce9e32 100644
--- a/src/main/java/org/traccar/api/resource/UserResource.java
+++ b/src/main/java/org/traccar/api/resource/UserResource.java
@@ -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();
}
diff --git a/src/main/java/org/traccar/api/security/PermissionsService.java b/src/main/java/org/traccar/api/security/PermissionsService.java
index c70414b2a..f39ded2b7 100644
--- a/src/main/java/org/traccar/api/security/PermissionsService.java
+++ b/src/main/java/org/traccar/api/security/PermissionsService.java
@@ -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)) {