aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/org/traccar/api/SecurityRequestFilter.java40
-rw-r--r--src/org/traccar/api/resource/DeviceResource.java7
-rw-r--r--src/org/traccar/api/resource/SessionResource.java12
-rw-r--r--src/org/traccar/api/resource/UserResource.java13
-rw-r--r--src/org/traccar/database/PermissionsManager.java38
-rw-r--r--src/org/traccar/model/User.java57
-rw-r--r--src/org/traccar/protocol/AutoGradeProtocolDecoder.java7
-rw-r--r--src/org/traccar/protocol/UproProtocolDecoder.java2
8 files changed, 148 insertions, 28 deletions
diff --git a/src/org/traccar/api/SecurityRequestFilter.java b/src/org/traccar/api/SecurityRequestFilter.java
index fd4c77525..3f2390754 100644
--- a/src/org/traccar/api/SecurityRequestFilter.java
+++ b/src/org/traccar/api/SecurityRequestFilter.java
@@ -17,6 +17,7 @@ package org.traccar.api;
import org.traccar.Context;
import org.traccar.api.resource.SessionResource;
+import org.traccar.helper.Log;
import org.traccar.model.User;
import javax.annotation.security.PermitAll;
@@ -62,28 +63,35 @@ public class SecurityRequestFilter implements ContainerRequestFilter {
SecurityContext securityContext = null;
- String authHeader = requestContext.getHeaderString(AUTHORIZATION_HEADER);
- if (authHeader != null) {
+ try {
- try {
- String[] auth = decodeBasicAuth(authHeader);
- User user = Context.getDataManager().login(auth[0], auth[1]);
- if (user != null) {
- Context.getStatisticsManager().registerRequest(user.getId());
- securityContext = new UserSecurityContext(new UserPrincipal(user.getId()));
+ String authHeader = requestContext.getHeaderString(AUTHORIZATION_HEADER);
+ if (authHeader != null) {
+
+ try {
+ String[] auth = decodeBasicAuth(authHeader);
+ User user = Context.getPermissionsManager().login(auth[0], auth[1]);
+ if (user != null) {
+ Context.getStatisticsManager().registerRequest(user.getId());
+ securityContext = new UserSecurityContext(new UserPrincipal(user.getId()));
+ }
+ } catch (SQLException e) {
+ throw new WebApplicationException(e);
}
- } catch (SQLException e) {
- throw new WebApplicationException(e);
- }
- } else if (request.getSession() != null) {
+ } else if (request.getSession() != null) {
+
+ Long userId = (Long) request.getSession().getAttribute(SessionResource.USER_ID_KEY);
+ if (userId != null) {
+ Context.getPermissionsManager().checkUser(userId);
+ Context.getStatisticsManager().registerRequest(userId);
+ securityContext = new UserSecurityContext(new UserPrincipal(userId));
+ }
- Long userId = (Long) request.getSession().getAttribute(SessionResource.USER_ID_KEY);
- if (userId != null) {
- Context.getStatisticsManager().registerRequest(userId);
- securityContext = new UserSecurityContext(new UserPrincipal(userId));
}
+ } catch (SecurityException e) {
+ Log.warning(e);
}
if (securityContext != null) {
diff --git a/src/org/traccar/api/resource/DeviceResource.java b/src/org/traccar/api/resource/DeviceResource.java
index f20ed86ad..0b389ede1 100644
--- a/src/org/traccar/api/resource/DeviceResource.java
+++ b/src/org/traccar/api/resource/DeviceResource.java
@@ -58,6 +58,13 @@ 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.getDeviceManager().addDevice(entity);
Context.getDataManager().linkDevice(getUserId(), entity.getId());
Context.getPermissionsManager().refreshPermissions();
diff --git a/src/org/traccar/api/resource/SessionResource.java b/src/org/traccar/api/resource/SessionResource.java
index 2847e41c1..996865c4b 100644
--- a/src/org/traccar/api/resource/SessionResource.java
+++ b/src/org/traccar/api/resource/SessionResource.java
@@ -29,6 +29,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -48,7 +49,7 @@ public class SessionResource extends BaseResource {
@PermitAll
@GET
- public User get() throws SQLException {
+ public User get(@QueryParam("token") String token) throws SQLException {
Long userId = (Long) request.getSession().getAttribute(USER_ID_KEY);
if (userId == null) {
Cookie[] cookies = request.getCookies();
@@ -64,7 +65,13 @@ public class SessionResource extends BaseResource {
}
}
if (email != null && password != null) {
- User user = Context.getDataManager().login(email, password);
+ User user = Context.getPermissionsManager().login(email, password);
+ if (user != null) {
+ userId = user.getId();
+ request.getSession().setAttribute(USER_ID_KEY, userId);
+ }
+ } else if (token != null) {
+ User user = Context.getPermissionsManager().getUserByToken(token);
if (user != null) {
userId = user.getId();
request.getSession().setAttribute(USER_ID_KEY, userId);
@@ -73,6 +80,7 @@ public class SessionResource extends BaseResource {
}
if (userId != null) {
+ Context.getPermissionsManager().checkUser(userId);
return Context.getPermissionsManager().getUser(userId);
} else {
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
diff --git a/src/org/traccar/api/resource/UserResource.java b/src/org/traccar/api/resource/UserResource.java
index f0a8597cc..2ff1639f6 100644
--- a/src/org/traccar/api/resource/UserResource.java
+++ b/src/org/traccar/api/resource/UserResource.java
@@ -60,13 +60,18 @@ public class UserResource extends BaseResource {
@Path("{id}")
@PUT
public Response update(@PathParam("id") long id, User entity) throws SQLException {
- if (entity.getAdmin()) {
+ User old = Context.getPermissionsManager().getUser(entity.getId());
+ if (old.getExpirationTime() == null && entity.getExpirationTime() != null
+ || old.getExpirationTime() != null && !old.getExpirationTime().equals(entity.getExpirationTime())
+ || old.getAdmin() != entity.getAdmin()
+ || old.getReadonly() != entity.getReadonly()
+ || old.getDisabled() != entity.getDisabled()
+ || old.getDeviceLimit() != entity.getDeviceLimit()
+ || old.getToken() == null && entity.getToken() != null
+ || old.getToken() != null && !old.getToken().equals(entity.getToken())) {
Context.getPermissionsManager().checkAdmin(getUserId());
} else {
Context.getPermissionsManager().checkUser(getUserId(), entity.getId());
- if (!entity.getReadonly()) {
- Context.getPermissionsManager().checkReadonly(entity.getId());
- }
}
Context.getPermissionsManager().updateUser(entity);
if (Context.getNotificationManager() != null) {
diff --git a/src/org/traccar/database/PermissionsManager.java b/src/org/traccar/database/PermissionsManager.java
index b0ae504d0..71633f6ef 100644
--- a/src/org/traccar/database/PermissionsManager.java
+++ b/src/org/traccar/database/PermissionsManager.java
@@ -39,6 +39,7 @@ public class PermissionsManager {
private volatile Server server;
private final Map<Long, User> users = new ConcurrentHashMap<>();
+ private final Map<String, Long> usersTokens = new HashMap<>();
private final Map<Long, Set<Long>> groupPermissions = new HashMap<>();
private final Map<Long, Set<Long>> devicePermissions = new HashMap<>();
@@ -81,10 +82,14 @@ public class PermissionsManager {
public final void refreshUsers() {
users.clear();
+ usersTokens.clear();
try {
server = dataManager.getServer();
for (User user : dataManager.getUsers()) {
users.put(user.getId(), user);
+ if (user.getToken() != null) {
+ usersTokens.put(user.getToken(), user.getId());
+ }
}
} catch (SQLException error) {
Log.warning(error);
@@ -146,7 +151,17 @@ public class PermissionsManager {
public void checkReadonly(long userId) throws SecurityException {
if (!isAdmin(userId) && (server.getReadonly() || isReadonly(userId))) {
- throw new SecurityException("User is readonly");
+ throw new SecurityException("Account is readonly");
+ }
+ }
+
+ public void checkUser(long userId) throws SecurityException {
+ User user = getUser(userId);
+ if (user.getDisabled()) {
+ throw new SecurityException("Account is disabled");
+ }
+ if (user.getExpirationTime() != null && System.currentTimeMillis() > user.getExpirationTime().getTime()) {
+ throw new SecurityException("Account has expired");
}
}
@@ -200,28 +215,43 @@ public class PermissionsManager {
public void addUser(User user) throws SQLException {
dataManager.addUser(user);
users.put(user.getId(), user);
+ if (user.getToken() != null) {
+ usersTokens.put(user.getToken(), user.getId());
+ }
refreshPermissions();
}
public void updateUser(User user) throws SQLException {
dataManager.updateUser(user);
+ User old = users.get(user.getId());
users.put(user.getId(), user);
+ if (user.getToken() != null) {
+ usersTokens.put(user.getToken(), user.getId());
+ }
+ if (old.getToken() != null && !old.getToken().equals(user.getToken())) {
+ usersTokens.remove(old.getToken());
+ }
refreshPermissions();
}
public void removeUser(long userId) throws SQLException {
dataManager.removeUser(userId);
+ usersTokens.remove(users.get(userId).getToken());
users.remove(userId);
refreshPermissions();
}
public User login(String email, String password) throws SQLException {
User user = dataManager.login(email, password);
- if (user != null && users.get(user.getId()) != null) {
+ if (user != null) {
+ checkUser(user.getId());
return users.get(user.getId());
- } else {
- return null;
}
+ return null;
+ }
+
+ public User getUserByToken(String token) {
+ return users.get(usersTokens.get(token));
}
}
diff --git a/src/org/traccar/model/User.java b/src/org/traccar/model/User.java
index aa0b33713..411b556fc 100644
--- a/src/org/traccar/model/User.java
+++ b/src/org/traccar/model/User.java
@@ -18,6 +18,8 @@ package org.traccar.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.traccar.helper.Hashing;
+import java.util.Date;
+
public class User extends Extensible {
private String name;
@@ -140,6 +142,61 @@ public class User extends Extensible {
this.coordinateFormat = coordinateFormat;
}
+ private boolean disabled;
+
+ public boolean getDisabled() {
+ return disabled;
+ }
+
+ public void setDisabled(boolean disabled) {
+ this.disabled = disabled;
+ }
+
+ private Date expirationTime;
+
+ public Date getExpirationTime() {
+ if (expirationTime != null) {
+ return new Date(expirationTime.getTime());
+ } else {
+ return null;
+ }
+ }
+
+ public void setExpirationTime(Date expirationTime) {
+ if (expirationTime != null) {
+ this.expirationTime = new Date(expirationTime.getTime());
+ } else {
+ this.expirationTime = null;
+ }
+ }
+
+ private int deviceLimit;
+
+ public int getDeviceLimit() {
+ return deviceLimit;
+ }
+
+ public void setDeviceLimit(int deviceLimit) {
+ this.deviceLimit = deviceLimit;
+ }
+
+ private String token;
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ if (token != null) {
+ if (!token.matches("^[a-zA-Z0-9]{16,}$")) {
+ throw new IllegalArgumentException("Illegal token");
+ }
+ this.token = token;
+ } else {
+ this.token = null;
+ }
+ }
+
public String getPassword() {
return null;
}
diff --git a/src/org/traccar/protocol/AutoGradeProtocolDecoder.java b/src/org/traccar/protocol/AutoGradeProtocolDecoder.java
index d520c282c..d8fe8b1a2 100644
--- a/src/org/traccar/protocol/AutoGradeProtocolDecoder.java
+++ b/src/org/traccar/protocol/AutoGradeProtocolDecoder.java
@@ -18,6 +18,7 @@ package org.traccar.protocol;
import org.jboss.netty.channel.Channel;
import org.traccar.BaseProtocolDecoder;
import org.traccar.DeviceSession;
+import org.traccar.helper.BitUtil;
import org.traccar.helper.DateBuilder;
import org.traccar.helper.Parser;
import org.traccar.helper.PatternBuilder;
@@ -43,7 +44,7 @@ public class AutoGradeProtocolDecoder extends BaseProtocolDecoder {
.number("([d.]{5})") // speed
.number("(dd)(dd)(dd)") // time
.number("([d.]{6})") // course
- .expression(".") // status
+ .expression("(.)") // status
.number("A(xxxx)")
.number("B(xxxx)")
.number("C(xxxx)")
@@ -88,6 +89,10 @@ public class AutoGradeProtocolDecoder extends BaseProtocolDecoder {
position.setCourse(parser.nextDouble());
+ int status = (byte) parser.next().charAt(0);
+ position.set(Position.KEY_STATUS, status);
+ position.set(Position.KEY_IGNITION, BitUtil.check(status, 0));
+
for (int i = 1; i <= 5; i++) {
position.set(Position.PREFIX_ADC + i, parser.next());
}
diff --git a/src/org/traccar/protocol/UproProtocolDecoder.java b/src/org/traccar/protocol/UproProtocolDecoder.java
index c6f400cae..24a0f5dcd 100644
--- a/src/org/traccar/protocol/UproProtocolDecoder.java
+++ b/src/org/traccar/protocol/UproProtocolDecoder.java
@@ -127,7 +127,7 @@ public class UproProtocolDecoder extends BaseProtocolDecoder {
odometer <<= 4;
odometer += data[i].charAt(j) - '0';
}
- position.set(Position.KEY_ODOMETER, odometer);
+ position.set(Position.KEY_ODOMETER, odometer * 2 * 1852 / 3600);
break;
case 'P':
position.set(Position.KEY_MCC, Integer.parseInt(data[i].substring(1, 5)));