Add exclusion list for domains.

main
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

@ -1,20 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* 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 com.wisemapping.rest;
@ -26,19 +26,16 @@ import com.wisemapping.model.User;
import com.wisemapping.rest.model.RestUser;
import com.wisemapping.service.MindmapService;
import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Pattern;
@Controller
public class AdminController extends BaseController {
@ -70,7 +67,7 @@ public class AdminController extends BaseController {
return new RestUser(user);
}
@RequestMapping(method = RequestMethod.POST, value = "admin/users", consumes = { "application/json"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.POST, value = "admin/users", consumes = {"application/json"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.CREATED)
public void createUser(@RequestBody RestUser user, HttpServletResponse response) throws WiseMappingException {
if (user == null) {
@ -109,7 +106,7 @@ public class AdminController extends BaseController {
@RequestMapping(method = RequestMethod.PUT, value = "admin/users/{id}/password", consumes = {"text/plain"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void changePassword(@RequestBody String password, @PathVariable int id) throws WiseMappingException {
public void changePassword(@RequestBody String password, @PathVariable int id) throws WiseMappingException {
if (password == null) {
throw new IllegalArgumentException("Password can not be null");
}
@ -133,7 +130,7 @@ public class AdminController extends BaseController {
final List<Collaboration> collaborations = mindmapService.findCollaborations(user);
for (Collaboration collaboration : collaborations) {
final Mindmap mindmap = collaboration.getMindMap();
mindmapService.removeMindmap(mindmap,user);
mindmapService.removeMindmap(mindmap, user);
}
userService.removeUser(user);

View File

@ -29,6 +29,7 @@ import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
@ -48,7 +49,6 @@ public class MindmapController extends BaseController {
final Logger logger = Logger.getLogger(MindmapController.class);
private static final String LATEST_HISTORY_REVISION = "latest";
private static final int MAX_ACCOUNTS_INACTIVE = 20;
@Qualifier("mindmapService")
@Autowired
@ -62,6 +62,9 @@ public class MindmapController extends BaseController {
@Autowired
private UserService userService;
@Value("${accounts.maxInactive:20}")
private int maxAccountsInactive;
@RequestMapping(method = RequestMethod.GET, value = "/maps/{id}", produces = {"application/json"})
@ResponseBody
public RestMindmap retrieve(@PathVariable int id) throws WiseMappingException {
@ -614,7 +617,7 @@ public class MindmapController extends BaseController {
.collect(Collectors.toSet()));
long inactiveAccounts = allEmails.stream().filter(e -> userService.getUserBy(e) == null).count();
if (inactiveAccounts > MAX_ACCOUNTS_INACTIVE) {
if (inactiveAccounts > maxAccountsInactive) {
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.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@Controller
@CrossOrigin
@ -52,6 +54,9 @@ public class UserController extends BaseController {
@Value("${google.recaptcha2.enabled}")
private Boolean recatchaEnabled;
@Value("${accounts.exclusion.domain:''}")
private String domainBanExclusion;
private static final Logger logger = Logger.getLogger(UserController.class);
private static final String REAL_IP_ADDRESS_HEADER = "X-Real-IP";
@ -115,5 +120,12 @@ public class UserController extends BaseController {
if (errors.hasErrors()) {
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)) {
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);
return new UsernamePasswordAuthenticationToken(userDetails, credentials, userDetails.getAuthorities());
}

View File

@ -23,6 +23,7 @@ import com.wisemapping.model.User;
import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
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) {
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.firstName.attribute=givenName
# User Account filtering policies
# Coma separated list of domains and emails ban
#accounts.exclusion.domain=