Compare commits

...

9 Commits

Author SHA1 Message Date
Paulo Gustavo Veiga 96b6ff3841 Fix typo on path. 2024-02-04 21:10:48 -08:00
Paulo Gustavo Veiga 34a5328a2c Complete JWT token support. 2024-02-04 20:53:24 -08:00
Paulo Gustavo Veiga 082f2614e3 Move to in memory 2024-02-04 19:45:14 -08:00
Paulo Gustavo Veiga 069943cf30 Add first version of token generation. 2024-02-04 18:28:23 -08:00
Paulo Gustavo Veiga 6674c607f7 Add registration test. 2024-02-04 17:31:21 -08:00
Paulo Gustavo Veiga a681cf9b90 Add user test. 2024-02-04 17:21:51 -08:00
Paulo Gustavo Veiga 9382fc2995 Clean up code. 2024-02-04 10:47:10 -08:00
Paulo Gustavo Veiga af4016cadd Improve code on rest. 2024-02-04 10:42:16 -08:00
Paulo Gustavo Veiga fdffda6186 Improve code. 2024-02-04 10:09:10 -08:00
27 changed files with 681 additions and 585 deletions

View File

@ -5,7 +5,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<relativePath/>
</parent>
<groupId>org.wisemapping</groupId>
@ -85,12 +84,6 @@
<version>12.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>10.1.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
@ -149,6 +142,7 @@
<version>2.7.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@ -161,13 +155,6 @@
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
@ -183,10 +170,18 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<version>1.18.26</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>6.2.1</version>
<scope>test</scope>
</dependency>
<!-- JWT dependencies -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
@ -197,7 +192,6 @@
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
@ -233,4 +227,14 @@
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>https://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>

View File

@ -1,8 +1,10 @@
package com.wisemapping.config.rest;
import com.wisemapping.filter.JwtAuthenticationFilter;
import com.wisemapping.rest.MindmapController;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
@ -11,6 +13,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
@ -21,6 +24,10 @@ import static org.springframework.security.config.Customizer.withDefaults;
@Import({InterceptorsConfig.class})
@EnableWebSecurity
public class RestAppConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
return new MvcRequestMatcher.Builder(introspector);
@ -30,12 +37,14 @@ public class RestAppConfig {
SecurityFilterChain apiSecurityFilterChain(@NotNull final HttpSecurity http, @NotNull final MvcRequestMatcher.Builder mvc) throws Exception {
return http
.securityMatcher("/**")
.addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers(mvc.pattern("/api/restfull/users/")).permitAll()
.requestMatchers(mvc.pattern("/api/restfull/users/resetPassword")).permitAll()
.requestMatchers(mvc.pattern("/api/restfull/oauth2/googlecallback")).permitAll()
.requestMatchers(mvc.pattern("/api/restfull/oauth2/confirmaccountsync")).permitAll()
.requestMatchers(mvc.pattern("/api/restfull/admin/**")).hasAnyRole("ADMIN")
.requestMatchers(mvc.pattern("/api/restful/users/")).permitAll()
.requestMatchers(mvc.pattern("/api/restful/authenticate")).permitAll()
.requestMatchers(mvc.pattern("/api/restful/users/resetPassword")).permitAll()
.requestMatchers(mvc.pattern("/api/restful/oauth2/googlecallback")).permitAll()
.requestMatchers(mvc.pattern("/api/restful/oauth2/confirmaccountsync")).permitAll()
.requestMatchers(mvc.pattern("/api/restful/admin/**")).hasAnyRole("ADMIN")
.requestMatchers(mvc.pattern("/**")).hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)

View File

@ -0,0 +1,84 @@
package com.wisemapping.filter;
import com.wisemapping.security.JwtTokenUtil;
import com.wisemapping.security.UserDetails;
import com.wisemapping.security.UserDetailsService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.Optional;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final String BEARER_TOKEN_PREFIX = "Bearer ";
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
final private static Logger logger = LogManager.getLogger();
@Override
protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain)
throws ServletException, IOException {
final Optional<String> token = getJwtTokenFromRequest(request);
if (token.isPresent() && SecurityContextHolder.getContext().getAuthentication() == null) {
// Extract email from token ...
final Optional<String> email = extractEmailFromToken(token.get());
if (email.isPresent() && jwtTokenUtil.validateJwtToken(token.get())) {
// Is it an existing user ?
final UserDetails userDetails = userDetailsService.loadUserByUsername(email.get());
if (userDetails != null) {
final UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
} else {
logger.trace("User " + email.get() + " could not be found");
}
}
}
filterChain.doFilter(request, response);
}
private Optional<String> extractEmailFromToken(final @NotNull String token) {
Optional<String> result = Optional.empty();
try {
result = Optional.of(jwtTokenUtil.extractFromJwtToken(token));
} catch (Exception e) {
// Handle token extraction/validation errors
logger.debug("Error extracting email from token: " + e.getMessage());
}
return result;
}
private static Optional<String> getJwtTokenFromRequest(@NotNull HttpServletRequest request) {
Optional<String> result = Optional.empty();
final String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader != null) {
if (authorizationHeader.startsWith(BEARER_TOKEN_PREFIX)) {
logger.trace("JWT Bearer token found");
final String token = authorizationHeader.substring(BEARER_TOKEN_PREFIX.length());
result = Optional.of(token);
}
}
return result;
}
}

View File

