diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/org/traccar/api/resource/UserResource.java | 235 | ||||
-rw-r--r-- | src/main/java/org/traccar/api/security/LoginService.java | 242 | ||||
-rw-r--r-- | src/main/java/org/traccar/helper/model/UserUtil.java | 146 |
3 files changed, 316 insertions, 307 deletions
diff --git a/src/main/java/org/traccar/api/resource/UserResource.java b/src/main/java/org/traccar/api/resource/UserResource.java index e41ebbe61..57df3481e 100644 --- a/src/main/java/org/traccar/api/resource/UserResource.java +++ b/src/main/java/org/traccar/api/resource/UserResource.java @@ -1,120 +1,115 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.traccar.api.resource; - -import org.traccar.api.BaseObjectResource; -import org.traccar.config.Config; -import org.traccar.config.Keys; -import org.traccar.helper.LogAction; -import org.traccar.helper.model.UserUtil; -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; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.Collection; -import java.util.Date; - -@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 StorageException { - if (userId > 0) { - permissionsService.checkUser(getUserId(), userId); - 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 { - return storage.getObjects(baseClass, new Request(new Columns.All())); - } - } - - @Override - @PermitAll - @POST - public Response add(User entity) throws StorageException { - User currentUser = getUserId() > 0 ? permissionsService.getUser(getUserId()) : null; - if (currentUser == null || !currentUser.getAdministrator()) { - 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 { - 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() + expirationDays * 86400000L)); - } - } - } - - if (UserUtil.isEmpty(storage)) { - entity.setAdministrator(true); - } - - 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", entity.getId()))); - - LogAction.create(getUserId(), entity); - - 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()); - } - return Response.ok(entity).build(); - } - -} +/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.api.resource;
+
+import org.traccar.api.BaseObjectResource;
+import org.traccar.config.Config;
+import org.traccar.config.Keys;
+import org.traccar.helper.LogAction;
+import org.traccar.helper.model.UserUtil;
+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;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.Collection;
+
+@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 StorageException {
+ if (userId > 0) {
+ permissionsService.checkUser(getUserId(), userId);
+ 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 {
+ return storage.getObjects(baseClass, new Request(new Columns.All()));
+ }
+ }
+
+ @Override
+ @PermitAll
+ @POST
+ public Response add(User entity) throws StorageException {
+ User currentUser = getUserId() > 0 ? permissionsService.getUser(getUserId()) : null;
+ if (currentUser == null || !currentUser.getAdministrator()) {
+ 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 {
+ if (!permissionsService.getServer().getRegistration()) {
+ throw new SecurityException("Registration disabled");
+ }
+ UserUtil.setUserDefaults(entity, config);
+ }
+ }
+
+ if (UserUtil.isEmpty(storage)) {
+ entity.setAdministrator(true);
+ }
+
+ 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", entity.getId())));
+
+ LogAction.create(getUserId(), entity);
+
+ 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());
+ }
+ return Response.ok(entity).build();
+ }
+
+}
diff --git a/src/main/java/org/traccar/api/security/LoginService.java b/src/main/java/org/traccar/api/security/LoginService.java index 7b51667c8..99539e50d 100644 --- a/src/main/java/org/traccar/api/security/LoginService.java +++ b/src/main/java/org/traccar/api/security/LoginService.java @@ -1,119 +1,123 @@ -/* - * Copyright 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.traccar.api.security; - -import org.traccar.api.signature.TokenManager; -import org.traccar.config.Config; -import org.traccar.config.Keys; -import org.traccar.database.LdapProvider; -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 javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Singleton; -import java.io.IOException; -import java.security.GeneralSecurityException; - -@Singleton -public class LoginService { - - private final Storage storage; - private final TokenManager tokenManager; - private final LdapProvider ldapProvider; - - private final String serviceAccountToken; - private final boolean forceLdap; - - @Inject - public LoginService( - Config config, Storage storage, TokenManager tokenManager, @Nullable LdapProvider ldapProvider) { - this.storage = storage; - this.tokenManager = tokenManager; - this.ldapProvider = ldapProvider; - serviceAccountToken = config.getString(Keys.WEB_SERVICE_ACCOUNT_TOKEN); - forceLdap = config.getBoolean(Keys.LDAP_FORCE); - } - - public User login(String token) throws StorageException, GeneralSecurityException, IOException { - if (serviceAccountToken != null && serviceAccountToken.equals(token)) { - return new ServiceAccountUser(); - } - long userId = tokenManager.verifyToken(token); - User user = storage.getObject(User.class, new Request( - new Columns.All(), new Condition.Equals("id", userId))); - if (user != null) { - checkUserEnabled(user); - } - return user; - } - - public User login(String email, String password) throws StorageException { - email = email.trim(); - User user = storage.getObject(User.class, new Request( - new Columns.All(), - new Condition.Or( - new Condition.Equals("email", email), - new Condition.Equals("login", email)))); - if (user != null) { - if (ldapProvider != null && user.getLogin() != null && ldapProvider.login(user.getLogin(), password) - || !forceLdap && user.isPasswordValid(password)) { - checkUserEnabled(user); - return user; - } - } else { - if (ldapProvider != null && ldapProvider.login(email, password)) { - user = ldapProvider.getUser(email); - user.setId(storage.addObject(user, new Request(new Columns.Exclude("id")))); - checkUserEnabled(user); - return user; - } - } - return null; - } - - public User login(String email, String name, Boolean administrator) throws StorageException { - User user = storage.getObject(User.class, new Request( - new Columns.All(), - new Condition.Equals("email", email))); - - if (user != null) { - checkUserEnabled(user); - return user; - } else { - user = new User(); - user.setName(name); - user.setEmail(email); - user.setFixedEmail(true); - user.setAdministrator(administrator); - user.setId(storage.addObject(user, new Request(new Columns.Exclude("id")))); - checkUserEnabled(user); - return user; - } - } - - private void checkUserEnabled(User user) throws SecurityException { - if (user == null) { - throw new SecurityException("Unknown account"); - } - user.checkDisabled(); - } - -} +/*
+ * Copyright 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.api.security;
+
+import org.traccar.api.signature.TokenManager;
+import org.traccar.config.Config;
+import org.traccar.config.Keys;
+import org.traccar.database.LdapProvider;
+import org.traccar.helper.model.UserUtil;
+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 javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+@Singleton
+public class LoginService {
+
+ private final Config config;
+ private final Storage storage;
+ private final TokenManager tokenManager;
+ private final LdapProvider ldapProvider;
+
+ private final String serviceAccountToken;
+ private final boolean forceLdap;
+
+ @Inject
+ public LoginService(
+ Config config, Storage storage, TokenManager tokenManager, @Nullable LdapProvider ldapProvider) {
+ this.storage = storage;
+ this.config = config;
+ this.tokenManager = tokenManager;
+ this.ldapProvider = ldapProvider;
+ serviceAccountToken = config.getString(Keys.WEB_SERVICE_ACCOUNT_TOKEN);
+ forceLdap = config.getBoolean(Keys.LDAP_FORCE);
+ }
+
+ public User login(String token) throws StorageException, GeneralSecurityException, IOException {
+ if (serviceAccountToken != null && serviceAccountToken.equals(token)) {
+ return new ServiceAccountUser();
+ }
+ long userId = tokenManager.verifyToken(token);
+ User user = storage.getObject(User.class, new Request(
+ new Columns.All(), new Condition.Equals("id", userId)));
+ if (user != null) {
+ checkUserEnabled(user);
+ }
+ return user;
+ }
+
+ public User login(String email, String password) throws StorageException {
+ email = email.trim();
+ User user = storage.getObject(User.class, new Request(
+ new Columns.All(),
+ new Condition.Or(
+ new Condition.Equals("email", email),
+ new Condition.Equals("login", email))));
+ if (user != null) {
+ if (ldapProvider != null && user.getLogin() != null && ldapProvider.login(user.getLogin(), password)
+ || !forceLdap && user.isPasswordValid(password)) {
+ checkUserEnabled(user);
+ return user;
+ }
+ } else {
+ if (ldapProvider != null && ldapProvider.login(email, password)) {
+ user = ldapProvider.getUser(email);
+ user.setId(storage.addObject(user, new Request(new Columns.Exclude("id"))));
+ checkUserEnabled(user);
+ return user;
+ }
+ }
+ return null;
+ }
+
+ public User login(String email, String name, Boolean administrator) throws StorageException {
+ User user = storage.getObject(User.class, new Request(
+ new Columns.All(),
+ new Condition.Equals("email", email)));
+
+ if (user != null) {
+ checkUserEnabled(user);
+ return user;
+ } else {
+ user = new User();
+ UserUtil.setUserDefaults(user, config);
+ user.setName(name);
+ user.setEmail(email);
+ user.setFixedEmail(true);
+ user.setAdministrator(administrator);
+ user.setId(storage.addObject(user, new Request(new Columns.Exclude("id"))));
+ checkUserEnabled(user);
+ return user;
+ }
+ }
+
+ private void checkUserEnabled(User user) throws SecurityException {
+ if (user == null) {
+ throw new SecurityException("Unknown account");
+ }
+ user.checkDisabled();
+ }
+
+}
diff --git a/src/main/java/org/traccar/helper/model/UserUtil.java b/src/main/java/org/traccar/helper/model/UserUtil.java index 9f93afeae..0dc355114 100644 --- a/src/main/java/org/traccar/helper/model/UserUtil.java +++ b/src/main/java/org/traccar/helper/model/UserUtil.java @@ -1,68 +1,78 @@ -/* - * Copyright 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. - * 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.helper.model; - -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.Order; -import org.traccar.storage.query.Request; - -import java.util.TimeZone; - -public final class UserUtil { - - private UserUtil() { - } - - public static boolean isEmpty(Storage storage) throws StorageException { - return storage.getObjects(User.class, new Request( - new Columns.Include("id"), - new Order("id", false, 1))).isEmpty(); - } - - public static String getDistanceUnit(Server server, User user) { - return lookupStringAttribute(server, user, "distanceUnit", "km"); - } - - public static String getSpeedUnit(Server server, User user) { - return lookupStringAttribute(server, user, "speedUnit", "kn"); - } - - public static String getVolumeUnit(Server server, User user) { - return lookupStringAttribute(server, user, "volumeUnit", "ltr"); - } - - public static TimeZone getTimezone(Server server, User user) { - String timezone = lookupStringAttribute(server, user, "timezone", null); - return timezone != null ? TimeZone.getTimeZone(timezone) : TimeZone.getDefault(); - } - - private static String lookupStringAttribute(Server server, User user, String key, String defaultValue) { - String preference; - String serverPreference = server.getString(key); - String userPreference = user.getString(key); - if (server.getForceSettings()) { - preference = serverPreference != null ? serverPreference : userPreference; - } else { - preference = userPreference != null ? userPreference : serverPreference; - } - return preference != null ? preference : defaultValue; - } - -} +/*
+ * Copyright 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.
+ * 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.helper.model;
+
+import org.traccar.config.Config;
+import org.traccar.config.Keys;
+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.Order;
+import org.traccar.storage.query.Request;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+public final class UserUtil {
+
+ private UserUtil() {
+ }
+
+ public static boolean isEmpty(Storage storage) throws StorageException {
+ return storage.getObjects(User.class, new Request(
+ new Columns.Include("id"),
+ new Order("id", false, 1))).isEmpty();
+ }
+
+ public static String getDistanceUnit(Server server, User user) {
+ return lookupStringAttribute(server, user, "distanceUnit", "km");
+ }
+
+ public static String getSpeedUnit(Server server, User user) {
+ return lookupStringAttribute(server, user, "speedUnit", "kn");
+ }
+
+ public static String getVolumeUnit(Server server, User user) {
+ return lookupStringAttribute(server, user, "volumeUnit", "ltr");
+ }
+
+ public static TimeZone getTimezone(Server server, User user) {
+ String timezone = lookupStringAttribute(server, user, "timezone", null);
+ return timezone != null ? TimeZone.getTimeZone(timezone) : TimeZone.getDefault();
+ }
+
+ private static String lookupStringAttribute(Server server, User user, String key, String defaultValue) {
+ String preference;
+ String serverPreference = server.getString(key);
+ String userPreference = user.getString(key);
+ if (server.getForceSettings()) {
+ preference = serverPreference != null ? serverPreference : userPreference;
+ } else {
+ preference = userPreference != null ? userPreference : serverPreference;
+ }
+ return preference != null ? preference : defaultValue;
+ }
+
+ public static void setUserDefaults(User user, Config config) {
+ user.setDeviceLimit(config.getInteger(Keys.USERS_DEFAULT_DEVICE_LIMIT));
+ int expirationDays = config.getInteger(Keys.USERS_DEFAULT_EXPIRATION_DAYS);
+ if (expirationDays > 0) {
+ user.setExpirationTime(new Date(System.currentTimeMillis() + expirationDays * 86400000L));
+ }
+ }
+}
|