Commit 5f111e36 authored by Matija Obreza's avatar Matija Obreza
Browse files

Imported MeController from the Catalog

parent c9618708
......@@ -15,15 +15,18 @@
*/
package org.genesys.catalog.server.controller.api;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.http.HttpServletRequest;
import org.genesys.catalog.exceptions.InvalidApiUsageException;
import org.genesys.catalog.exceptions.NotFoundElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
......@@ -35,11 +38,11 @@ import org.springframework.web.context.request.WebRequest;
*
* @author Matija Obreza
*/
@ControllerAdvice(basePackages = { "org.genesys.catalog.server.controller.api.v0" })
@ControllerAdvice(basePackages = { "org.genesys.catalog.server.controller.api", "org.genesys2.server.servlet.controller.api" })
public class ApiExceptionHandler {
/** The log. */
protected final Log LOG = LogFactory.getLog(getClass());
protected final Logger LOG = LoggerFactory.getLogger(getClass());
// @ResponseStatus(code = HttpStatus.NOT_FOUND)
// @ExceptionHandler(NoSuchAccessionException.class)
......@@ -125,6 +128,20 @@ public class ApiExceptionHandler {
return new ApiError<>(e);
}
/**
* Handle request method fail.
*
* @param req the req
* @param e the e
* @return the model and view
*/
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(value = { HttpRequestMethodNotSupportedException.class })
public ApiError<Exception> handleRequestMethodFail(final HttpServletRequest req, final HttpRequestMethodNotSupportedException e) {
LOG.warn("Request method {} not supported for URL {}", e.getMethod(), req.getRequestURL(), e);
return new ApiError<>(e);
}
/**
* Handle server error.
*
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.genesys.catalog.server.controller.api.v0;
import java.io.IOException;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.security.SecurityContextUtil;
import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.lockout.AccountLockoutManager;
import org.genesys.catalog.model.Partner;
import org.genesys.catalog.model.dataset.Dataset;
import org.genesys.catalog.model.filters.DatasetFilter;
import org.genesys.catalog.model.filters.DescriptorFilter;
import org.genesys.catalog.model.filters.DescriptorListFilter;
import org.genesys.catalog.model.filters.PartnerFilter;
import org.genesys.catalog.model.traits.Descriptor;
import org.genesys.catalog.model.traits.DescriptorList;
import org.genesys.catalog.server.controller.api.FilteredPage;
import org.genesys.catalog.service.DatasetService;
import org.genesys.catalog.service.DescriptorListService;
import org.genesys.catalog.service.DescriptorService;
import org.genesys.catalog.service.PartnerService;
import org.genesys.catalog.service.ShortFilterService;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* The Class MeController.
*
* @author Andrey Lugovskoy.
*/
@RestController
@RequestMapping(MeController.API_URL)
@PreAuthorize("isAuthenticated()")
public class MeController {
/** The Constant API_URL. */
public static final String API_URL = "/api/v0/me";
@Autowired
private PartnerService partnerService;
@Autowired
private DatasetService datasetService;
@Autowired
private DescriptorService descriptorService;
@Autowired
private DescriptorListService descriptorListService;
@Autowired
private ConsumerTokenServices consumerTokenServices;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AccountLockoutManager lockoutManager;
@Autowired
private UserService userService;
/** The short filter service. */
@Autowired
protected ShortFilterService shortFilterService;
/**
* Removes the token.
*
* @param token the token
* @return the object
*/
@PostMapping(value = "/token", consumes = "text/plain")
public Object removeToken(@RequestBody final String token) {
consumerTokenServices.revokeToken(token);
return token;
}
/**
* Gets the profile.
*
* @return the profile
*/
@GetMapping(value = "/profile")
public User getProfile() {
final User currentUser = SecurityContextUtil.getMe();
return userService.getUser(UUID.fromString(currentUser.getUuid()));
}
/**
* Change password.
*
* @param oldPassword the old password
* @param newPassword the new password
* @return the string
* @throws UserException the user exception
*/
@PostMapping(value = "/password")
public String changePassword(@RequestParam(name = "old", required = true) final String oldPassword, @RequestParam(name = "new", required = true) final String newPassword)
throws UserException {
final User currentUser = userService.getUser(UUID.fromString(SecurityContextUtil.getMe().getUuid()));
if (currentUser.isAccountLocked()) {
throw new LockedException("Too many failed login attempts.");
}
if (passwordEncoder.matches(oldPassword, currentUser.getPassword())) {
lockoutManager.handleSuccessfulLogin(currentUser.getUsername());
// need to reload the record (different versions)
userService.changePassword(userService.getUser(UUID.fromString(currentUser.getUuid())), newPassword);
return "OK";
} else {
lockoutManager.handleFailedLogin(currentUser.getUsername());
throw new UserException("Your old password was entered incorrectly. Please enter it again.");
}
}
/**
* My partners.
*
* @param page the page
* @param pageSize the page size
* @param direction the direction
* @param sort the sort
* @param partnerFilter the partner filter
* @return the page
*/
@PostMapping(value = "/partners")
public Page<Partner> myPartners(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "name") final String[] sort, @RequestBody final PartnerFilter partnerFilter) {
return partnerService.listPartnersForCurrentUser(partnerFilter, new PageRequest(page, Integer.min(pageSize, 100), direction, sort));
}
/**
* My datasets.
*
* @param page the page
* @param pageSize the page size
* @param direction the direction
* @param sort the sort
* @param filterCode short filter code -- overrides filter in body
* @param filter the filter
* @return the page
* @throws IOException
*/
@PostMapping(value = "/datasets")
public FilteredPage<Dataset> myDatasets(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "DESC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "lastModifiedDate") final String[] sort,
@RequestParam(name = "f", required = false) String filterCode,
@RequestBody(required = false) DatasetFilter filter) throws IOException {
if (StringUtils.isNotBlank(filterCode)) {
filter = shortFilterService.filterByCode(filterCode, DatasetFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
return new FilteredPage<>(filterCode, filter, datasetService.listDatasetsForCurrentUser(filter, new PageRequest(page, Integer.min(pageSize, 100), direction, sort)));
}
/**
* My descriptors.
*
* @param page the page
* @param pageSize the page size
* @param direction the direction
* @param sort the sort
* @param filter the descriptor filter
* @return the page
* @throws IOException
*/
@PostMapping(value = "/descriptors")
public FilteredPage<Descriptor> myDescriptors(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "DESC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "lastModifiedDate") final String[] sort,
@RequestParam(name = "f", required = false) String filterCode,
@RequestBody(required = false) DescriptorFilter filter) throws IOException {
if (StringUtils.isNotBlank(filterCode)) {
filter = shortFilterService.filterByCode(filterCode, DescriptorFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
return new FilteredPage<>(filterCode, filter, descriptorService.listDescriptorsForCurrentUser(filter, new PageRequest(page, Integer.min(pageSize, 100), direction, sort)));
}
/**
* My descriptor lists.
*
* @param page the page
* @param pageSize the page size
* @param direction the direction
* @param sort the sort
* @param descriptorListFilter the descriptor list filter
* @return the page
* @throws IOException
*/
@PostMapping(value = "/descriptorlists")
public FilteredPage<DescriptorList> myDescriptorLists(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "DESC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "lastModifiedDate") final String[] sort,
@RequestParam(name = "f", required = false) String filterCode,
@RequestBody(required = false) DescriptorListFilter filter) throws IOException {
if (StringUtils.isNotBlank(filterCode)) {
filter = shortFilterService.filterByCode(filterCode, DescriptorListFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
return new FilteredPage<>(filterCode, filter, descriptorListService.listDescriptorListsForCurrentUser(filter, new PageRequest(page, Integer.min(pageSize, 100), direction, sort)));
}
}
......@@ -110,6 +110,16 @@ public class Crop extends GlobalVersionedAuditedModel implements AclAwareModel {
public void setName(String name) {
this.name = name;
}
/// For compatibility with the Catalog
@Transient
public String getTitle() {
return name;
}
public void setTitle(String title) {
setName(title);
}
public String getShortName() {
return shortName;
......@@ -119,6 +129,17 @@ public class Crop extends GlobalVersionedAuditedModel implements AclAwareModel {
this.shortName = shortName;
}
/// For compatibility with the Catalog
@Transient
public String getCode() {
return shortName;
}
public void setCode(final String code) {
this.shortName = code;
}
public String getDescription() {
return description;
}
......
......@@ -17,6 +17,7 @@
package org.genesys2.server.service;
import java.util.List;
import java.util.UUID;
import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.model.BasicUser.AccountType;
......@@ -40,6 +41,8 @@ public interface UserService extends BasicUserService<UserRole, User> {
User getUserByUuid(String uuid);
User getUser(UUID uuid);
boolean exists(String username);
Page<UserWrapper> listWrapped(int startRow, int pageSize) throws UserException;
......@@ -77,4 +80,5 @@ public interface UserService extends BasicUserService<UserRole, User> {
* @throws UserException
*/
void archiveUser(User user) throws UserException;
}
......@@ -25,6 +25,7 @@ import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
......@@ -294,6 +295,11 @@ public class UserServiceImpl extends BasicUserServiceImpl<UserRole, User> implem
return user;
}
@Override
public User getUser(UUID uuid) {
return getUserByUuid(uuid.toString());
}
@Override
public boolean exists(String username) {
......
......@@ -20,9 +20,6 @@ import java.util.List;
import javax.xml.bind.ValidationException;
import net.sf.oval.ConstraintViolation;
import net.sf.oval.Validator;
import org.genesys2.server.exception.AuthorizationException;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.impl.Crop;
......@@ -48,6 +45,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import net.sf.oval.ConstraintViolation;
import net.sf.oval.Validator;
@Controller
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = { "/api/v0/crops", "/json/v0/crops" })
......@@ -81,7 +81,7 @@ public class CropsController extends RestController {
* @return
* @throws ValidationException
*/
@RequestMapping(value = "", method = { RequestMethod.PUT, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
@RequestMapping(value = { "", "/create" }, method = { RequestMethod.PUT, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody Object createCrop(@RequestBody Crop cropJson) throws ValidationException {
LOG.info("Creating crop");
final Validator validator = new Validator();
......
......@@ -68,8 +68,8 @@ import org.springframework.web.servlet.view.JstlView;
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "org.genesys2.server.servlet.filter", "org.genesys2.server.servlet.controller",
"org.genesys.catalog.service", "org.genesys.catalog.server.util", "org.genesys.catalog.server.controller" })
@ComponentScan(basePackages = { "org.genesys2.server.servlet.filter", "org.genesys2.server.servlet.controller", "org.genesys.catalog.service", "org.genesys.catalog.server.util",
"org.genesys.catalog.server.controller" })
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Value("${theme.defaultThemeName}")
......@@ -170,39 +170,40 @@ public class WebConfiguration extends WebMvcConfigurerAdapter {
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/api/**")
// .allowedOrigins(uiOrigin)
.allowedMethods("*");
.allowedMethods("PUT", "POST", "GET", "DELETE");
// .allowedHeaders("header1", "header2", "header3")
// .exposedHeaders("header1", "header2")
// .allowCredentials(false).maxAge(3600);
registry.addMapping("/html/**").allowCredentials(false).allowedMethods("GET", "OPTIONS", "HEAD").allowedOrigins(baseUrl).maxAge(3600);
}
@Bean
public CorsProcessor corsProcessor() {
return new SameOriginCorsProcessor();
}
/**
* This bean post-processor sets our {@link #corsProcessor()} on all AbstractHandlerMapping beans
* This bean post-processor sets our {@link #corsProcessor()} on all
* AbstractHandlerMapping beans
*/
@Bean
public BeanPostProcessor useCustomCorsProcessor() {
return new BeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AbstractHandlerMapping) {
((AbstractHandlerMapping)bean).setCorsProcessor(corsProcessor());
((AbstractHandlerMapping) bean).setCorsProcessor(corsProcessor());
}
return bean;
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
};
}
public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
final MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
......@@ -213,8 +214,10 @@ public class WebConfiguration extends WebMvcConfigurerAdapter {
mapper.disable(SerializationFeature.EAGER_SERIALIZER_FETCH);
// deserialization
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
// Never ignore stuff we don't understand
mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// // Never ignore stuff we don't understand
// mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// ignore stuff we don't understand
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// explicit json views: every fields needs to be annotated, therefore enabled
mapper.enable(MapperFeature.DEFAULT_VIEW_INCLUSION);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment