Add exclusion list for domains.

This commit is contained in:
Paulo Gustavo Veiga 2022-04-11 17:50:19 -03:00
parent 7af7925610
commit 3e9a5a0b12
6 changed files with 49 additions and 96 deletions

View File

@ -26,19 +26,16 @@ import com.wisemapping.model.User;
import com.wisemapping.rest.model.RestUser; import com.wisemapping.rest.model.RestUser;
import com.wisemapping.service.MindmapService; import com.wisemapping.service.MindmapService;
import com.wisemapping.service.UserService; import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
@Controller @Controller
public class AdminController extends BaseController { public class AdminController extends BaseController {

View File

@ -29,6 +29,7 @@ import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -48,7 +49,6 @@ public class MindmapController extends BaseController {
final Logger logger = Logger.getLogger(MindmapController.class); final Logger logger = Logger.getLogger(MindmapController.class);
private static final String LATEST_HISTORY_REVISION = "latest"; private static final String LATEST_HISTORY_REVISION = "latest";
private static final int MAX_ACCOUNTS_INACTIVE = 20;
@Qualifier("mindmapService") @Qualifier("mindmapService")
@Autowired @Autowired
@ -62,6 +62,9 @@ public class MindmapController extends BaseController {
@Autowired @Autowired
private UserService userService; private UserService userService;
@Value("${accounts.maxInactive:20}")
private int maxAccountsInactive;
@RequestMapping(method = RequestMethod.GET, value = "/maps/{id}", produces = {"application/json"}) @RequestMapping(method = RequestMethod.GET, value = "/maps/{id}", produces = {"application/json"})
@ResponseBody @ResponseBody
public RestMindmap retrieve(@PathVariable int id) throws WiseMappingException { public RestMindmap retrieve(@PathVariable int id) throws WiseMappingException {
@ -614,7 +617,7 @@ public class MindmapController extends BaseController {
.collect(Collectors.toSet())); .collect(Collectors.toSet()));
long inactiveAccounts = allEmails.stream().filter(e -> userService.getUserBy(e) == null).count(); long inactiveAccounts = allEmails.stream().filter(e -> userService.getUserBy(e) == null).count();
if (inactiveAccounts > MAX_ACCOUNTS_INACTIVE) { if (inactiveAccounts > maxAccountsInactive) {
throw new TooManyInactiveAccountsExceptions(inactiveAccounts); throw new TooManyInactiveAccountsExceptions(inactiveAccounts);
} }
} }

View File

@ -38,6 +38,8 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@Controller @Controller
@CrossOrigin @CrossOrigin
@ -52,6 +54,9 @@ public class UserController extends BaseController {
@Value("${google.recaptcha2.enabled}") @Value("${google.recaptcha2.enabled}")
private Boolean recatchaEnabled; private Boolean recatchaEnabled;
@Value("${accounts.exclusion.domain:''}")
private String domainBanExclusion;
private static final Logger logger = Logger.getLogger(UserController.class); private static final Logger logger = Logger.getLogger(UserController.class);
private static final String REAL_IP_ADDRESS_HEADER = "X-Real-IP"; private static final String REAL_IP_ADDRESS_HEADER = "X-Real-IP";
@ -115,5 +120,12 @@ public class UserController extends BaseController {
if (errors.hasErrors()) { if (errors.hasErrors()) {
throw errors; throw errors;
} }
// Is excluded ?.
final List<String> excludedDomains = Arrays.asList(domainBanExclusion.split(","));
final String emailDomain = registration.getEmail().split("@")[1];
if (excludedDomains.contains(emailDomain)) {
throw new IllegalArgumentException("Email is part of ban exclusion list due to abuse. Please, contact site admin if you think this is an error." + emailDomain);
}
} }
} }

View File

@ -45,6 +45,12 @@ public class AuthenticationProvider implements org.springframework.security.auth
if (user == null || credentials == null || !encoder.matches(user.getPassword(), credentials)) { if (user == null || credentials == null || !encoder.matches(user.getPassword(), credentials)) {
throw new BadCredentialsException("Username/Password does not match for " + auth.getPrincipal()); throw new BadCredentialsException("Username/Password does not match for " + auth.getPrincipal());
} }
// User has been disabled ...
if (!user.isActive()) {
throw new BadCredentialsException("User has been disabled for login " + auth.getPrincipal());
}
userDetailsService.getUserService().auditLogin(user); userDetailsService.getUserService().auditLogin(user);
return new UsernamePasswordAuthenticationToken(userDetails, credentials, userDetails.getAuthorities()); return new UsernamePasswordAuthenticationToken(userDetails, credentials, userDetails.getAuthorities());
} }

View File

@ -23,6 +23,7 @@ import com.wisemapping.model.User;
import com.wisemapping.service.UserService; import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
@ -43,77 +44,6 @@ public class UserDetailsService
} }
} }
// @Override
// @NotNull
// public UserDetails loadUserDetails(@NotNull OpenIDAuthenticationToken token) throws UsernameNotFoundException {
//
// final User tUser = buildUserFromToken(token);
// final User dbUser = userService.getUserBy(tUser.getEmail());
//
// final User result;
// if (dbUser != null) {
// if (!token.getIdentityUrl().equals(dbUser.getAuthenticatorUri())) {
// throw new IllegalStateException("Identity url for this user can not change:" + token.getIdentityUrl());
// }
// result = dbUser;
// } else {
// try {
// tUser.setAuthenticationType(AuthenticationType.OPENID);
// tUser.setAuthenticatorUri(token.getIdentityUrl());
//
// result = userService.createUser(tUser, false, false);
// } catch (WiseMappingException e) {
// throw new IllegalStateException(e);
// }
//
// }
// return new UserDetails(result, isAdmin(result.getEmail()));
// }
// @NotNull
// private User buildUserFromToken(@NotNull OpenIDAuthenticationToken token) {
// final User result = new User();
//
// String lastName = null;
// String firstName = null;
// String email = null;
// String fullName = null;
//
// final List<OpenIDAttribute> attributes = token.getAttributes();
// for (OpenIDAttribute attribute : attributes) {
// if (attribute.getName().equals("email")) {
// email = attribute.getValues().get(0);
// }
//
// if (attribute.getName().equals("firstname")) {
// firstName = attribute.getValues().get(0);
//
// }
//
// if (attribute.getName().equals("lastname")) {
// lastName = attribute.getValues().get(0);
// }
//
// if (attribute.getName().equals("fullname")) {
// fullName = attribute.getValues().get(0);
// }
//
// }
// if (lastName == null || firstName == null) {
// result.setFirstname(fullName);
// result.setLastname("");
// } else {
// result.setLastname(lastName);
// result.setFirstname(firstName);
// }
// result.setEmail(email);
// result.setPassword("");
//
// final Calendar now = Calendar.getInstance();
// result.setActivationDate(now);
// return result;
// }
private boolean isAdmin(@Nullable String email) { private boolean isAdmin(@Nullable String email) {
return email != null && adminUser != null && email.trim().endsWith(adminUser); return email != null && adminUser != null && email.trim().endsWith(adminUser);
} }

View File

@ -134,6 +134,11 @@ security.ldap.auth.attribute=mail
security.ldap.lastName.attribute=sn security.ldap.lastName.attribute=sn
security.ldap.firstName.attribute=givenName security.ldap.firstName.attribute=givenName
# User Account filtering policies
# Coma separated list of domains and emails ban
#accounts.exclusion.domain=