diff --git a/wise-webapp/src/main/java/com/wisemapping/dao/UserManagerImpl.java b/wise-webapp/src/main/java/com/wisemapping/dao/UserManagerImpl.java index 3e5f9893..663fe9d2 100644 --- a/wise-webapp/src/main/java/com/wisemapping/dao/UserManagerImpl.java +++ b/wise-webapp/src/main/java/com/wisemapping/dao/UserManagerImpl.java @@ -52,6 +52,7 @@ public class UserManagerImpl @Override + @Nullable public User getUserBy(@NotNull final String email) { User user = null; diff --git a/wise-webapp/src/main/java/com/wisemapping/exceptions/TooManyInactiveAccountsExceptions.java b/wise-webapp/src/main/java/com/wisemapping/exceptions/TooManyInactiveAccountsExceptions.java new file mode 100755 index 00000000..dc2c8428 --- /dev/null +++ b/wise-webapp/src/main/java/com/wisemapping/exceptions/TooManyInactiveAccountsExceptions.java @@ -0,0 +1,37 @@ +/* + * 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.exceptions; + + +import javax.validation.constraints.NotNull; + +public class TooManyInactiveAccountsExceptions + extends ClientException { + private static final String TOO_MANY_INACTIVE_ACCOUNTS = "TOO_MANY_INACTIVE_ACCOUNTS"; + + public TooManyInactiveAccountsExceptions(@NotNull long accounts) { + super("Too many inactive accounts:" + accounts, Severity.WARNING); + } + + @NotNull + @Override + protected String getMsgBundleKey() { + return TOO_MANY_INACTIVE_ACCOUNTS; + } +} diff --git a/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java b/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java index c59eb0f2..370f7c57 100644 --- a/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java +++ b/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java @@ -41,7 +41,6 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; @Controller @@ -49,6 +48,7 @@ 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 @@ -58,6 +58,10 @@ public class MindmapController extends BaseController { @Autowired private LabelService labelService; + @Qualifier("userService") + @Autowired + private UserService userService; + @RequestMapping(method = RequestMethod.GET, value = "/maps/{id}", produces = {"application/json"}) @ResponseBody public RestMindmap retrieve(@PathVariable int id) throws WiseMappingException { @@ -169,7 +173,7 @@ public class MindmapController extends BaseController { /** * The intention of this method is the update of several properties at once ... */ - @RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}", consumes = { "application/json"}, produces = {"application/json"}) + @RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}", consumes = {"application/json"}, produces = {"application/json"}) @ResponseStatus(value = HttpStatus.NO_CONTENT) public void updateProperties(@RequestBody RestMindmap restMindmap, @PathVariable int id, @RequestParam(required = false) boolean minor) throws IOException, WiseMappingException { @@ -243,7 +247,7 @@ public class MindmapController extends BaseController { @RequestMapping(method = RequestMethod.POST, value = "/maps/{id}/collabs/", consumes = {"application/json"}, produces = {"application/json"}) @ResponseStatus(value = HttpStatus.NO_CONTENT) - public void updateCollabs(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException, AccessDeniedSecurityException, InvalidEmailException { + public void updateCollabs(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException, AccessDeniedSecurityException, InvalidEmailException, TooManyInactiveAccountsExceptions { final Mindmap mindMap = findMindmapById(id); // Only owner can change collaborators... @@ -252,6 +256,9 @@ public class MindmapController extends BaseController { throw new IllegalArgumentException("No enough permissions"); } + // Do not allow more than 20 collabs not active + verifyActiveCollabs(restCollabs, user); + // Compare one by one if some of the elements has been changed .... final Set collabsToRemove = new HashSet<>(mindMap.getCollaborations()); for (RestCollaboration restCollab : restCollabs.getCollaborations()) { @@ -279,7 +286,6 @@ public class MindmapController extends BaseController { if (role != CollaborationRole.OWNER) { mindmapService.addCollaboration(mindMap, restCollab.getEmail(), role, restCollabs.getMessage()); } - } // Remove all collaborations that no applies anymore .. @@ -290,7 +296,7 @@ public class MindmapController extends BaseController { @RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/collabs/", consumes = {"application/json"}, produces = {"application/json"}) @ResponseStatus(value = HttpStatus.NO_CONTENT) - public void addCollab(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException, AccessDeniedSecurityException, InvalidEmailException { + public void addCollab(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException, AccessDeniedSecurityException, InvalidEmailException, TooManyInactiveAccountsExceptions { final Mindmap mindMap = findMindmapById(id); // Only owner can change collaborators... @@ -299,6 +305,9 @@ public class MindmapController extends BaseController { throw new AccessDeniedSecurityException("User must be owner to share mindmap"); } + // Do not allow more than 20 collabs not active + verifyActiveCollabs(restCollabs, user); + // Is valid email address ? final EmailValidator emailValidator = EmailValidator.getInstance(); final Set invalidEmails = restCollabs @@ -503,7 +512,7 @@ public class MindmapController extends BaseController { response.setHeader("ResourceId", Integer.toString(mindmap.getId())); } - @RequestMapping(method = RequestMethod.POST, value = "/maps/{id}", consumes = {"application/json"}, produces = { "application/json", "text/plain"}) + @RequestMapping(method = RequestMethod.POST, value = "/maps/{id}", consumes = {"application/json"}, produces = {"application/json", "text/plain"}) @ResponseStatus(value = HttpStatus.CREATED) public void createDuplicate(@RequestBody RestMindmapInfo restMindmap, @PathVariable int id, @NotNull HttpServletResponse response) throws IOException, WiseMappingException { // Validate ... @@ -588,4 +597,25 @@ public class MindmapController extends BaseController { } return result; } + + private void verifyActiveCollabs(@NotNull RestCollaborationList restCollabs, User user) throws TooManyInactiveAccountsExceptions { + // Do not allow more than 20 new accounts per mindmap... + final List userMindmaps = mindmapService.findMindmapsByUser(user); + final Set allEmails = userMindmaps + .stream() + .filter(m -> m.hasPermissions(user, CollaborationRole.OWNER)) + .map(Mindmap::getCollaborations) + .flatMap(Collection::stream) + .map(c -> c.getCollaborator().getEmail()) + .collect(Collectors.toSet()); + allEmails.addAll(restCollabs + .getCollaborations().stream() + .map(RestCollaboration::getEmail) + .collect(Collectors.toSet())); + + long inactiveAccounts = allEmails.stream().filter(e -> userService.getUserBy(e) == null).count(); + if (inactiveAccounts > MAX_ACCOUNTS_INACTIVE) { + throw new TooManyInactiveAccountsExceptions(inactiveAccounts); + } + } } diff --git a/wise-webapp/src/main/resources/messages_en.properties b/wise-webapp/src/main/resources/messages_en.properties index f28273c7..36de1159 100644 --- a/wise-webapp/src/main/resources/messages_en.properties +++ b/wise-webapp/src/main/resources/messages_en.properties @@ -68,4 +68,5 @@ PASSWORD_CHANGED.EMAIL_TITLE=Your password has been changed successfully PASSWORD_CHANGED.EMAIL_BODY=

This is only an notification that your password has been changed. No further action is required.

SHARE_MAP.EMAIL_SUBJECT={0} has shared a mind map with you EMAIL.DO_NOT_REPLAY=Important: Do not reply this email. If you need further help or have any concerns regarding your account, contact us to here. -EMAIL.GREETINGS=Hi \ No newline at end of file +EMAIL.GREETINGS=Hi +TOO_MANY_INACTIVE_ACCOUNTS=You have shared your mindmaps to more than 20 user that have not registered yet. Please, remove inactive accounts or ask them to register. \ No newline at end of file