/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * 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.constellation.rest.api; import javax.annotation.security.RolesAllowed; import javax.inject.Inject; import javax.inject.Named; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.google.common.base.Function; import com.google.common.base.Optional; import org.constellation.admin.dto.metadata.Page; import org.constellation.admin.dto.metadata.PagedSearch; import org.constellation.configuration.AcknowlegementType; import org.constellation.database.api.UserWithRole; import org.constellation.database.api.jooq.tables.pojos.CstlUser; import org.constellation.database.api.repository.UserRepository; import org.constellation.security.*; import org.geotoolkit.util.StringUtilities; import org.glassfish.jersey.media.multipart.FormDataParam; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.ArrayList; /** * RestFull user configuration service * * @author Benjamin Garcia (Geomatys) * @version 0.9 * @since 0.9 */ @Component @Named @Path("/1/user/") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public class UserRest { @Inject private UserRepository userRepository; @Inject private org.constellation.security.SecurityManager securityManager; @GET @RolesAllowed("cstl-admin") public Response findAll(@QueryParam("withRoles") boolean withRole) { return Response.ok(userRepository.findActivesWithRole()).build(); } /** * search pageable on user * @param pagedSearch * @return */ @POST @Path("/search") @RolesAllowed("cstl-admin") public Page<UserWithRole> search(PagedSearch pagedSearch){ String text = pagedSearch.getText(), sortFieldName = null, sortOrder = null; int page = pagedSearch.getPage(), size = pagedSearch.getSize(); if(pagedSearch.getSort() != null) { sortFieldName = pagedSearch.getSort().getField(); sortOrder = pagedSearch.getSort().getOrder().name(); } return new Page<UserWithRole>() .setNumber(pagedSearch.getPage()) .setSize(pagedSearch.getSize()) .setContent(userRepository.search(text, size, page, sortFieldName, sortOrder)) .setTotal(userRepository.searchCount(pagedSearch.getText())); } @PUT @Path("/updateValidation/{id}") @Transactional public Response updateValidation(@PathParam("id") int id){ Optional<CstlUser> user = userRepository.findById(id); if(user.isPresent()){ boolean active = user.get().getActive(); if(active){ if (userRepository.isLastAdmin(id)){ return Response.serverError().entity("admin.user.last.admin").build(); } else { userRepository.desactivate(id); } } else { userRepository.activate(id); } } return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).build(); } @GET @Path("{id}") public Response findOne(@PathParam("id") int id) { return Response.ok(userRepository.findById(id)).build(); } @GET @Path("{id}/withRole") public Response findOneWithRole(@PathParam("id") int id) { return userRepository.findOneWithRole(id).transform(new Function<UserWithRole, Response>() { @Override public Response apply(UserWithRole userWithRole) { return Response.ok(userWithRole).build(); } }).or(Response.status(404).build()); } @GET @Path("/myAccount") public Response myAccount() { String currentUserLogin = securityManager.getCurrentUserLogin(); return userRepository.findOneWithRole(currentUserLogin).transform(new Function<UserWithRole, Response>() { @Override public Response apply(UserWithRole userWithRole) { return Response.ok(userWithRole).build(); } }).or(Response.status(404).build()); } @DELETE @Path("{id}") @RolesAllowed("cstl-admin") @Transactional public Response delete(@PathParam("id") int id) { if (userRepository.isLastAdmin(id)) return Response.serverError().entity("admin.user.last.admin") .build(); userRepository.desactivate(id); return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).build(); } /** * Add user, * this method take FormDataParam to support upload (logo or avatar) * @param userId * @param login * @param email * @param lastname * @param firstname * @param address * @param additionalAddress * @param zip * @param city * @param country * @param phone * @param password * @return */ @POST @Path("/add") @RolesAllowed("cstl-admin") @Consumes(MediaType.MULTIPART_FORM_DATA) @Transactional(rollbackFor = Exception.class) public Response add(@FormDataParam("userId") Integer userId, @FormDataParam("login") String login, @FormDataParam("email") String email, @FormDataParam("lastname") String lastname, @FormDataParam("firstname") String firstname, @FormDataParam("address") String address, @FormDataParam("additionalAddress") String additionalAddress, @FormDataParam("zip") String zip, @FormDataParam("city") String city, @FormDataParam("country") String country, @FormDataParam("phone") String phone, @FormDataParam("password") String password, @FormDataParam("role") String role, @FormDataParam("locale") String locale){ //add user CstlUser user = new CstlUser(); user.setId(null); user.setLogin(login); user.setFirstname(firstname); user.setLastname(lastname); user.setEmail(email); user.setActive(true); user.setAddress(address); user.setAdditionalAddress(additionalAddress); user.setZip(zip); user.setCity(city); user.setCountry(country); user.setPhone(phone); user.setPassword(StringUtilities.MD5encode(password)); user.setLocale(locale); user = userRepository.insert(user); //add user to role userRepository.addUserToRole(user.getId(), role); return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).build(); } @POST @Path("/edit") @RolesAllowed("cstl-admin") @Consumes(MediaType.MULTIPART_FORM_DATA) @Transactional(rollbackFor = Exception.class) public Response edit(@FormDataParam("userId") Integer userId, @FormDataParam("login") String login, @FormDataParam("email") String email, @FormDataParam("lastname") String lastname, @FormDataParam("firstname") String firstname, @FormDataParam("address") String address, @FormDataParam("additionalAddress") String additionalAddress, @FormDataParam("zip") String zip, @FormDataParam("city") String city, @FormDataParam("country") String country, @FormDataParam("phone") String phone, @FormDataParam("password") String password, @FormDataParam("group") Integer group, @FormDataParam("role") String role, @FormDataParam("locale") String locale) { Optional<CstlUser> optionalUser = userRepository.findById(userId); if(optionalUser.isPresent()){ CstlUser user = optionalUser.get(); user.setLogin(login); user.setFirstname(firstname); user.setLastname(lastname); user.setEmail(email); user.setAddress(address); user.setAdditionalAddress(additionalAddress); user.setZip(zip); user.setCity(city); user.setCountry(country); user.setPhone(phone); user.setLocale(locale); //check password update String newPassword = StringUtilities.MD5encode(password); if(password != null && !password.isEmpty() && !newPassword.equals(user.getPassword())){ user.setPassword(newPassword); } userRepository.update(user); //add user to role userRepository.addUserToRole(user.getId(), role); return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).build(); } return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).status(Response.Status.NOT_FOUND).build(); } @POST @Path("/my_account") @Consumes(MediaType.MULTIPART_FORM_DATA) @Transactional(rollbackFor = Exception.class) public Response myAccount(@FormDataParam("userId") Integer userId, @FormDataParam("login") String login, @FormDataParam("email") String email, @FormDataParam("lastname") String lastname, @FormDataParam("firstname") String firstname, @FormDataParam("address") String address, @FormDataParam("additionalAddress") String additionalAddress, @FormDataParam("zip") String zip, @FormDataParam("city") String city, @FormDataParam("country") String country, @FormDataParam("phone") String phone, @FormDataParam("password") String password, @FormDataParam("group") Integer group, @FormDataParam("role") String role, @FormDataParam("locale") String locale) { String currentUserLogin = securityManager.getCurrentUserLogin(); if(currentUserLogin != null){ Optional<CstlUser> optionalUser = userRepository.findOne(currentUserLogin); if(optionalUser.isPresent()){ CstlUser user = optionalUser.get(); user.setLogin(login); user.setFirstname(firstname); user.setLastname(lastname); user.setEmail(email); user.setAddress(address); user.setAdditionalAddress(additionalAddress); user.setZip(zip); user.setCity(city); user.setCountry(country); user.setPhone(phone); user.setLocale(locale); //check password update String newPassword = StringUtilities.MD5encode(password); if(password != null && !password.isEmpty() && !newPassword.equals(user.getPassword())){ user.setPassword(newPassword); } userRepository.update(user); return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).build(); } } return Response.noContent().type(MediaType.TEXT_PLAIN_TYPE).status(Response.Status.NOT_FOUND).build(); } /** * Called on login. To know if login is granted to access to server * * @return an {@link AcknowlegementType} on {@link Response} to know * operation state */ @GET @Path("access") public Response access() { final AcknowlegementType response = new AcknowlegementType("Success", "You have access to the configuration service"); return Response.ok(response).build(); } }