package org.cloudfoundry.identity.uaa.invitations;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.identity.uaa.account.PasswordChangeRequest;
import org.cloudfoundry.identity.uaa.codestore.ExpiringCode;
import org.cloudfoundry.identity.uaa.codestore.ExpiringCodeStore;
import org.cloudfoundry.identity.uaa.constants.OriginKeys;
import org.cloudfoundry.identity.uaa.scim.ScimUser;
import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning;
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import java.util.Map;
import java.util.Set;
import static org.cloudfoundry.identity.uaa.codestore.ExpiringCodeType.INVITATION;
import static org.springframework.security.oauth2.common.util.OAuth2Utils.CLIENT_ID;
import static org.springframework.security.oauth2.common.util.OAuth2Utils.REDIRECT_URI;
@Service
public class EmailInvitationsService implements InvitationsService {
public static final String USER_ID = "user_id";
public static final String EMAIL = "email";
private final Log logger = LogFactory.getLog(getClass());
@Autowired
private ScimUserProvisioning scimUserProvisioning;
@Autowired
private ExpiringCodeStore expiringCodeStore;
@Autowired
private ClientDetailsService clientDetailsService;
@Override
public AcceptedInvitation acceptInvitation(String code, String password) {
ExpiringCode expiringCode = expiringCodeStore.retrieveCode(code);
if ((null == expiringCode) || (null != expiringCode.getIntent() && !INVITATION.name().equals(expiringCode.getIntent()))) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST);
}
Map<String,String> userData = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {});
String userId = userData.get(USER_ID);
String clientId = userData.get(CLIENT_ID);
String redirectUri = userData.get(REDIRECT_URI);
ScimUser user = scimUserProvisioning.retrieve(userId);
user = scimUserProvisioning.verifyUser(userId, user.getVersion());
if (OriginKeys.UAA.equals(user.getOrigin()) && StringUtils.hasText(password)) {
PasswordChangeRequest request = new PasswordChangeRequest();
request.setPassword(password);
scimUserProvisioning.changePassword(userId, null, password);
}
String redirectLocation = "/home";
try {
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
Set<String> redirectUris = clientDetails.getRegisteredRedirectUri();
redirectLocation = UaaUrlUtils.findMatchingRedirectUri(redirectUris, redirectUri, redirectLocation);
} catch (NoSuchClientException x) {
logger.debug("Unable to find client_id for invitation:"+clientId);
} catch (Exception x) {
logger.error("Unable to resolve redirect for clientID:"+clientId, x);
}
return new AcceptedInvitation(redirectLocation, user);
}
}