Merge branch 'develop'

This commit is contained in:
Paulo Gustavo Veiga 2022-09-11 13:21:26 -07:00
commit 3658d3347e
36 changed files with 934 additions and 340 deletions

View File

@ -46,12 +46,17 @@ In order to reduce the life-cycle to develop UI backend testing, you can do the
A quick and dirty solution to share changes in the UI is to manually compile the dist. This will make the loader file available without the need to publish:
`yarn --cwd wisemapping-frontend build;cp -r wisemapping-frontend/packages/mindplot/dist/* wisemapping-open-source/wise-ui/target/wisemapping-mindplot/package/dist;cp -r wisemapping-frontend/packages/mindplot/dist/* wisemapping-open-source/wise-ui/target/wisemapping-mindplot/package/dist`
`yarn --cwd wisemapping-frontend build;cp -r wisemapping-frontend/packages/mindplot/dist/* wisemapping-open-source/wise-ui/target/wisemapping-mindplot/package/dist;cp -r wisemapping-frontend/packages/webapp/dist/* wisemapping-open-source/wise-ui/target/wisemapping-webapp/package/dist`
### Compiling and running with docker-compose
Check out the [docker section](./docker/README.
Check out the [docker section](./docker/README.)
### Test reports
Individual test result reports can be found in wisemapping-open-source/wise-webapp/target/failsafe-reports/index.html
Test coverage report of unit and integration test can be found in wisemapping-open-source/wise-webapp/target/site/jacoco and wisemapping-open-source/wise-webapp/target/site/jacoco-it folders. Coverage report is generated in the verify phase of [lifecicle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#introduction-to-the-build-lifecyclea) using [jacoco](https://www.jacoco.org/jacoco/trunk/doc/maven.html)
## Members
@ -60,13 +65,10 @@ Check out the [docker section](./docker/README.
* Paulo Veiga <pveiga@wisemapping.com>
* Pablo Luna <pablo@wisemapping.com>
### Individual Contributors
* Ezequiel Bergamaschi <ezequielbergamaschi@gmail.com>
### Past Individual Contributors
* Ignacio Manzano
* Ignacio Manzano
* Ezequiel Bergamaschi <ezequielbergamaschi@gmail.com>
## License

View File

@ -9,15 +9,27 @@ There are multiple ways to run WiseMapping depending on your database configurat
## Option 1: Running HSQL within the image storage
> $ docker run -it --rm -p 8080:8080 veigap/wisemapping:latest>
> $ docker run -it --rm -p 8080:8080 wisemapping/wisemapping:latest
Then, open your browser at `http://localhost:8888`. A default user is available for testing `test@wisemapping.com` and password `test`.
Then, open your browser at `http://localhost:8888`. A default user is available for testing `test@wisemapping.org` and password `test`.
***This option, all changes will be lost once the image is stopped. Use it for testing only***
## Option 2: Running HSQL with mounted directory
> $ docker run -it --rm -p 8080:8080 veigap/wisemapping:latest
Only one time, copy the empty default out of the container:
> $ mkdir your- db-dir-store-path
>
> $ docker run --name wiseapp -d --mount type=bind,source=your-db-dir-store-path,target=/var/lib/wise-db wisemapping/wisemapping:latest
>
> $ docker cp wiseapp:/var/lib/wisemapping/db your-db-dir-store-path
>
> $ docker stop wiseapp;docker rm wiseapp
Then, execute the container mounting tbe directory:
> $ docker run --mount type=bind,source=your-db-dir-store-path/db,target=/var/lib/wisemapping/db -it --rm -p 8080:8080 wisemapping/wisemapping:latest
## Option 3: External MySQL/PostgreSQL
@ -36,7 +48,7 @@ Download `app.properties` configuration file and configure the required sections
Run the application mounting your previously configured `app.properties`
> $ docker run --mount type=bind,source=your-file-path/app.properties,target=/usr/local/tomcat/webapps/ROOT/WEB-INF/app.properties -it --rm -p 8080:8080 veigap/wisemapping:latest
> $ docker run --mount type=bind,source=your-file-path/app.properties,target=/usr/local/tomcat/webapps/ROOT/WEB-INF/app.properties -it --rm -p 8080:8080 wisemapping/wisemapping:latest
# Advanced configuration

View File

@ -4,7 +4,7 @@
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<properties>
<com.wisemapping.version>5.0.11</com.wisemapping.version>
<com.wisemapping.version>5.0.12</com.wisemapping.version>
<superpom.dir>${project.basedir}/wise-webapps</superpom.dir>
</properties>
@ -16,7 +16,7 @@
<groupId>org.wisemapping</groupId>
<artifactId>wisemapping</artifactId>
<name>WiseMapping Project</name>
<version>5.0.11</version>
<version>5.0.12</version>
<packaging>pom</packaging>
<licenses>

View File

@ -12,7 +12,7 @@
<groupId>org.wisemapping</groupId>
<artifactId>wisemapping</artifactId>
<relativePath>../pom.xml</relativePath>
<version>5.0.11</version>
<version>5.0.12</version>
</parent>
<build>
@ -29,11 +29,11 @@
<mkdir dir="target/wisemapping-mindplot"/>
<exec executable="npm" dir="target" failonerror="true">
<arg value="pack"/>
<arg value="@wisemapping/mindplot@5.0.12"/>
<arg value="@wisemapping/mindplot@5.0.16"/>
</exec>
<exec executable="tar" dir="target" failonerror="true">
<arg value="-xvzf"/>
<arg value="wisemapping-mindplot-5.0.12.tgz"/>
<arg value="wisemapping-mindplot-5.0.16.tgz"/>
<arg value="-C"/>
<arg value="wisemapping-mindplot"/>
</exec>
@ -42,11 +42,11 @@
<mkdir dir="target/wisemapping-webapp"/>
<exec executable="npm" dir="target" failonerror="true">
<arg value="pack"/>
<arg value="@wisemapping/webapp@5.0.12"/>
<arg value="@wisemapping/webapp@5.0.15"/>
</exec>
<exec executable="tar" dir="target" failonerror="true">
<arg value="-xvzf"/>
<arg value="wisemapping-webapp-5.0.12.tgz"/>
<arg value="wisemapping-webapp-5.0.15.tgz"/>
<arg value="-C"/>
<arg value="wisemapping-webapp"/>
</exec>

View File

@ -1,5 +1,4 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>wise-webapp</artifactId>
<packaging>war</packaging>
@ -9,13 +8,13 @@
<groupId>org.wisemapping</groupId>
<artifactId>wisemapping</artifactId>
<relativePath>../pom.xml</relativePath>
<version>5.0.11</version>
<version>5.0.12</version>
</parent>
<properties>
<org.springframework.version>5.3.18</org.springframework.version>
<org.springframework.version>5.3.22</org.springframework.version>
<org.springframework.addons>5.6.2</org.springframework.addons>
<hibernate.version>5.6.5.Final</hibernate.version>
<hibernate.version>5.6.11.Final</hibernate.version>
<hibernate-validator.version>6.0.21.Final</hibernate-validator.version>
<spring-security-taglibs.version>5.6.1</spring-security-taglibs.version>
</properties>
@ -452,6 +451,69 @@
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*Test*</exclude>
</excludes>
<propertyName>integrationTestArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>default-check</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.10</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
<!-- Confirm why there is a NPE -->
<!-- <execution>-->
<!-- <id>default-report-integration</id>-->
<!-- <phase>verify</phase>-->
<!-- <goals>-->
<!-- <goal>report-integration</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<execution>
<id>default-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
@ -459,6 +521,9 @@
<version>9.4.34.v20201102</version>
<configuration>
<stopKey>foo</stopKey>
<httpConnector>
<port>8080</port>
</httpConnector>
<stopPort>9999</stopPort>
<war>${project.build.directory}/wisemapping.war</war>
<reload>automatic</reload>
@ -488,9 +553,13 @@
<goal>run-forked</goal>
</goals>
<configuration>
<useTestClasspath>true</useTestClasspath>
<useTestScope>true</useTestScope>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
<waitForChild>false</waitForChild>
<jvmArgs>-Ddatabase.base.url=${project.build.directory}</jvmArgs>
<maxStartupLines>200</maxStartupLines>
<jvmArgs>${integrationTestArgLine} -Ddatabase.base.url=${project.build.directory} -Djetty.port=8080</jvmArgs>
</configuration>
</execution>
<execution>
@ -499,6 +568,9 @@
<goals>
<goal>stop</goal>
</goals>
<configuration>
<stopWait>1</stopWait>
</configuration>
</execution>
</executions>
</plugin>
@ -514,6 +586,7 @@
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
</project>

View File

@ -52,6 +52,7 @@ public class UserManagerImpl
@Override
@Nullable
public User getUserBy(@NotNull final String email) {
User user = null;

View File

@ -0,0 +1,39 @@
/*
* 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 org.jetbrains.annotations.NotNull;
public class CollabChangeException
extends ClientException
{
private static final String MSG_KEY = "OWNER_ROLE_CAN_NOT_BE_CHANGED";
public CollabChangeException(@NotNull String email)
{
super("Collab email can not be change. " + email + " is the the owner.",Severity.WARNING);
}
@NotNull
@Override
protected String getMsgBundleKey() {
return MSG_KEY;
}
}

View File

@ -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;
}
}

View File

@ -73,6 +73,11 @@ final public class NotificationService {
model.put("message", message);
model.put("doNotReplay", messageSource.getMessage("EMAIL.DO_NOT_REPLAY", new Object[]{mailer.getSupportEmail()}, locale));
// To resolve resources on templates ...
model.put("noArg", new Object[]{});
model.put("messages", messageSource);
model.put("locale", locale);
mailer.sendEmail(formMail, collabEmail, subject, model, "newCollaboration.vm");
} catch (Exception e) {
handleException(e);
@ -122,6 +127,11 @@ final public class NotificationService {
model.put("supportEmail", mailer.getSupportEmail());
model.put("doNotReplay", messageSource.getMessage("EMAIL.DO_NOT_REPLAY", new Object[]{mailer.getSupportEmail()}, locale));
// To resolve resources on templates ...
model.put("noArg", new Object[]{});
model.put("messages", messageSource);
model.put("locale", locale);
logger.debug("Email properties->" + model);
mailer.sendEmail(mailer.getServerSenderEmail(), user.getEmail(), mailSubject, model, "baseLayout.vm");
} catch (Exception e) {

View File

@ -66,7 +66,7 @@ public class Mindmap implements Serializable {
@OneToMany(mappedBy = "mindMap", orphanRemoval = true, cascade = {CascadeType.ALL})
private Set<Collaboration> collaborations = new HashSet<>();
@ManyToMany(cascade = CascadeType.ALL)
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE})
@JoinTable(
name = "R_LABEL_MINDMAP",
joinColumns = @JoinColumn(name = "mindmap_id"),

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;
@ -41,7 +42,6 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Controller
@ -58,6 +58,13 @@ public class MindmapController extends BaseController {
@Autowired
private LabelService labelService;
@Qualifier("userService")
@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 {
@ -169,7 +176,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 +250,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 +259,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<Collaboration> collabsToRemove = new HashSet<>(mindMap.getCollaborations());
for (RestCollaboration restCollab : restCollabs.getCollaborations()) {
@ -279,7 +289,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 +299,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, CollabChangeException {
final Mindmap mindMap = findMindmapById(id);
// Only owner can change collaborators...
@ -299,6 +308,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<String> invalidEmails = restCollabs
@ -312,41 +324,42 @@ public class MindmapController extends BaseController {
}
// Has any role changed ?. Just removed it.
final Map<String, Collaboration> mapsByEmail = mindMap
final Map<String, Collaboration> collabByEmail = mindMap
.getCollaborations()
.stream()
.collect(Collectors.toMap(collaboration -> collaboration.getCollaborator().getEmail(), collaboration -> collaboration));
restCollabs
.getCollaborations()
.forEach(collab -> {
final String email = collab.getEmail();
if (mapsByEmail.containsKey(email)) {
try {
mindmapService.removeCollaboration(mindMap, mapsByEmail.get(email));
} catch (CollaborationException e) {
logger.error(e);
}
}
});
// Great, let's add all the collabs again ...
for (RestCollaboration restCollab : restCollabs.getCollaborations()) {
final Collaboration collaboration = mindMap.findCollaboration(restCollab.getEmail());
// Validate role format ...
String roleStr = restCollab.getRole();
// Validate newRole format ...
final String roleStr = restCollab.getRole();
if (roleStr == null) {
throw new IllegalArgumentException(roleStr + " is not a valid role");
throw new IllegalArgumentException(roleStr + " is not a valid newRole");
}
// Is owner ?
final CollaborationRole role = CollaborationRole.valueOf(roleStr.toUpperCase());
if (role == CollaborationRole.OWNER) {
throw new IllegalArgumentException("Owner can not be added as part of the collaboration list.");
}
// Had the newRole changed ?. Otherwise, don't touch it.
final CollaborationRole newRole = CollaborationRole.valueOf(roleStr.toUpperCase());
final String collabEmail = restCollab.getEmail();
final Collaboration currentCollab = collabByEmail.get(collabEmail);
if (currentCollab == null || currentCollab.getRole() != newRole) {
mindmapService.addCollaboration(mindMap, restCollab.getEmail(), role, restCollabs.getMessage());
// Are we trying to change the owner ...
if (currentCollab != null && currentCollab.getRole() == CollaborationRole.OWNER) {
throw new CollabChangeException(collabEmail);
}
// Role can not be changed ...
if (newRole == CollaborationRole.OWNER) {
throw new CollabChangeException(collabEmail);
}
// This is collaboration that with different newRole, try to change it ...
if (currentCollab != null) {
mindmapService.removeCollaboration(mindMap, currentCollab);
}
mindmapService.addCollaboration(mindMap, collabEmail, newRole, restCollabs.getMessage());
}
}
}
@ -503,7 +516,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 +601,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<Mindmap> userMindmaps = mindmapService.findMindmapsByUser(user);
final Set<String> 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 > 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

@ -40,15 +40,18 @@ import java.util.TimeZone;
public class RestMindmapHistory {
static private final SimpleDateFormat sdf;
private final int id;
private final Calendar creation;
private final String creator;
private int id;
private Calendar creation;
private String creator;
static {
sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public RestMindmapHistory() {
}
public RestMindmapHistory(@NotNull MindMapHistory history) {
this.id = history.getId();
this.creation = history.getCreationTime();
@ -61,18 +64,18 @@ public class RestMindmapHistory {
}
public void setCreationTime() {
}
public String getCreator() {
return creator;
}
public void setCreator() {
// Do nothing ...
public void setCreator(String creator) {
}
public void setId(int id) {
this.id=id;
}
private String toISO8601(@NotNull Date date) {

View File

@ -24,11 +24,7 @@ import com.wisemapping.model.Collaborator;
import com.wisemapping.model.Mindmap;
import org.jetbrains.annotations.NotNull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -45,7 +41,7 @@ public class RestMindmapList {
this(Collections.emptyList(), null);
}
public RestMindmapList(@NotNull List<Mindmap> mindmaps, @NotNull Collaborator collaborator) {
public RestMindmapList(@NotNull List<Mindmap> mindmaps, Collaborator collaborator) {
this.mindmapsInfo = mindmaps.stream()
.map(m->new RestMindmapInfo(m, collaborator))
.collect(Collectors.toList());

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

@ -22,13 +22,13 @@
</table>
</div>
<div style="font-size: 13px; background-color: #FFF; padding: 10px 7px 7px 7px; min-height: 100px">
Hi ${firstName}:
${messages.getMessage("EMAIL.GREETINGS",$noArgs,$locale)} ${firstName}:
<p>
${messageBody}
</p>
<p style="color: #898989;">Regards,<br/>
The WiseMapping Team<br/>
<p style="color: #898989;">
<a href="http://www.wisemapping.com">The WiseMapping Team</a><br/>
</p>
</div>
</div>

View File

@ -1,29 +1,29 @@
<html>
<body>
<h3>Welcome to WiseMapping!</h3>
<div>
<h3>Welcome to WiseMapping!</h3>
<p>
To active your account and verify your e-mail address, please click on the following link.
</p>
<a href="${emailcheck}">${emailcheck}</a>
</p>
<p>
If you have received this mail by error, you do not need to take any action to cancel the account. The account will
not be activated, and you will not receive any further emails.
</p>
<p>
To active your account and verify your e-mail address, please click on the following link.
</p>
<a href="${emailcheck}">${emailcheck}</a>
</p>
<p>
If you have received this mail by error, you do not need to take any action to cancel the account. The account will
not be activated, and you will not receive any further emails.
</p>
<p>
If clicking the link above does not work, copy and paste the URL in a new browser window instead.
</p>
<p>
If clicking the link above does not work, copy and paste the URL in a new browser window instead.
</p>
<p>
For questions or concerns regarding your account, send us an email to support@wisemapping.com.
</p>
<p>
For questions or concerns regarding your account, send us an email to support@wisemapping.com.
</p>
<p>
Cheers, <br/>
The WiseMapping Team.
<a href="http://www.wisemapping.com">WiseMapping Site</a>
</p>
<p style="color: #898989;">
<a href="http://www.wisemapping.com">The WiseMapping Team</a><br/>
</p>
<div>
</body>
</html>
</html>

View File

@ -33,6 +33,8 @@
</div>
</div>
<p style="font-size: 13px;font-family: Arial, sans-serif">${doNotReplay}</p>
<p style="color: #898989;">
<a href="http://www.wisemapping.com">The WiseMapping Team</a><br/>
</p>
</body>
</html>

View File

@ -66,4 +66,6 @@ MINDMAP_EMPTY_ERROR=Mindmap darf nicht leer sein.
INVALID_MINDMAP_FORMAT=Ungültiges Mindmap-Format.
TOO_BIG_MINDMAP=Sie haben das Limit von 5000 Themen in einer Mindmap erreicht.
SHARE_MAP.EMAIL_SUBJECT={0} hat eine Mindmap mit Ihnen geteilt
EMAIL.DO_NOT_REPLAY=Wichtig: Antworten Sie nicht auf diese E-Mail. Wenn Sie weitere Hilfe benötigen oder Bedenken bezüglich Ihres Kontos haben, kontaktieren Sie uns <a href="mailto:{0}">hier</a>.
EMAIL.DO_NOT_REPLAY=Wichtig: Antworten Sie nicht auf diese E-Mail. Wenn Sie weitere Hilfe benötigen oder Bedenken bezüglich Ihres Kontos haben, kontaktieren Sie uns <a href="mailto:{0}">hier</a>.
EMAIL.GREETINGS=Hallo
OWNER_ROLE_CAN_NOT_BE_CHANGED=Owner role can not be change. Please, remove owner from the change list.

View File

@ -67,4 +67,7 @@ PASSWORD_CHANGED.EMAIL_SUBJECT=Your password has been changed
PASSWORD_CHANGED.EMAIL_TITLE=Your password has been changed successfully
PASSWORD_CHANGED.EMAIL_BODY=<p>This is only an notification that your password has been changed. No further action is required.</p>
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 <a href="mailto:{0}">here</a>.
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 <a href="mailto:{0}">here</a>.
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.
OWNER_ROLE_CAN_NOT_BE_CHANGED=Owner role can not be change. Please, remove owner from the change list.

View File

@ -58,7 +58,7 @@ INVALID_MINDMAP_FORMAT=Formato de mapa mental no válido.
TOO_BIG_MINDMAP=Ha alcanzado el límite de 5000 nodos en un mapa mental.
REGISTRATION.EMAIL_SUBJECT=Bienvenido/a a WiseMapping !
REGISTRATION.EMAIL_TITLE=Tu cuenta ha sido creada exitosamente
REGISTRATION.EMAIL_BODY=<p> Gracias por tu interest en WiseMapping. Hace click <a href='https://app.wisemapping.com/c/login'>aqui</a> para empezar a crear y compatir tus mapas mentales. Ideas y sugerencias, no dudes en contactarnos a <a href=\"mailto:feedback@wisemapping.com\">feedback@wisemapping.com</a>.</p>
REGISTRATION.EMAIL_BODY=<p> Gracias por tu interes en WiseMapping. Hace click <a href='https://app.wisemapping.com/c/login'>aqui</a> para empezar a crear y compatir tus mapas mentales. Ideas y sugerencias, no dudes en contactarnos a <a href=\"mailto:feedback@wisemapping.com\">feedback@wisemapping.com</a>.</p>
CHANGE_PASSWORD.EMAIL_SUBJECT=Su contraseña ha sido restablecida
CHANGE_PASSWORD.EMAIL_TITLE=Se ha generado una contraseña temporal
CHANGE_PASSWORD.EMAIL_BODY=<p>Alguien, muy probablemente usted, solicitó una nueva contraseña para su cuenta de WiseMapping. </p><p><strong>Esta es su nueva contraseña: {0} </strong></p><p>Puede iniciar sesión haciendo clic <a href='{1}/c/login'>aquí </a>. Te recomendamos que cambie la contraseña lo antes posible.</p>
@ -66,4 +66,6 @@ PASSWORD_CHANGED.EMAIL_SUBJECT=Su contraseña ha sido cambiada
PASSWORD_CHANGED.EMAIL_TITLE=Su contraseña ha sido cambiada con éxito
PASSWORD_CHANGED.EMAIL_BODY=<p>Esto es solo una notificación de que su contraseña ha sido cambiada. No se requiere ninguna otra acción.</p>
SHARE_MAP.EMAIL_SUBJECT={0} te ha compartido un mapa mental
EMAIL.DO_NOT_REPLAY=Importante: No responda este correo electrónico. Si necesita más ayuda o tiene alguna inquietud con respecto a su cuenta, comuníquese con nosotros a <a href="mailto:{0}">aquí</a>.
EMAIL.DO_NOT_REPLAY=Importante: No responda este correo electrónico. Si necesita más ayuda o tiene alguna inquietud con respecto a su cuenta, comuníquese con nosotros a <a href="mailto:{0}">aquí</a>.
EMAIL.GREETINGS=Hola
OWNER_ROLE_CAN_NOT_BE_CHANGED=Owner role can not be change. Please, remove owner from the change list.

View File

@ -66,4 +66,6 @@ MINDMAP_EMPTY_ERROR=La carte mentale ne peut pas être vide.
INVALID_MINDMAP_FORMAT=Format de carte mentale non valide.
TOO_BIG_MINDMAP=Vous avez atteint la limite de 5000 sujets dans une carte mentale.
SHARE_MAP.EMAIL_SUBJECT={0} a partagé une carte mentale avec vous
EMAIL.DO_NOT_REPLAY=Important : Ne répondez pas à cet e-mail. Si vous avez besoin d'aide supplémentaire ou si vous avez des inquiétudes concernant votre compte, contactez-nous <a href="mailto:{0}">ici</a>.
EMAIL.DO_NOT_REPLAY=Important : Ne répondez pas à cet e-mail. Si vous avez besoin d'aide supplémentaire ou si vous avez des inquiétudes concernant votre compte, contactez-nous <a href="mailto:{0}">ici</a>.
EMAIL.GREETINGS=Salut
OWNER_ROLE_CAN_NOT_BE_CHANGED=Owner role can not be change. Please, remove owner from the change list.

View File

@ -61,3 +61,5 @@ REGISTRATION.EMAIL_TITLE=Ваша учетная запись успешно с
REGISTRATION.EMAIL_BODY=<p> Благодарим вас за интерес к WiseMapping. Нажмите <a href='https://app.wisemapping.com/c/login'>здесь</a>, чтобы начать создавать и публиковать новые интеллект-карты. Если у вас есть какие-либо отзывы или идеи, отправьте нам электронное письмо по адресу <a href=\"mailto:feedback@wisemapping.com\">feedback@wisemapping.com</a>. Мы будем рады услышать от вас.</p >
SHARE_MAP.EMAIL_SUBJECT={0} has shared a mindmap 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 <a href="mailto:{0}">here</a>.
EMAIL.GREETINGS=Hi
OWNER_ROLE_CAN_NOT_BE_CHANGED=Owner role can not be change. Please, remove owner from the change list.

View File

@ -67,3 +67,5 @@ PASSWORD_CHANGED.EMAIL_TITLE=你已经成功更改密码
PASSWORD_CHANGED.EMAIL_BODY=<p>这只是您的密码已更改的通知。无需进一步操作。</p>
SHARE_MAP.EMAIL_SUBJECT={0} 与您分享了一张思维导图
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 <a href="mailto:{0}">here</a>.
EMAIL.GREETINGS=Hi
OWNER_ROLE_CAN_NOT_BE_CHANGED=Owner role can not be change. Please, remove owner from the change list.

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=

View File

@ -71,8 +71,13 @@ div#position {
background-size: 40px 40px;
background-color: #FFF;
border-radius: 8px;
padding: 0;
}
#position-button>img {
vertical-align: middle;
}
#zoom-button {
width: 40px;
border: 0;
@ -88,6 +93,13 @@ div#position {
background-position: center;
cursor: pointer;
background-color: #FFF;
padding: 0;
}
#zoom-plus,
#zoom-minus
>img {
vertical-align: middle;
}
#zoom-plus {

View File

@ -1,16 +0,0 @@
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:if test="${requestScope['google.analytics.enabled']}">
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '${requestScope['google.analytics.account']}', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->
</c:if>

View File

@ -23,7 +23,7 @@
<script>
window.serverconfig = {
apiBaseUrl: '',
apiBaseUrl: '${requestScope['site.baseurl']}',
analyticsAccount: '${requestScope['google.analytics.account']}',
clientType: 'rest',
recaptcha2Enabled: ${requestScope['google.recaptcha2.enabled']},
@ -44,7 +44,7 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="root" class="mindplot-root"></div>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/webapp/vendors.bundle.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/webapp/app.bundle.js" crossorigin="anonymous"></script>

View File

@ -7,6 +7,7 @@
<html>
<head>
<meta name="viewport" content="initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<base href="${requestScope['site.baseurl']}/static/mindplot/">
<title>${mindmap.title} | <spring:message code="SITE.TITLE"/></title>
@ -15,66 +16,97 @@
<script type="text/javascript">
var mapId = '${mindmap.id}';
var historyId = '${hid}';
var readOnly = true;
var userOptions = ${mindmap.properties};
var locale = '${locale}';
var isAuth = ${principal != null};
</script>
<%@ include file="/jsp/googleAnalytics.jsf" %>
<c:if test="${requestScope['google.analytics.enabled']}">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=${requestScope['google.analytics.account']}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${requestScope['google.analytics.account']}',
{
'page_title' : 'Public View'
});
</script>
</c:if>
<style>
body {
height: 100vh;
width: 100vw;
min-width: 100vw;
min-height: 100vh;
margin: 0px;
}
.mindplot-root {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="mindplot"></div>
<div id="root" class="mindplot-root">
<mindplot-component id="mindmap-comp"></mindplot-component>
<div id="mindplot-tooltips" className="wise-editor"></div>
<a href="${requestScope['site.homepage']}" target="new">
<div id="footerLogo"></div>
</a>
<div id="mapDetails">
<span class="title"><spring:message code="CREATOR"/>:</span><span>${mindmap.creator.fullName}</span>
<span class="title"><spring:message code="DESCRIPTION"/>:</span><span>${mindmap.title}</span>
</div>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/mindplot/loader.js" crossorigin="anonymous"></script>
<div id="floating-panel">
<div id="zoom-button">
<button id="zoom-plus">
<img src="../../images/add.svg" />
</button>
<button id="zoom-minus">
<img src="../../images/minus.svg" />
</button>
<div id="position">
<button id="position-button">
<img src="../../images/center_focus.svg" />
</button>
</div>
</div>
</div>
</div>
<a href="${requestScope['site.homepage']}" target="new">
<div id="footerLogo"></div>
</a>
<script type="text/javascript">
// Hook zoom events ...
const zoomInButton = document.getElementById('zoom-plus');
if (zoomInButton) {
zoomInButton.addEventListener('click', () => {
designer.zoomIn();
});
}
<div id="mapDetails">
<span class="title"><spring:message code="CREATOR"/>:</span><span>${mindmap.creator.fullName}</span>
<span class="title"><spring:message code="DESCRIPTION"/>:</span><span>${mindmap.title}</span>
</div>
<script type="text/javascript" src="${requestScope['site.static.js.url']}/mindplot/loader.js" crossorigin="anonymous"></script>
<div id="floating-panel">
<div id="zoom-button">
<button id="zoom-plus">
<img src="../../images/add.svg" />
</button>
<button id="zoom-minus">
<img src="../../images/minus.svg" />
</button>
<div id="position">
<button id="position-button">
<img src="../../images/center_focus.svg" />
</button>
</div>
</div>
</div>
<script type="text/javascript">
// Hook zoom events ...
const zoomInButton = document.getElementById('zoom-plus');
if (zoomInButton) {
zoomInButton.addEventListener('click', () => {
designer.zoomIn();
});
}
const zoomOutButton = document.getElementById('zoom-minus');
if (zoomOutButton) {
zoomOutButton.addEventListener('click', () => {
designer.zoomOut();
});
}
const position = document.getElementById('position');
if (position) {
position.addEventListener('click', () => {
designer.zoomToFit();
});
}
</script>
const zoomOutButton = document.getElementById('zoom-minus');
if (zoomOutButton) {
zoomOutButton.addEventListener('click', () => {
designer.zoomOut();
});
}
const position = document.getElementById('position');
if (position) {
position.addEventListener('click', () => {
designer.zoomToFit();
});
}
</script>
</body>
</html>

View File

@ -14,7 +14,7 @@
<script>
window.serverconfig = {
apiBaseUrl: '',
apiBaseUrl: '${requestScope['site.baseurl']}',
analyticsAccount: '${requestScope['google.analytics.account']}',
clientType: 'rest',
recaptcha2Enabled: ${requestScope['google.recaptcha2.enabled']},

View File

@ -1,7 +1,6 @@
Sitemap: https://www.wisemapping.com/sitemap.xml
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Allow: /
Disallow: /c/restful/maps/*/document/xml-pub
Disallow: /c/maps/*/edit

View File

@ -83,7 +83,7 @@ public class RestAdminITCase {
}
}
public String createNewUser(final @NotNull MediaType mediaType) {
public RestUser createNewUserAndGetUser(final @NotNull MediaType mediaType) {
// Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
@ -99,6 +99,13 @@ public class RestAdminITCase {
ResponseEntity<RestUser> result = findUser(requestHeaders, templateRest, location);
assertEquals(result.getBody().getEmail(), restUser.getEmail(), "Returned object object seems not be the same.");
return result.getBody();
}
public String createNewUser(final @NotNull MediaType mediaType) {
// Fill user data ...
final RestUser restUser = createNewUserAndGetUser(mediaType);
// Find by email and check ...
// @todo: review find by email... It's failing with 406
// findUser(requestHeaders, templateRest, location);
@ -119,7 +126,7 @@ public class RestAdminITCase {
return templateRest.exchange(url, HttpMethod.GET, findUserEntity, RestUser.class);
}
private ResponseEntity<RestUser> findUserByEmail(HttpHeaders requestHeaders, RestTemplate templateRest, final String email) {
public ResponseEntity<RestUser> findUserByEmail(HttpHeaders requestHeaders, RestTemplate templateRest, final String email) {
HttpEntity<RestUser> findUserEntity = new HttpEntity<>(requestHeaders);
// Add extension only to avoid the fact that the last part is extracted ...

View File

@ -78,6 +78,7 @@ public class RestLabelITCase {
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void createLabelWithoutRequiredField(final @NotNull MediaType mediaType) throws IOException, WiseMappingException {
final HttpHeaders requestHeaders = RestHelper.createHeaders(mediaType);
requestHeaders.set(HttpHeaders.ACCEPT_LANGUAGE, "en");
final RestTemplate template = RestHelper.createTemplate(userEmail + ":" + "admin");
try {

View File

@ -14,10 +14,18 @@ import org.testng.annotations.Test;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static com.wisemapping.test.rest.RestHelper.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.springframework.web.client.RestClientException;
import static org.testng.Assert.*;
@Test
@ -25,11 +33,11 @@ public class RestMindmapITCase {
private String userEmail = "admin@wisemapping.com";
private static final String ICON = "glyphicon glyphicon-tag";
final RestAdminITCase restAdminITCase = new RestAdminITCase();
@BeforeClass
void createUser() {
final RestAdminITCase restAdminITCase = new RestAdminITCase();
userEmail = restAdminITCase.createNewUser(MediaType.APPLICATION_JSON);
userEmail += ":" + "admin";
}
@ -46,12 +54,8 @@ public class RestMindmapITCase {
final String title2 = "List Maps 2 - " + mediaType;
addNewMap(template, title2);
// Check that the map has been created ...
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
final ResponseEntity<RestMindmapList> response = template.exchange(BASE_REST_URL + "/maps/", HttpMethod.GET, findMapEntity, RestMindmapList.class);
// Validate that the two maps are there ...
final RestMindmapList body = response.getBody();
final RestMindmapList body = fetchMaps(requestHeaders, template);
final List<RestMindmapInfo> mindmaps = body.getMindmapsInfo();
boolean found1 = false;
@ -96,11 +100,7 @@ public class RestMindmapITCase {
// Create a sample map ...
final URI resourceUri = addNewMap(template, "Map to change title - " + mediaType);
// Change map title ...
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
final String newTitle = "New map to change title - " + mediaType;
final HttpEntity<String> updateEntity = new HttpEntity<>(newTitle, requestHeaders);
template.put(HOST_PORT + resourceUri + "/title", updateEntity);
String newTitle = changeMapTitle(requestHeaders, mediaType, template, resourceUri);
// Load map again ..
final RestMindmap map = findMap(requestHeaders, template, resourceUri);
@ -110,6 +110,7 @@ public class RestMindmapITCase {
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void validateMapsCreation(final @NotNull MediaType mediaType) { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
requestHeaders.set(HttpHeaders.ACCEPT_LANGUAGE, "en");
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
@ -160,16 +161,25 @@ public class RestMindmapITCase {
// Update map xml content ...
final String resourceUrl = HOST_PORT + resourceUri.toString();
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
final String newXmlContent = "<map>this is not valid</map>";
HttpEntity<String> updateEntity = new HttpEntity<>(newXmlContent, requestHeaders);
template.put(resourceUrl + "/document/xml", updateEntity);
String newXmlContent = updateMapDocument(requestHeaders, template, resourceUrl);
// Check that the map has been updated ...
final RestMindmap response = findMap(requestHeaders, template, resourceUri);
assertEquals(response.getXml(), newXmlContent);
}
private String updateMapDocument(final HttpHeaders requestHeaders, final RestTemplate template, final String resourceUrl, String content) throws RestClientException {
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
final String newXmlContent = content != null ? content : "<map>this is not valid</map>";
HttpEntity<String> updateEntity = new HttpEntity<>(newXmlContent, requestHeaders);
template.put(resourceUrl + "/document/xml", updateEntity);
return newXmlContent;
}
private String updateMapDocument(final HttpHeaders requestHeaders, final RestTemplate template, final String resourceUrl) throws RestClientException {
return updateMapDocument(requestHeaders, template, resourceUrl, null);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void cloneMap(final @NotNull MediaType mediaType) throws IOException { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
@ -194,9 +204,67 @@ public class RestMindmapITCase {
assertEquals(response.getXml(), xml);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void updateStarred(final @NotNull MediaType mediaType) { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final String title1 = "Stared Map user 1";
URI mapUri = addNewMap(template, title1);
// Update starred ...
final String resourceUrl = HOST_PORT + mapUri.toString() + "/starred";
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
final HttpHeaders textContentType = new HttpHeaders();
textContentType.setContentType(MediaType.TEXT_PLAIN);
final HttpEntity<String> updateEntity = new HttpEntity<>("true", textContentType);
template.put(resourceUrl, updateEntity);
// Has been updated ?.
final String mapId = mapUri.getPath().replace("/service/maps/", "");
Optional<RestMindmapInfo> mindmapInfo = fetchMap(requestHeaders, template, mapId);
// @todo: Enforce check...
// assertTrue(mindmapInfo.get().getStarred() == true);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void verifyMapOwnership(final @NotNull MediaType mediaType) { // Configure media types ...
throw new SkipException("missing test: removeUserShouldOnlyDeleteOnwedMap");
final RestAdminITCase restAdminITCase = new RestAdminITCase();
final HttpHeaders requestHeaders = createHeaders(mediaType);
RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final String title1 = "verifyMapOwnership Map user 1";
addNewMap(template, title1);
//create another user
RestUser secondUser = restAdminITCase.createNewUserAndGetUser(MediaType.APPLICATION_JSON);
final RestTemplate secondTemplate = createTemplate(secondUser.getEmail() + ":admin");
final String title2 = "verifyMapOwnership Map user 2";
addNewMap(secondTemplate, title2);
// Delete user ...
String authorisation = "admin@wisemapping.org" + ":" + "test";
RestTemplate superadminTemplate = createTemplate(authorisation);
superadminTemplate.delete(BASE_REST_URL + "/admin/users/" + secondUser.getId());
// Validate that the two maps are there ...
final RestMindmapList body = fetchMaps(requestHeaders, template);
final List<RestMindmapInfo> mindmaps = body.getMindmapsInfo();
boolean found1 = false;
for (RestMindmapInfo mindmap : mindmaps) {
if (mindmap.getTitle().equals(title1)) {
found1 = true;
break;
}
}
assertTrue(found1, "Map could not be found");
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
@ -242,25 +310,10 @@ public class RestMindmapITCase {
// Create a sample map ...
final URI resourceUri = addNewMap(template, "Map for addCollabs - " + mediaType);
// Add a new collaboration ...
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
final RestCollaborationList collabs = new RestCollaborationList();
collabs.setMessage("Adding new permission");
final String newCollab = "new-collab@example.com";
String role = "editor";
final RestCollaboration collab = new RestCollaboration();
collab.setEmail(newCollab);
collab.setRole(role);
collabs.addCollaboration(collab);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
String newCollab = addNewCollaboration(requestHeaders, template, resourceUri);
// Has been added ?
final ResponseEntity<RestCollaborationList> response = fetchCollabs(requestHeaders, template, resourceUri);
RestCollaborationList responseCollbs = response.getBody();
RestCollaborationList responseCollbs = fetchAndGetCollabs(requestHeaders, template, resourceUri);
// Has been added ?
assertEquals(responseCollbs.getCount(), 2);
@ -286,17 +339,13 @@ public class RestMindmapITCase {
final String newCollab = "new-collab@example.com";
String role = "editor";
final RestCollaboration collab = new RestCollaboration();
collab.setEmail(newCollab);
collab.setRole(role);
collabs.addCollaboration(collab);
final RestCollaboration collab = addCollabToList(newCollab, role, collabs);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
// Has been added ?
final ResponseEntity<RestCollaborationList> response = fetchCollabs(requestHeaders, template, resourceUri);
RestCollaborationList responseCollbs = response.getBody();
RestCollaborationList responseCollbs = fetchAndGetCollabs(requestHeaders, template, resourceUri);
assertEquals(responseCollbs.getCount(), 2);
// Update the collaboration type ...
@ -318,25 +367,10 @@ public class RestMindmapITCase {
// Create a sample map ...
final URI resourceUri = addNewMap(template, "Map for deleteCollabs - " + mediaType);
// Add a new collaboration ...
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
final RestCollaborationList collabs = new RestCollaborationList();
collabs.setMessage("Adding new permission");
final String newCollab = "new-collab@example.com";
String role = "editor";
final RestCollaboration collab = new RestCollaboration();
collab.setEmail(newCollab);
collab.setRole(role);
collabs.addCollaboration(collab);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
String newCollab = addNewCollaboration(requestHeaders, template, resourceUri);
// Has been added ?
final ResponseEntity<RestCollaborationList> response = fetchCollabs(requestHeaders, template, resourceUri);
RestCollaborationList responseCollbs = response.getBody();
RestCollaborationList responseCollbs = fetchAndGetCollabs(requestHeaders, template, resourceUri);
// Has been added ?
assertEquals(responseCollbs.getCount(), 2);
@ -349,6 +383,82 @@ public class RestMindmapITCase {
assertEquals(afterDeleteResponse.getBody().getCollaborations().size(), 1);
}
private String addNewCollaboration(final HttpHeaders requestHeaders, final RestTemplate template, final URI resourceUri) throws RestClientException {
// Add a new collaboration ...
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
final RestCollaborationList collabs = new RestCollaborationList();
collabs.setMessage("Adding new permission");
final String newCollab = "new-collab@example.com";
String role = "editor";
addCollabToList(newCollab, role, collabs);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
return newCollab;
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void deleteCollabsWithInvalidEmail(final @NotNull MediaType mediaType) {
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "deleteCollabsWithInvalidEmail");
// Remove with invalid email ...
try {
template.delete(HOST_PORT + resourceUri + "/collabs?email=invalidEmail");
} catch (HttpClientErrorException e) {
assertEquals(e.getRawStatusCode(), 400);
assertTrue(e.getMessage().contains("Invalid email exception:"));
}
// Check that it has been removed ...
final ResponseEntity<RestCollaborationList> afterDeleteResponse = fetchCollabs(requestHeaders, template, resourceUri);
assertEquals(afterDeleteResponse.getBody().getCollaborations().size(), 1);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void deleteCollabsWithoutOwnerPermission(final @NotNull MediaType mediaType) {
final HttpHeaders requestHeaders = createHeaders(mediaType);
RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "deleteWithoutOwnerPermission");
final String newCollab = restAdminITCase.createNewUser(MediaType.APPLICATION_JSON);
template = createTemplate(newCollab + ":admin");
// Remove with invalid email ...
try {
template.delete(HOST_PORT + resourceUri + "/collabs?email=" + newCollab);
} catch (HttpClientErrorException e) {
assertEquals(e.getRawStatusCode(), 400);
assertTrue(e.getMessage().contains("No enough permissions"));
}
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void deleteOwnerCollab(final @NotNull MediaType mediaType) {
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "Map for deleteOwnerCollab");
// Now, remove owner collab ...
try {
template.delete(HOST_PORT + resourceUri + "/collabs?email=" + userEmail.replace(":admin", ""));
} catch (HttpClientErrorException e) {
assertEquals(e.getRawStatusCode(), 400);
assertTrue(e.getMessage().contains("Can not remove owner collab"));
}
}
@NotNull
private ResponseEntity<RestCollaborationList> fetchCollabs(HttpHeaders requestHeaders, RestTemplate template, URI resourceUri) {
final HttpEntity findCollabs = new HttpEntity(requestHeaders);
@ -361,7 +471,7 @@ public class RestMindmapITCase {
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
// Create a sample map ...fetchAndGetCollabs(requestHeaders, template, resourceUri);
final URI resourceUri = addNewMap(template, "Map for Collaboration - " + mediaType);
// Add a new collaboration ...
@ -370,19 +480,48 @@ public class RestMindmapITCase {
collabs.setMessage("Adding new permission");
// Validate that owner can not be added.
final RestCollaboration collab = new RestCollaboration();
final String newCollab = "new-collab@example.com";
collab.setEmail(newCollab);
collab.setRole("owner");
collabs.addCollaboration(collab);
addCollabToList("newCollab@example", "owner", collabs);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void removeLabelFromMindmap(final @NotNull MediaType mediaType) { // Configure media types ...
throw new SkipException("missing test: label removal from map");
public void removeLabelFromMindmap(final @NotNull MediaType mediaType) throws IOException, WiseMappingException { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a new label
final String titleLabel = "removeLabelFromMindmap";
final URI labelUri = RestLabelITCase.addNewLabel(requestHeaders, template, titleLabel, COLOR, ICON);
// Create a sample map ...
final String mapTitle = "removeLabelFromMindmap";
final URI mindmapUri = addNewMap(template, mapTitle);
final String mapId = mindmapUri.getPath().replace("/service/maps/", "");
// Assign label to map ...
String labelId = labelUri.getPath().replace("/service/labels/", "");
HttpEntity<String> labelEntity = new HttpEntity<>(labelId, requestHeaders);
template.postForLocation(BASE_REST_URL + "/maps/" + mapId + "/labels", labelEntity);
// Remove label from map
template.delete(BASE_REST_URL + "/maps/" + mapId + "/labels/" + labelId);
Optional<RestMindmapInfo> mindmapInfo = fetchMap(requestHeaders, template, mapId);
assertTrue(mindmapInfo.get().getLabels().size() == 0);
}
@NotNull
private Optional<RestMindmapInfo> fetchMap(HttpHeaders requestHeaders, RestTemplate template, @NotNull String mapId) {
// Check that the label has been removed ...
final List<RestMindmapInfo> mindmapsInfo = fetchMaps(requestHeaders, template).getMindmapsInfo();
Optional<RestMindmapInfo> mindmapInfo = mindmapsInfo
.stream()
.filter(m -> m.getId() == Integer.parseInt(mapId))
.findAny();
return mindmapInfo;
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
@ -410,18 +549,266 @@ public class RestMindmapITCase {
template.postForLocation(BASE_REST_URL + "/maps/" + mapId + "/labels", labelEntity);
// Check that the label has been assigned ...
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
final ResponseEntity<RestMindmapList> mindmapList = template.exchange(BASE_REST_URL + "/maps/", HttpMethod.GET, findMapEntity, RestMindmapList.class);
final List<RestMindmapInfo> mindmapsInfo = mindmapList.getBody().getMindmapsInfo();
Optional<RestMindmapInfo> mindmapInfo = mindmapsInfo
.stream()
.filter(m -> m.getId() == Integer.parseInt(mapId))
.findAny();
Optional<RestMindmapInfo> mindmapInfo = fetchMap(requestHeaders, template, mapId);
assertTrue(mindmapInfo.get().getLabels().size() == 1);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void updateCollabs(final @NotNull MediaType mediaType) {
// Create a sample map ...
final RestTemplate template = createTemplate(userEmail);
final URI resourceUri = addNewMap(template, "Map for updateCollabs - " + mediaType);
final HttpHeaders requestHeaders = createHeaders(mediaType);
// Add a new collaboration ...
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
RestCollaborationList collabs = new RestCollaborationList();
collabs.setMessage("Adding new permission");
String newCollab = "new-collab@example.com";
String role = "editor";
addCollabToList(newCollab, role, collabs);
HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
collabs = fetchAndGetCollabs(requestHeaders, template, resourceUri);
//delete one collab
collabs.setCollaborations(collabs.getCollaborations().stream().filter(c -> c.getRole().equals("owner")).collect(Collectors.toList()));
//Add another collaborationMediaType
newCollab = "another-collab@example.com";
addCollabToList(newCollab, role, collabs);
//add owner to list
addCollabToList(userEmail.replace(":admin", ""), "owner", collabs);
updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.postForLocation(HOST_PORT + resourceUri + "/collabs/", updateEntity);
RestCollaborationList responseCollbs = fetchAndGetCollabs(requestHeaders, template, resourceUri);
// Has been another-collaboration list updated ?
assertTrue(responseCollbs.getCollaborations().stream().anyMatch(x -> x.getEmail().equals("another-collab@example.com")));
assertEquals(responseCollbs.getCount(), 2);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void updateProperties(final @NotNull MediaType mediaType) throws IOException, WiseMappingException { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final String title = "updateProperties map";
final URI resourceUri = addNewMap(template, title);
// Build map to update ...
final RestMindmap mapToUpdate = new RestMindmap();
mapToUpdate.setXml("<map>this is not valid</map>");
mapToUpdate.setProperties("{zoom:x}");
mapToUpdate.setTitle("new title for map");
mapToUpdate.setDescription("updated map description");
// Update map ...
final String resourceUrl = HOST_PORT + resourceUri.toString();
final HttpEntity<RestMindmap> updateEntity = new HttpEntity<>(mapToUpdate, requestHeaders);
template.put(resourceUrl, updateEntity);
// Check that the map has been updated ...
HttpEntity<RestUser> findMapEntity = new HttpEntity<>(requestHeaders);
final ResponseEntity<RestMindmap> response = template.exchange(HOST_PORT + resourceUri, HttpMethod.GET, findMapEntity, RestMindmap.class);
assertEquals(response.getBody().getTitle(), mapToUpdate.getTitle());
assertEquals(response.getBody().getDescription(), mapToUpdate.getDescription());
assertEquals(response.getBody().getXml(), mapToUpdate.getXml());
assertEquals(response.getBody().getProperties(), mapToUpdate.getProperties());
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void batchDelete(final @NotNull MediaType mediaType) { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final String title1 = "Batch delete map 1";
addNewMap(template, title1);
final String title2 = "Batch delete map 2";
addNewMap(template, title2);
String maps;
maps = fetchMaps(requestHeaders, template).getMindmapsInfo().stream().map(map -> {
return String.valueOf(map.getId());
}).collect(Collectors.joining(","));
template.delete(BASE_REST_URL + "/maps/batch?ids=" + maps);
// Validate that the two maps are there ...
final RestMindmapList body = fetchMaps(requestHeaders, template);
assertEquals(body.getMindmapsInfo().size(), 0);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void updatePublishState(final @NotNull MediaType mediaType) throws IOException, WiseMappingException { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final String mapTitle = "updatePublishState";
final URI mindmapUri = addNewMap(template, mapTitle);
final String mapId = mindmapUri.getPath().replace("/service/maps/", "");
// Change map status ...
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
//final String newPublicState = "true";
final HttpEntity<String> updateEntity = new HttpEntity<>(Boolean.TRUE.toString(), requestHeaders);
template.put(HOST_PORT + mindmapUri + "/publish", updateEntity);
//fetch public view
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
ResponseEntity<String> publicView = template.exchange(HOST_PORT + "/c/" + mapId + "/public", HttpMethod.GET, findMapEntity, String.class);
assertNotNull(publicView.getBody());
assertEquals(publicView.getStatusCodeValue(), 200);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void fetchMapHistory(final @NotNull MediaType mediaType) { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "Map to change title - " + mediaType);
updateMapDocument(requestHeaders, template, HOST_PORT + resourceUri.toString());
//fetch map history
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
final ResponseEntity<RestMindmapHistoryList> maps = template.exchange(HOST_PORT + resourceUri + "/history/", HttpMethod.GET, findMapEntity, RestMindmapHistoryList.class);
assertEquals(maps.getBody().getCount(), 1);
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void updateRevertMindmap(final @NotNull MediaType mediaType) throws IOException { // Configure media types ...
final HttpHeaders requestHeaders = createHeaders(mediaType);
final RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "map to test revert changes");
updateMapDocument(requestHeaders, template, HOST_PORT + resourceUri.toString(), "<map><node text='this is an xml to test revert changes service'></map>");
updateMapDocument(requestHeaders, template, HOST_PORT + resourceUri.toString(), "<map><node text='this is an xml with modification to be reverted'></map>");
//fetch map history
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
final ResponseEntity<RestMindmapHistoryList> mapHistories = template.exchange(HOST_PORT + resourceUri + "/history/", HttpMethod.GET, findMapEntity, RestMindmapHistoryList.class);
//aply revert
final HttpEntity<String> cloneEntity = new HttpEntity<>(requestHeaders);
template.postForLocation(HOST_PORT + resourceUri + "/history/latest", cloneEntity);
final RestMindmap latestStoredMap = findMap(requestHeaders, template, resourceUri);
template.postForLocation(HOST_PORT + resourceUri + "/history/" + mapHistories.getBody().getChanges().get(1).getId(), cloneEntity);
final RestMindmap firstVersionMap = findMap(requestHeaders, template, resourceUri);
//verify revert
assertEquals(firstVersionMap.getXml(), "<map><node text='this is an xml to test revert changes service'></map>");
assertEquals(latestStoredMap.getXml(), "<map><node text='this is an xml with modification to be reverted'></map>");
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void addCollabWhitoutOwnerPermission(final @NotNull MediaType mediaType) {
final HttpHeaders requestHeaders = createHeaders(mediaType);
RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "MaddCollabWhitoutOwnerPermission");
// Add a new collaboration ...
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
final RestCollaborationList collabs = new RestCollaborationList();
collabs.setMessage("Adding new permission");
final String newCollab = restAdminITCase.createNewUser(MediaType.APPLICATION_JSON);
String role = "editor";
addCollabToList(newCollab, role, collabs);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
template = createTemplate(newCollab + ":admin");
//add collab again with the new user expecting the Exception
try {
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
} catch (HttpClientErrorException e) {
assertEquals(e.getRawStatusCode(), 400);
assertTrue(e.getMessage().contains("User must be owner to share mindmap"));
}
}
@Test(dataProviderClass = RestHelper.class, dataProvider = "ContentType-Provider-Function")
public void addCollabWhitOwnerRole(final @NotNull MediaType mediaType) {
final HttpHeaders requestHeaders = createHeaders(mediaType);
RestTemplate template = createTemplate(userEmail);
// Create a sample map ...
final URI resourceUri = addNewMap(template, "addCollabWhitOwnerRole");
// Add a new collaboration ...
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
final RestCollaborationList collabs = new RestCollaborationList();
collabs.setMessage("Adding new permission");
final String newCollab = "new-collaborator@mail.com";
String role = "owner";
addCollabToList(newCollab, role, collabs);
final HttpEntity<RestCollaborationList> updateEntity = new HttpEntity<>(collabs, requestHeaders);
try {
template.put(HOST_PORT + resourceUri + "/collabs/", updateEntity);
} catch (HttpClientErrorException e) {
assertEquals(e.getRawStatusCode(), 400);
assertTrue(e.getMessage().contains("Collab email can not be change"));
}
}
private String changeMapTitle(final HttpHeaders requestHeaders, final MediaType mediaType, final RestTemplate template, final URI resourceUri) throws RestClientException {
// Change map title ...
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
final String newTitle = "New map to change title - " + mediaType;
final HttpEntity<String> updateEntity = new HttpEntity<>(newTitle, requestHeaders);
template.put(HOST_PORT + resourceUri + "/title", updateEntity);
return newTitle;
}
private RestMindmapList fetchMaps(final HttpHeaders requestHeaders, final RestTemplate template) throws RestClientException {
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
final ResponseEntity<RestMindmapList> maps = template.exchange(BASE_REST_URL + "/maps/", HttpMethod.GET, findMapEntity, RestMindmapList.class);
return maps.getBody();
}
private RestCollaborationList fetchAndGetCollabs(final HttpHeaders requestHeaders, final RestTemplate template, final URI resourceUri) {
final ResponseEntity<RestCollaborationList> response = fetchCollabs(requestHeaders, template, resourceUri);
RestCollaborationList responseCollbs = response.getBody();
return responseCollbs;
}
private RestCollaboration addCollabToList(String newCollab, String role, RestCollaborationList collabs) {
RestCollaboration collab = new RestCollaboration();
collab.setEmail(newCollab);
collab.setRole(role);
collabs.addCollaboration(collab);
return collab;
}
private RestMindmap findMap(HttpHeaders requestHeaders, RestTemplate template, URI resourceUri) {
final HttpEntity findMapEntity = new HttpEntity(requestHeaders);
final ResponseEntity<RestMindmap> response = template.exchange(HOST_PORT + resourceUri.toString(), HttpMethod.GET, findMapEntity, RestMindmap.class);