/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.user.server;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import com.google.common.collect.ImmutableMap;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.core.rest.Service;
import org.eclipse.che.api.core.rest.annotations.GenerateLink;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.user.shared.dto.UserDto;
import org.eclipse.che.commons.env.EnvironmentContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
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.Response;
import java.util.Map;
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.Response.Status.CREATED;
import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER;
import static org.eclipse.che.api.user.server.Constants.LINK_REL_CURRENT_USER_PASSWORD;
import static org.eclipse.che.api.user.server.Constants.LINK_REL_USER;
import static org.eclipse.che.api.user.server.DtoConverter.asDto;
/**
* User REST API.
*
* @author Yevhenii Voevodin
* @author Anton Korneta
*/
@Path("/user")
@Api(value = "/user", description = "User REST API")
public class UserService extends Service {
public static final String USER_SELF_CREATION_ALLOWED = "che.auth.user_self_creation";
private final UserManager userManager;
private final TokenValidator tokenValidator;
private final UserLinksInjector linksInjector;
private final UserValidator userValidator;
private final boolean userSelfCreationAllowed;
@Inject
public UserService(UserManager userManager,
TokenValidator tokenValidator,
UserValidator userNameValidator,
UserLinksInjector linksInjector,
@Named(USER_SELF_CREATION_ALLOWED) boolean userSelfCreationAllowed) {
this.userManager = userManager;
this.linksInjector = linksInjector;
this.tokenValidator = tokenValidator;
this.userValidator = userNameValidator;
this.userSelfCreationAllowed = userSelfCreationAllowed;
}
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_USER)
@ApiOperation(value = "Create a new user", response = UserDto.class)
@ApiResponses({@ApiResponse(code = 201, message = "User successfully created, response contains created entity"),
@ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"),
@ApiResponse(code = 401, message = "Missed token parameter"),
@ApiResponse(code = 500, message = "Couldn't create user due to internal server error")})
public Response create(@ApiParam("New user")
UserDto userDto,
@ApiParam("Authentication token")
@QueryParam("token")
String token,
@ApiParam("User type")
@QueryParam("temporary")
@DefaultValue("false")
Boolean isTemporary) throws BadRequestException,
UnauthorizedException,
ConflictException,
ServerException {
if (userDto != null) {
//should be generated by userManager
userDto.setId(null);
}
final User newUser = token == null ? userDto : tokenValidator.validateToken(token);
userValidator.checkUser(newUser);
return Response.status(CREATED)
.entity(linksInjector.injectLinks(asDto(userManager.create(newUser, isTemporary)), getServiceContext()))
.build();
}
@GET
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_CURRENT_USER)
@ApiOperation("Get logged in user")
@ApiResponses({@ApiResponse(code = 200, message = "The response contains currently logged in user entity"),
@ApiResponse(code = 500, message = "Couldn't get user due to internal server error")})
public UserDto getCurrent() throws NotFoundException, ServerException {
final User user = userManager.getById(userId());
return linksInjector.injectLinks(asDto(user), getServiceContext());
}
@POST
@Path("/password")
@Consumes(APPLICATION_FORM_URLENCODED)
@GenerateLink(rel = LINK_REL_CURRENT_USER_PASSWORD)
@ApiOperation(value = "Update password of logged in user",
notes = "Password must contain at least 8 characters, " +
"passport must contain letters and digits")
@ApiResponses({@ApiResponse(code = 204, message = "Password successfully updated"),
@ApiResponse(code = 400, message = "Incoming password is invalid value." +
"Valid password must contain at least 8 character " +
"which are letters and digits"),
@ApiResponse(code = 500, message = "Couldn't update password due to internal server error")})
public void updatePassword(@ApiParam(value = "New password", required = true)
@FormParam("password")
String password) throws NotFoundException,
BadRequestException,
ServerException,
ConflictException {
userValidator.checkPassword(password);
final UserImpl user = new UserImpl(userManager.getById(userId()));
user.setPassword(password);
userManager.update(user);
}
@GET
@Path("/{id}")
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_USER)
@ApiOperation("Get user by identifier")
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested user entity"),
@ApiResponse(code = 404, message = "User with requested identifier not found"),
@ApiResponse(code = 500, message = "Impossible to get user due to internal server error")})
public UserDto getById(@ApiParam("User identifier")
@PathParam("id")
String id) throws NotFoundException, ServerException {
final User user = userManager.getById(id);
return linksInjector.injectLinks(asDto(user), getServiceContext());
}
@GET
@Path("/find")
@Produces(APPLICATION_JSON)
@GenerateLink(rel = LINK_REL_USER)
@ApiOperation("Get user by email or name")
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested user entity"),
@ApiResponse(code = 404, message = "User with requested email/name not found"),
@ApiResponse(code = 500, message = "Impossible to get user due to internal server error")})
public UserDto find(@ApiParam("User email, if it is set then name shouldn't be")
@QueryParam("email")
String email,
@ApiParam("User name, if is is set then email shouldn't be")
@QueryParam("name")
String name) throws NotFoundException,
ServerException,
BadRequestException {
if (email == null && name == null) {
throw new BadRequestException("Missed user's email or name");
}
if (email != null && name != null) {
throw new BadRequestException("Expected either user's email or name, while both values received");
}
final User user = name == null ? userManager.getByEmail(email) : userManager.getByName(name);
return linksInjector.injectLinks(asDto(user), getServiceContext());
}
@DELETE
@Path("/{id}")
@GenerateLink(rel = LINK_REL_USER)
@ApiOperation("Delete user")
@ApiResponses({@ApiResponse(code = 204, message = "User successfully removed"),
@ApiResponse(code = 409, message = "Couldn't remove user due to conflict(e.g. it has related entities)"),
@ApiResponse(code = 500, message = "Couldn't remove user due to internal server error")})
public void remove(@ApiParam("User identifier")
@PathParam("id")
String id) throws ServerException, ConflictException {
userManager.remove(id);
}
@GET
@Path("/settings")
@Produces(APPLICATION_JSON)
public Map<String, String> getSettings() {
return ImmutableMap.of(USER_SELF_CREATION_ALLOWED, Boolean.toString(userSelfCreationAllowed));
}
private static String userId() {
return EnvironmentContext.getCurrent().getSubject().getUserId();
}
}