@ -39,6 +39,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/restful/account/")
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
public class AccountController extends BaseController {
@Qualifier("userService")
@ -53,7 +54,7 @@ public class AccountController extends BaseController {
@Autowired
private LabelService labelService;
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/account/password", consumes = {"text/plain"})
@RequestMapping(method = RequestMethod.PUT, value = "password", consumes = {"text/plain"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void changePassword(@RequestBody String password) throws PasswordTooLongException {
if (password == null) {
@ -69,13 +70,13 @@ public class AccountController extends BaseController {
userService.changePassword(user);
}
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/account", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "", produces = {"application/json"})
public RestUser fetchAccount() {
final User user = Utils.getUser(true);
return new RestUser(user);
}
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/account/firstname", consumes = {"text/plain"})
@RequestMapping(method = RequestMethod.PUT, value = "firstname", consumes = {"text/plain"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void changeFirstname(@RequestBody String firstname) {
if (firstname == null) {
@ -87,7 +88,7 @@ public class AccountController extends BaseController {
userService.updateUser(user);
}
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/account/lastname", consumes = {"text/plain"})
@RequestMapping(method = RequestMethod.PUT, value = "lastname", consumes = {"text/plain"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void changeLastName(@RequestBody String lastname) {
if (lastname == null) {
@ -99,7 +100,7 @@ public class AccountController extends BaseController {
userService.updateUser(user);
}
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/account/locale", consumes = {"text/plain"})
@RequestMapping(method = RequestMethod.PUT, value = "locale", consumes = {"text/plain"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void changeLanguage(@RequestBody String language) {
if (language == null) {
@ -113,7 +114,7 @@ public class AccountController extends BaseController {
}
@ResponseStatus(value = HttpStatus.NO_CONTENT)
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/account")
@RequestMapping(method = RequestMethod.DELETE, value = "")
public void deleteUser() throws WiseMappingException {
// Delete collaborations ...
final User user = Utils.getUser(true);

View File

@ -33,10 +33,10 @@ import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping("/api/restful/admin")
@PreAuthorize("isAuthenticated() and hasRole('ROLE_ADMIN')")
public class AdminController extends BaseController {
@Qualifier("userService")
@ -47,9 +47,9 @@ public class AdminController extends BaseController {
@Autowired
private MindmapService mindmapService;
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/admin/users/{id}", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/users/{id}", produces = {"application/json"})
@ResponseBody
public RestUser getUserById(@PathVariable int id) throws IOException {
public RestUser getUserById(@PathVariable int id) {
final User userBy = userService.getUserBy(id);
if (userBy == null) {
throw new IllegalArgumentException("User could not be found");
@ -57,9 +57,9 @@ public class AdminController extends BaseController {
return new RestUser(userBy);
}
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/admin/users/email/{email:.+}", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/users/email/{email:.+}", produces = {"application/json"})
@ResponseBody
public RestUser getUserByEmail(@PathVariable String email) throws IOException {
public RestUser getUserByEmail(@PathVariable String email) {
final User user = userService.getUserBy(email);
if (user == null) {
throw new IllegalArgumentException("User '" + email + "' could not be found");
@ -67,9 +67,9 @@ public class AdminController extends BaseController {
return new RestUser(user);
}
@RequestMapping(method = RequestMethod.POST, value = "/api/restfull/admin/users", consumes = {"application/json"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.POST, value = "/users", consumes = {"application/json"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.CREATED)
public void createUser(@RequestBody RestUser user, HttpServletResponse response) throws WiseMappingException {
public void createUser(@RequestBody RestUser user, final HttpServletResponse response) throws WiseMappingException {
if (user == null) {
throw new IllegalArgumentException("User could not be found");
}
@ -101,12 +101,12 @@ public class AdminController extends BaseController {
// Finally create the user ...
delegated.setAuthenticationType(AuthenticationType.DATABASE);
userService.createUser(delegated, false, true);
response.setHeader("Location", "/api/restfull/admin/users/" + user.getId());
response.setHeader("Location", "/api/restful/admin/users/" + user.getId());
}
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/admin/users/{id}/password", consumes = {"text/plain"})
@RequestMapping(method = RequestMethod.PUT, value = "/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) {
if (password == null) {
throw new IllegalArgumentException("Password can not be null");
}
@ -119,7 +119,7 @@ public class AdminController extends BaseController {
userService.changePassword(user);
}
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/admin/users/{id}")
@RequestMapping(method = RequestMethod.DELETE, value = "/users/{id}")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void deleteUserByEmail(@PathVariable int id) throws WiseMappingException {
final User user = userService.getUserBy(id);
@ -132,7 +132,6 @@ public class AdminController extends BaseController {
final Mindmap mindmap = collaboration.getMindMap();
mindmapService.removeMindmap(mindmap, user);
}
userService.removeUser(user);
}
}

View File

@ -0,0 +1,81 @@
/*
* 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;
import com.wisemapping.rest.model.RestJwtUser;
import com.wisemapping.security.JwtTokenUtil;
import com.wisemapping.security.UserDetailsService;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin
@RequestMapping("/api/restful")
public class JwtAuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody RestJwtUser user, @NotNull HttpServletResponse response) throws Exception {
// Is a valid user ?
authenticate(user.getEmail(), user.getPassword());
// Create token ...
final UserDetails userDetails = userDetailsService
.loadUserByUsername(user.getEmail());
final String token = jwtTokenUtil.generateJwtToken(userDetails);
// Add token in the header ...
response.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
return ResponseEntity.ok(token);
}
private void authenticate(@NotNull String username, @NotNull String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
}

View File

@ -27,20 +27,20 @@ import com.wisemapping.rest.model.RestLabelList;
import com.wisemapping.security.Utils;
import com.wisemapping.service.LabelService;
import com.wisemapping.validator.LabelValidator;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/restful/labels")
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
public class LabelController extends BaseController {
@ -49,7 +49,7 @@ public class LabelController extends BaseController {
private LabelService labelService;
@RequestMapping(method = RequestMethod.POST, value = "/api/restfull/labels", consumes = {"application/json"})
@RequestMapping(method = RequestMethod.POST, value = "", consumes = {"application/json"})
@ResponseStatus(value = HttpStatus.CREATED)
public void createLabel(@RequestBody RestLabel restLabel, @NotNull HttpServletResponse response, @RequestParam(required = false) String title) throws WiseMappingException {
// Overwrite title if it was specified by parameter.
@ -63,11 +63,11 @@ public class LabelController extends BaseController {
final Label label = createLabel(restLabel);
// Return the new created label ...
response.setHeader("Location", "/api/restfull/labels/" + label.getId());
response.setHeader("Location", "/api/restful/labels/" + label.getId());
response.setHeader("ResourceId", Long.toString(label.getId()));
}
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/labels/", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/", produces = {"application/json"})
public RestLabelList retrieveList() {
final User user = Utils.getUser();
assert user != null;
@ -75,7 +75,7 @@ public class LabelController extends BaseController {
return new RestLabelList(all);
}
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/labels/{id}")
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void deleteLabelById(@PathVariable int id) throws WiseMappingException {
final User user = Utils.getUser();

View File

@ -35,8 +35,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@ -48,7 +46,7 @@ import java.util.stream.Collectors;
@RestController
@Transactional(propagation = Propagation.REQUIRED)
@RequestMapping("/api/restful/maps")
public class MindmapController extends BaseController {
private final Logger logger = LogManager.getLogger();
@ -71,7 +69,7 @@ public class MindmapController extends BaseController {
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/maps/{id}", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/{id}", produces = {"application/json"})
@ResponseBody
public RestMindmap retrieve(@PathVariable int id) throws WiseMappingException {
final User user = Utils.getUser();
@ -80,7 +78,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/maps/", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/", produces = {"application/json"})
public RestMindmapList retrieveList(@RequestParam(required = false) String q) {
final User user = Utils.getUser();
@ -94,7 +92,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/maps/{id}/history/", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/{id}/history/", produces = {"application/json"})
public RestMindmapHistoryList fetchHistory(@PathVariable int id) {
final List<MindMapHistory> histories = mindmapService.findMindmapHistory(id);
final RestMindmapHistoryList result = new RestMindmapHistoryList();
@ -104,7 +102,7 @@ public class MindmapController extends BaseController {
return result;
}
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/document", consumes = {"application/json"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{id}/document", consumes = {"application/json"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@ -136,7 +134,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(value = "/api/restfull/maps/{id}/history/{hid}", method = RequestMethod.POST)
@RequestMapping(value = "/{id}/history/{hid}", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateRevertMindmap(@PathVariable int id, @PathVariable String hid) throws WiseMappingException, IOException {
final Mindmap mindmap = findMindmapById(id);
@ -156,7 +154,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("permitAll()")
@RequestMapping(method = RequestMethod.GET, value = {"/api/restfull/maps/{id}/document/xml", "/api/restfull/maps/{id}/document/xml-pub"}, consumes = {"text/plain"}, produces = {"application/xml; charset=UTF-8"})
@RequestMapping(method = RequestMethod.GET, value = {"/{id}/document/xml", "/{id}/document/xml-pub"}, consumes = {"text/plain"}, produces = {"application/xml; charset=UTF-8"})
@ResponseBody
public byte[] retrieveDocument(@PathVariable int id, @NotNull HttpServletResponse response) throws WiseMappingException, IOException {
final Mindmap mindmap = findMindmapById(id);
@ -166,9 +164,9 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = {"/api/restfull/maps/{id}/document/xml"}, consumes = {"text/plain"})
@RequestMapping(method = RequestMethod.PUT, value = {"/{id}/document/xml"}, consumes = {"text/plain"})
@ResponseBody
public void updateDocument(@PathVariable int id, @RequestBody String xmlDoc) throws WiseMappingException, IOException {
public void updateDocument(@PathVariable int id, @RequestBody String xmlDoc) throws WiseMappingException {
final Mindmap mindmap = findMindmapById(id);
final User user = Utils.getUser();
mindmap.setXmlStr(xmlDoc);
@ -178,7 +176,7 @@ public class MindmapController extends BaseController {
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.GET, value = {"/api/restfull/maps/{id}/{hid}/document/xml"}, consumes = {"text/plain"}, produces = {"application/xml; charset=UTF-8"})
@RequestMapping(method = RequestMethod.GET, value = {"/{id}/{hid}/document/xml"}, consumes = {"text/plain"}, produces = {"application/xml; charset=UTF-8"})
@ResponseBody
public byte[] retrieveDocument(@PathVariable int id, @PathVariable int hid, @NotNull HttpServletResponse response) throws WiseMappingException, IOException {
final MindMapHistory mindmapHistory = mindmapService.findMindmapHistory(id, hid);
@ -190,7 +188,7 @@ public class MindmapController extends BaseController {
* The intention of this method is the update of several properties at once ...
*/
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}", consumes = {"application/json"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{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 {
@ -245,7 +243,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/title", consumes = {"text/plain"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{id}/title", consumes = {"text/plain"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateTitle(@RequestBody String title, @PathVariable int id) throws WiseMappingException {
@ -264,7 +262,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.POST, value = "/api/restfull/maps/{id}/collabs/", consumes = {"application/json"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.POST, value = "/{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, TooManyInactiveAccountsExceptions {
final Mindmap mindMap = findMindmapById(id);
@ -314,7 +312,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/collabs/", consumes = {"application/json"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{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, TooManyInactiveAccountsExceptions, OwnerCannotChangeException {
final Mindmap mindMap = findMindmapById(id);
@ -382,7 +380,7 @@ public class MindmapController extends BaseController {
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/maps/{id}/collabs", produces = {"application/json"})
@RequestMapping(method = RequestMethod.GET, value = "/{id}/collabs", produces = {"application/json"})
public RestCollaborationList retrieveList(@PathVariable int id) throws MapCouldNotFoundException, AccessDeniedSecurityException {
final Mindmap mindMap = findMindmapById(id);
@ -399,7 +397,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/description", consumes = {"text/plain"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{id}/description", consumes = {"text/plain"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateDescription(@RequestBody String description, @PathVariable int id) throws WiseMappingException {
final Mindmap mindmap = findMindmapById(id);
@ -408,7 +406,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/publish", consumes = {"text/plain"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{id}/publish", consumes = {"text/plain"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updatePublishState(@RequestBody String value, @PathVariable int id) throws WiseMappingException {
@ -426,18 +424,18 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/maps/{id}")
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void deleteMapById(@PathVariable int id) throws IOException, WiseMappingException {
public void deleteMapById(@PathVariable int id) throws WiseMappingException {
final User user = Utils.getUser();
final Mindmap mindmap = findMindmapById(id);
mindmapService.removeMindmap(mindmap, user);
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/maps/{id}/collabs")
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}/collabs")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void deleteCollabByEmail(@PathVariable int id, @RequestParam(required = false) String email) throws IOException, WiseMappingException {
public void deleteCollabByEmail(@PathVariable int id, @RequestParam(required = false) String email) throws WiseMappingException {
logger.debug("Deleting permission for email:" + email);
// Is a valid email address ?
@ -467,7 +465,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/starred", consumes = {"text/plain"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{id}/starred", consumes = {"text/plain"}, produces = {"application/json"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateStarredState(@RequestBody String value, @PathVariable int id) throws WiseMappingException {
@ -486,7 +484,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.GET, value = "/api/restfull/maps/{id}/starred", produces = {"text/plain"})
@RequestMapping(method = RequestMethod.GET, value = "/{id}/starred", produces = {"text/plain"})
@ResponseBody
public String fetchStarred(@PathVariable int id) throws WiseMappingException {
final Mindmap mindmap = findMindmapById(id);
@ -501,9 +499,9 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/maps/batch")
@RequestMapping(method = RequestMethod.DELETE, value = "/batch")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void batchDelete(@RequestParam() String ids) throws IOException, WiseMappingException {
public void batchDelete(@RequestParam() String ids) throws WiseMappingException {
final User user = Utils.getUser();
final String[] mapsIds = ids.split(",");
try {
@ -519,9 +517,9 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.POST, value = "/api/restfull/maps", consumes = {"application/xml", "application/json"})
@RequestMapping(method = RequestMethod.POST, value = "", consumes = {"application/xml", "application/json"})
@ResponseStatus(value = HttpStatus.CREATED)
public void createMap(@RequestBody(required = false) String mapXml, @NotNull HttpServletResponse response, @RequestParam(required = false) String title, @RequestParam(required = false) String description) throws IOException, WiseMappingException {
public void createMap(@RequestBody(required = false) String mapXml, @NotNull HttpServletResponse response, @RequestParam(required = false) String title, @RequestParam(required = false) String description) throws WiseMappingException {
final Mindmap mindmap = new Mindmap();
if (title != null && !title.isEmpty()) {
@ -550,14 +548,14 @@ public class MindmapController extends BaseController {
mindmapService.addMindmap(mindmap, user);
// Return the new created map ...
response.setHeader("Location", "/api/restfull/maps/" + mindmap.getId());
response.setHeader("Location", "/api/restful/maps/" + mindmap.getId());
response.setHeader("ResourceId", Integer.toString(mindmap.getId()));
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.POST, value = "/api/restfull/maps/{id}", consumes = {"application/json"}, produces = {"application/json", "text/plain"})
@RequestMapping(method = RequestMethod.POST, value = "/{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 {
public void createDuplicate(@RequestBody RestMindmapInfo restMindmap, @PathVariable int id, @NotNull HttpServletResponse response) throws WiseMappingException {
// Validate ...
final BindingResult result = new BeanPropertyBindingResult(restMindmap, "");
new MapInfoValidator(mindmapService).validate(restMindmap.getDelegated(), result);
@ -578,13 +576,13 @@ public class MindmapController extends BaseController {
mindmapService.addMindmap(clonedMap, user);
// Return the new created map ...
response.setHeader("Location", "/api/restfull/maps/" + clonedMap.getId());
response.setHeader("Location", "/api/restful/maps/" + clonedMap.getId());
response.setHeader("ResourceId", Integer.toString(clonedMap.getId()));
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.DELETE, value = "/api/restfull/maps/{id}/labels/{lid}")
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}/labels/{lid}")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void removeLabelFromMap(@PathVariable int id, @PathVariable int lid) throws WiseMappingException {
final User user = Utils.getUser();
@ -600,7 +598,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.POST, value = "/api/restfull/maps/{id}/labels", consumes = {"application/json"})
@RequestMapping(method = RequestMethod.POST, value = "/{id}/labels", consumes = {"application/json"})
@ResponseStatus(value = HttpStatus.OK)
public void updateLabel(@PathVariable int id, @RequestBody int lid) throws WiseMappingException {
final User user = Utils.getUser();
@ -615,7 +613,7 @@ public class MindmapController extends BaseController {
}
@PreAuthorize("isAuthenticated() and hasRole('ROLE_USER')")
@RequestMapping(method = RequestMethod.PUT, value = "/api/restfull/maps/{id}/lock", consumes = {"text/plain"}, produces = {"application/json"})
@RequestMapping(method = RequestMethod.PUT, value = "/{id}/lock", consumes = {"text/plain"}, produces = {"application/json"})
public ResponseEntity<RestLockInfo> lockMindmap(@RequestBody String value, @PathVariable int id) throws WiseMappingException {
final User user = Utils.getUser();
final LockManager lockManager = mindmapService.getLockManager();

View File

@ -48,6 +48,7 @@ import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/api/restful/users")
@CrossOrigin
public class UserController extends BaseController {
@ -71,7 +72,7 @@ public class UserController extends BaseController {
private static final Logger logger = LogManager.getLogger();
private static final String REAL_IP_ADDRESS_HEADER = "X-Real-IP";
@RequestMapping(method = RequestMethod.POST, value = "/users/", produces = { "application/json" })
@RequestMapping(method = RequestMethod.POST, value = "/", produces = { "application/json" })
@ResponseStatus(value = HttpStatus.CREATED)
public void registerUser(@RequestBody RestUserRegistration registration, @NotNull HttpServletRequest request,
@NotNull HttpServletResponse response) throws WiseMappingException, BindException {
@ -98,10 +99,10 @@ public class UserController extends BaseController {
user.setAuthenticationType(AuthenticationType.DATABASE);
userService.createUser(user, false, true);
response.setHeader("Location", "/service/users/" + user.getId());
response.setHeader("Location", "/api/restful/users/" + user.getId());
}
@RequestMapping(method = RequestMethod.PUT, value = "/users/resetPassword", produces = { "application/json" })
@RequestMapping(method = RequestMethod.PUT, value = "/resetPassword", produces = { "application/json" })
@ResponseStatus(value = HttpStatus.OK)
public RestResetPasswordResponse resetPassword(@RequestParam String email) throws InvalidAuthSchemaException, EmailNotExistsException {
try {

View File

@ -0,0 +1,59 @@
/*
* 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.model;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.jetbrains.annotations.NotNull;
@JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
isGetterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RestJwtUser {
private String email;
private String password;
public RestJwtUser(@NotNull String email, @NotNull String password) {
this.setEmail(email);
this.setPassword(password);
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@ -1,3 +1,21 @@
/*
* 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.model;
import com.fasterxml.jackson.annotation.JsonAutoDetect;

View File

@ -24,6 +24,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.wisemapping.model.User;
import java.awt.*;
@JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
@ -47,6 +49,15 @@ public class RestUserRegistration {
return user;
}
public static RestUserRegistration create(String email, String password, String firstname, String lastname) {
final RestUserRegistration result = new RestUserRegistration();
result.email = email;
result.password = password;
result.firstname = firstname;
result.lastname = lastname;
return result;
}
public String getEmail() {
return email;
}

View File

@ -0,0 +1,61 @@
package com.wisemapping.security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.security.Key;
import java.util.Date;
@Component
public class JwtTokenUtil implements Serializable {
final private Logger logger = LogManager.getLogger();
@Value("${app.jwt.secret}")
private String jwtSecret;
@Value("${app.jwt.expirationMin}")
private int jwtExpirationMin;
public String generateJwtToken(@NotNull final UserDetails user) {
return Jwts.builder()
.setSubject((user.getUsername()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMin * 1000L * 60))
.signWith(key(), SignatureAlgorithm.HS256)
.compact();
}
private Key key() {
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret));
}
public String extractFromJwtToken(String token) {
return Jwts.parserBuilder().setSigningKey(key()).build()
.parseClaimsJws(token).getBody().getSubject();
}
public boolean validateJwtToken(@NotNull String authToken) {
try {
Jwts.parserBuilder().setSigningKey(key()).build().parse(authToken);
return true;
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
}

View File

@ -36,7 +36,7 @@ public class UserDetailsService
@Autowired
private UserService userService;
@Value("${admin.user}")
@Value("${app.admin.user}")
private String adminUser;
@Override

View File

@ -34,7 +34,6 @@ final public class Utils {
return getUser(false);
}
@NotNull
public static User getUser(boolean forceCheck) {
User result = null;
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();

View File

@ -54,7 +54,7 @@ public class MindmapServiceImpl
@Autowired
private NotificationService notificationService;
@Value("${admin.user}")
@Value("${app.admin.user}")
private String adminUser;
final private LockManager lockManager;

View File

@ -8,9 +8,9 @@ spring:
name: wisemapping-api
title: wisemapping-api
datasource:
url: jdbc:hsqldb:mem:wisemapping
driver-class-name: org.hsqldb.jdbc.JDBCDriver
password: ''
url: jdbc:hsqldb:file:${database.base.url}/db/wisemapping
username: sa
jpa:
hibernate:
@ -29,13 +29,23 @@ spring:
mode: always
platform: hsqldb
# Login ...
logging:
level:
org:
apache:
tomcat: INFO
root: TRACE
# Application Configuration.
admin:
user: admin@wisemapping.org
database:
base:
url: /Users/veigap/
app:
jwt:
secret: dlqxKAg685SaKhsQXIMeM=JWCw3bkl3Ei3Tb7LMlnd19oMd66burPNlJ0Po1qguyjgpakQTk2CN3
expirationMin: 10080 # One week
admin:
user: admin@wisemapping.org
google:
ads:
enabled: false
@ -46,12 +56,6 @@ google:
enabled: true
secretKey: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
siteKey: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
logging:
level:
org:
apache:
tomcat: INFO
root: INFO
mail:
password: ''
serverSendEmail: root@localhost

View File

@ -1 +0,0 @@
../../../../../../wise-ui/target/wisemapping-mindplot/package/dist

View File

@ -1 +0,0 @@
../../../../../../wise-ui/target/wisemapping-webapp/package/dist

View File

@ -1,399 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.1.2</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Spring</short-name>
<uri>http://www.springframework.org/tags</uri>
<description>Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller</description>
<tag>
<name>htmlEscape</name>
<tag-class>org.springframework.web.servlet.tags.HtmlEscapeTag</tag-class>
<body-content>JSP</body-content>
<description>
Sets default HTML escape value for the current page.
Overrides a "defaultHtmlEscape" context-param in web.xml, if any.
</description>
<attribute>
<name>defaultHtmlEscape</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>Set the default value for HTML escaping, to be put
into the current PageContext.
</description>
</attribute>
</tag>
<tag>
<name>escapeBody</name>
<tag-class>org.springframework.web.servlet.tags.EscapeBodyTag</tag-class>
<body-content>JSP</body-content>
<description>
Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</description>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set HTML escaping for this tag, as boolean value. Overrides the
default HTML escaping setting for the current page.
</description>
</attribute>
<attribute>
<name>javaScriptEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set JavaScript escaping for this tag, as boolean value.
Default is false.
</description>
</attribute>
</tag>
<tag>
<name>message</name>
<tag-class>org.springframework.web.servlet.tags.MessageTag</tag-class>
<body-content>JSP</body-content>
<description>
Retrieves the message with the given code, or text if code isn't resolvable.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</description>
<attribute>
<name>message</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>A MessageSourceResolvable argument (direct or through JSP EL).
Fits nicely when used in conjunction with Spring's own validation error
classes which all implement the MessageSourceResolvable interface. For
example, this allows you to iterate over all of the errors in a form,
passing each error (using a runtime expression) as the value of this
'message' attribute, thus effecting the easy display of such error
messages.
</description>
</attribute>
<attribute>
<name>code</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The code (key) to use when looking up the message.
If code is not provided, the text attribute will be used.
</description>
</attribute>
<attribute>
<name>arguments</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set optional message arguments for this tag, as a
(comma-)delimited String (each String argument can contain JSP EL),
an Object array (used as argument array), or a single Object (used
as single argument).
</description>
</attribute>
<attribute>
<name>argumentSeparator</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The separator character to be used for splitting the
arguments string value; defaults to a 'comma' (',').
</description>
</attribute>
<attribute>
<name>text</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Default text to output when a message for the given code
could not be found. If both text and code are not set, the tag will
output null.
</description>
</attribute>
<attribute>
<name>var</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The string to use when binding the result to the page,
request, session or application scope. If not specified, the result
gets outputted to the writer (i.e. typically directly to the JSP).
</description>
</attribute>
<attribute>
<name>scope</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The scope to use when exporting the result to a variable.
This attribute is only used when var is also set. Possible values are
page, request, session and application.
</description>
</attribute>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set HTML escaping for this tag, as boolean value.
Overrides the default HTML escaping setting for the current page.
</description>
</attribute>
<attribute>
<name>javaScriptEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set JavaScript escaping for this tag, as boolean value. Default is false.</description>
</attribute>
</tag>
<tag>
<name>theme</name>
<tag-class>org.springframework.web.servlet.tags.ThemeTag</tag-class>
<body-content>JSP</body-content>
<description>
Retrieves the theme message with the given code, or text if code isn't resolvable.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</description>
<attribute>
<name>message</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>A MessageSourceResolvable argument (direct or through JSP EL).</description>
</attribute>
<attribute>
<name>code</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The code (key) to use when looking up the message.
If code is not provided, the text attribute will be used.
</description>
</attribute>
<attribute>
<name>arguments</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set optional message arguments for this tag, as a
(comma-)delimited String (each String argument can contain JSP EL),
an Object array (used as argument array), or a single Object (used
as single argument).
</description>
</attribute>
<attribute>
<name>argumentSeparator</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The separator character to be used for splitting the
arguments string value; defaults to a 'comma' (',').
</description>
</attribute>
<attribute>
<name>text</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Default text to output when a message for the given code
could not be found. If both text and code are not set, the tag will
output null.
</description>
</attribute>
<attribute>
<name>var</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The string to use when binding the result to the page,
request, session or application scope. If not specified, the result
gets outputted to the writer (i.e. typically directly to the JSP).
</description>
</attribute>
<attribute>
<name>scope</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The scope to use when exporting the result to a variable.
This attribute is only used when var is also set. Possible values are
page, request, session and application.
</description>
</attribute>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set HTML escaping for this tag, as boolean value.
Overrides the default HTML escaping setting for the current page.
</description>
</attribute>
<attribute>
<name>javaScriptEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set JavaScript escaping for this tag, as boolean value. Default is false.</description>
</attribute>
</tag>
<tag>
<name>hasBindErrors</name>
<tag-class>org.springframework.web.servlet.tags.BindErrorsTag</tag-class>
<body-content>JSP</body-content>
<description>
Provides Errors instance in case of bind errors.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</description>
<variable>
<name-given>errors</name-given>
<variable-class>org.springframework.validation.Errors</variable-class>
</variable>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>The name of the bean in the request, that needs to be
inspected for errors. If errors are available for this bean, they
will be bound under the 'errors' key.
</description>
</attribute>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set HTML escaping for this tag, as boolean value.
Overrides the default HTML escaping setting for the current page.
</description>
</attribute>
</tag>
<tag>
<name>nestedPath</name>
<tag-class>org.springframework.web.servlet.tags.NestedPathTag</tag-class>
<body-content>JSP</body-content>
<description>
Sets a nested path to be used by the bind tag's path.
</description>
<variable>
<name-given>nestedPath</name-given>
<variable-class>java.lang.String</variable-class>
</variable>
<attribute>
<name>path</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>Set the path that this tag should apply. E.g. 'customer'
to allow bind paths like 'address.street' rather than
'customer.address.street'.
</description>
</attribute>
</tag>
<tag>
<name>bind</name>
<tag-class>org.springframework.web.servlet.tags.BindTag</tag-class>
<body-content>JSP</body-content>
<description>
Provides BindStatus object for the given bind path.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</description>
<variable>
<name-given>status</name-given>
<variable-class>org.springframework.web.servlet.support.BindStatus</variable-class>
</variable>
<attribute>
<name>path</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>The path to the bean or bean property to bind status
information for. For instance account.name, company.address.zipCode
or just employee. The status object will exported to the page scope,
specifically for this bean or bean property
</description>
</attribute>
<attribute>
<name>ignoreNestedPath</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set whether to ignore a nested path, if any. Default is to not ignore.</description>
</attribute>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set HTML escaping for this tag, as boolean value. Overrides
the default HTML escaping setting for the current page.
</description>
</attribute>
</tag>
<tag>
<name>transform</name>
<tag-class>org.springframework.web.servlet.tags.TransformTag</tag-class>
<body-content>JSP</body-content>
<description>
Provides transformation of variables to Strings, using an appropriate
custom PropertyEditor from BindTag (can only be used inside BindTag).
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a 'defaultHtmlEscape' context-param in web.xml).
</description>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>The value to transform. This is the actual object you want
to have transformed (for instance a Date). Using the PropertyEditor that
is currently in use by the 'spring:bind' tag.
</description>
</attribute>
<attribute>
<name>var</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The string to use when binding the result to the page,
request, session or application scope. If not specified, the result gets
outputted to the writer (i.e. typically directly to the JSP).
</description>
</attribute>
<attribute>
<name>scope</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>The scope to use when exported the result to a variable.
This attribute is only used when var is also set. Possible values are
page, request, session and application.
</description>
</attribute>
<attribute>
<name>htmlEscape</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description>Set HTML escaping for this tag, as boolean value. Overrides
the default HTML escaping setting for the current page.
</description>
</attribute>
</tag>
</taglib>

View File

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringModelInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.wisemapping.rest"/>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorParameter" value="true"/>
<property name="parameterName" value="mediaType"/>
<property name="defaultContentType" value="application/json" />
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/>
<entry key="json" value="application/json"/>
</map>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
<property name="extractValueFromSingleKeyModel" value="true"/>
</bean>
</list>
</property>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="defaultEncoding" value="UTF-8"/>
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
</beans>

View File

@ -118,14 +118,4 @@ public class RestAccountControllerTest {
return templateRest.postForLocation(BASE_REST_URL + "/admin/users", createUserEntity);
}
private RestUser createDummyUser() {
final RestUser restUser = new RestUser();
final String username = "foo-to-delete" + System.nanoTime();
final String email = username + "@example.org";
restUser.setEmail(email);
restUser.setFirstname("foo first name");
restUser.setLastname("foo last name");
restUser.setPassword("fooPassword");
return restUser;
}
}

View File

@ -1,5 +1,6 @@
package com.wisemapping.test.rest;
import com.wisemapping.rest.model.RestUser;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
@ -11,7 +12,7 @@ import java.util.ArrayList;
import java.util.List;
public class RestHelper {
public static final String BASE_REST_URL = "/api/restfull";
public static final String BASE_REST_URL = "/api/restful";
static HttpHeaders createHeaders(@NotNull MediaType mediaType) {
List<MediaType> acceptableMediaTypes = new ArrayList<>();
@ -22,4 +23,15 @@ public class RestHelper {
result.setContentType(mediaType);
return result;
}
static RestUser createDummyUser() {
final RestUser restUser = new RestUser();
final String username = "foo-to-delete" + System.nanoTime();
final String email = username + "@example.org";
restUser.setEmail(email);
restUser.setFirstname("foo first name");
restUser.setLastname("foo last name");
restUser.setPassword("fooPassword");
return restUser;
}
}

View File

@ -0,0 +1,109 @@
/*
* 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.test.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wisemapping.config.common.CommonConfig;
import com.wisemapping.config.rest.RestAppConfig;
import com.wisemapping.model.User;
import com.wisemapping.rest.JwtAuthController;
import com.wisemapping.rest.model.RestJwtUser;
import com.wisemapping.rest.model.RestUser;
import com.wisemapping.rest.model.RestUserRegistration;
import com.wisemapping.security.JwtTokenUtil;
import com.wisemapping.service.UserService;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import static com.wisemapping.test.rest.RestHelper.createDummyUser;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, JwtAuthController.class})
@AutoConfigureMockMvc
public class RestJwtAuthControllerTest {
@Autowired
private ObjectMapper objectMapper;
@Autowired
JwtTokenUtil jwtTokenUtil;
@Autowired
private MockMvc mockMvc;
@Autowired
private UserService userService;
@Test
void generateTokenValidUser() throws Exception {
final RestJwtUser user = new RestJwtUser("test@wisemapping.org", "test");
final String userJson = objectMapper.writeValueAsString(user);
final MvcResult result = mockMvc.perform(
post("/api/restful/authenticate").
contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().isOk()).andReturn();
assertTrue(jwtTokenUtil.validateJwtToken(result.getResponse().getContentAsString()));
}
@Test
void generateTokenInvalidPassword() throws Exception {
final RestJwtUser user = new RestJwtUser("test@wisemapping.org", "test1");
final String userJson = objectMapper.writeValueAsString(user);
mockMvc.perform(
post("/api/restful/authenticate").
contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().is4xxClientError());
}
@Test
void generateTokenInvalidPasswordUser() throws Exception {
final RestJwtUser user = new RestJwtUser("test-not-exist@wisemapping.org", "test");
final String userJson = objectMapper.writeValueAsString(user);
mockMvc.perform(
post("/api/restful/authenticate").
contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().is4xxClientError());
}
}

View File

@ -134,7 +134,7 @@ public class RestLabelControllerTest {
// Create a new label ...
final HttpEntity<RestLabel> createUserEntity = new HttpEntity<>(restLabel, requestHeaders);
final ResponseEntity<String> result = template.exchange("/api/restfull/labels", HttpMethod.POST, createUserEntity, String.class);
final ResponseEntity<String> result = template.exchange("/api/restful/labels", HttpMethod.POST, createUserEntity, String.class);
if (!result.getStatusCode().is2xxSuccessful()) {
throw new IllegalStateException(result.toString());
}

View File

@ -128,7 +128,7 @@ public class RestMindmapControllerTest {
// Add map with same name ...
HttpEntity<RestMindmap> createUserEntity = new HttpEntity<>(requestHeaders);
final ResponseEntity<String> response = restTemplate.exchange("/api/restfull/maps?title=" + title, HttpMethod.POST, createUserEntity, String.class);
final ResponseEntity<String> response = restTemplate.exchange("/api/restful/maps?title=" + title, HttpMethod.POST, createUserEntity, String.class);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertTrue(Objects.requireNonNull(response.getBody()).contains("You have already a map with the same name"));
}
@ -254,7 +254,7 @@ public class RestMindmapControllerTest {
addNewMap(secondTemplate, title2);
final TestRestTemplate superadminTemplate = this.restTemplate.withBasicAuth("admin@wisemapping.org", "test");
final ResponseEntity<String> exchange = superadminTemplate.exchange("/api/restfull/admin/users/" + secondUser.getId(), HttpMethod.DELETE, null, String.class);
final ResponseEntity<String> exchange = superadminTemplate.exchange("/api/restful/admin/users/" + secondUser.getId(), HttpMethod.DELETE, null, String.class);
assertTrue(exchange.getStatusCode().is2xxSuccessful(), "Status Code:" + exchange.getStatusCode() + "- " + exchange.getBody());
// Validate that the two maps are there ...
@ -490,15 +490,15 @@ public class RestMindmapControllerTest {
// Create a sample map ...
final String mapTitle = "removeLabelFromMindmap";
final URI mindmapUri = addNewMap(restTemplate, mapTitle);
final String mapId = mindmapUri.getPath().replace("/api/restfull/maps/", "");
final String mapId = mindmapUri.getPath().replace("/api/restful/maps/", "");
// Assign label to map ...
String labelId = labelUri.getPath().replace("/api/restfull/labels/", "");
String labelId = labelUri.getPath().replace("/api/restful/labels/", "");
HttpEntity<String> labelEntity = new HttpEntity<>(labelId, requestHeaders);
restTemplate.postForLocation("/api/restfull/maps/" + mapId + "/labels", labelEntity);
restTemplate.postForLocation("/api/restful/maps/" + mapId + "/labels", labelEntity);
// Remove label from map
final ResponseEntity<String> exchange = restTemplate.exchange("/api/restfull//maps/" + mapId + "/labels/" + labelId, HttpMethod.DELETE, null, String.class);
final ResponseEntity<String> exchange = restTemplate.exchange("/api/restful//maps/" + mapId + "/labels/" + labelId, HttpMethod.DELETE, null, String.class);
assertTrue(exchange.getStatusCode().is2xxSuccessful());
@ -535,12 +535,12 @@ public class RestMindmapControllerTest {
// Create a sample map ...
final String mapTitle = "Maps 1 - ";
final URI mindmapUri = addNewMap(restTemplate, mapTitle);
final String mapId = mindmapUri.getPath().replace("/api/restfull/maps/", "");
final String mapId = mindmapUri.getPath().replace("/api/restful/maps/", "");
// Assign label to map ...
String labelId = labelUri.getPath().replace("/api/restfull/labels/", "");
String labelId = labelUri.getPath().replace("/api/restful/labels/", "");
HttpEntity<String> labelEntity = new HttpEntity<>(labelId, requestHeaders);
restTemplate.postForLocation("/api/restfull/maps/" + mapId + "/labels", labelEntity);
restTemplate.postForLocation("/api/restful/maps/" + mapId + "/labels", labelEntity);
// Check that the label has been assigned ...
Optional<RestMindmapInfo> mindmapInfo = fetchMap(requestHeaders, restTemplate, mapId);
@ -636,7 +636,7 @@ public class RestMindmapControllerTest {
final String maps = fetchMaps(requestHeaders, restTemplate).getMindmapsInfo().stream().map(map -> String.valueOf(map.getId())).collect(Collectors.joining(","));
final ResponseEntity<String> exchange = restTemplate.exchange("/api/restfull/maps/batch?ids=" + maps, HttpMethod.DELETE, null, String.class);
final ResponseEntity<String> exchange = restTemplate.exchange("/api/restful/maps/batch?ids=" + maps, HttpMethod.DELETE, null, String.class);
assertTrue(exchange.getStatusCode().is2xxSuccessful(), "Status code:" + exchange.getStatusCode() + " - " + exchange.getBody());
// Validate that the two maps are there ...
@ -769,7 +769,7 @@ public class RestMindmapControllerTest {
@NotNull
private RestMindmapList fetchMaps(final HttpHeaders requestHeaders, final TestRestTemplate template) throws RestClientException {
final HttpEntity<RestMindmapList> findMapEntity = new HttpEntity<>(requestHeaders);
final ResponseEntity<RestMindmapList> response = template.exchange("/api/restfull/maps/", HttpMethod.GET, findMapEntity, RestMindmapList.class);
final ResponseEntity<RestMindmapList> response = template.exchange("/api/restful/maps/", HttpMethod.GET, findMapEntity, RestMindmapList.class);
assertTrue(response.getStatusCode().is2xxSuccessful(), response.toString());
return Objects.requireNonNull(response.getBody());
@ -804,7 +804,7 @@ public class RestMindmapControllerTest {
// Create a new map ...
final HttpHeaders requestHeaders = createHeaders(MediaType.APPLICATION_XML);
HttpEntity<String> createUserEntity = new HttpEntity<>(xml, requestHeaders);
return template.postForLocation("/api/restfull/maps?title=" + title, createUserEntity);
return template.postForLocation("/api/restful/maps?title=" + title, createUserEntity);
}
private URI addNewMap(@NotNull TestRestTemplate template, @NotNull String title) {

View File

@ -0,0 +1,118 @@
/*
* 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.test.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wisemapping.config.common.CommonConfig;
import com.wisemapping.config.rest.RestAppConfig;
import com.wisemapping.model.User;
import com.wisemapping.rest.UserController;
import com.wisemapping.rest.model.RestUser;
import com.wisemapping.rest.model.RestUserRegistration;
import com.wisemapping.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.web.servlet.MockMvc;
import static com.wisemapping.test.rest.RestHelper.createDummyUser;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, UserController.class})
@AutoConfigureMockMvc
public class RestUserControllerTest {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private MockMvc mockMvc;
@Autowired
private UserService userService;
private RestUser createUser() throws Exception {
final RestUser result = createDummyUser();
final String userJson = objectMapper.writeValueAsString(result);
mockMvc.perform(
post("/api/restful/admin/users").
contentType(MediaType.APPLICATION_JSON)
.content(userJson)
.with(user("test@wisemapping.org").roles("ADMIN")))
.andExpect(status().isCreated());
// Check dao ...
User userBy = userService.getUserBy(result.getEmail());
assertNotNull(userBy);
return result;
}
@Test
void resetPasswordInvalidUser() throws Exception {
this.mockMvc.perform
(put("/api/restful/users/resetPassword?email=doesnotexist@example.com"))
.andDo(print())
.andExpect(status().is4xxClientError())
.andExpect(content().string(containsString("The email provided is not a valid user account.")));
}
@Test
void resetPasswordValidUser() throws Exception {
final RestUser user = createUser();
this.mockMvc.perform
(put("/api/restful/users/resetPassword?email=" + user.getEmail()))
.andDo(print())
.andExpect(status().isOk());
}
@Test
@Disabled
void registerNewUser() throws Exception {
final RestUserRegistration user = RestUserRegistration.create("some@example.com", "somepass", "Test", "registation");
final String userJson = objectMapper.writeValueAsString(user);
mockMvc.perform(
post("/api/restful/users/").
contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().isCreated());
// Check dao ...
User userBy = userService.getUserBy(user.getEmail());
assertNotNull(userBy);
}
}