/*
* JBoss, a division of Red Hat
* Copyright 2013, Red Hat Middleware, LLC, and individual
* contributors as indicated by the @authors tag. See the
* copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.portal.account;
import java.util.Collection;
import javax.servlet.http.HttpSession;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.application.UserProfileLifecycle;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.portal.webui.workspace.UIWorkingWorkspace;
import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.organization.UserProfile;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.web.CacheUserProfileFilter;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.web.application.JavascriptManager;
import org.exoplatform.web.application.Parameter;
import org.exoplatform.webui.application.WebuiRequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIApplication;
import org.exoplatform.webui.core.lifecycle.Lifecycle;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.form.UIForm;
import org.exoplatform.webui.form.UIFormStringInput;
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;
import org.gatein.security.oauth.spi.AccessTokenContext;
import org.gatein.security.oauth.spi.OAuthProviderType;
import org.gatein.security.oauth.common.OAuthConstants;
import org.gatein.security.oauth.spi.OAuthProviderTypeRegistry;
import org.gatein.security.oauth.spi.SocialNetworkService;
import org.gatein.security.oauth.exception.OAuthException;
import org.gatein.security.oauth.exception.OAuthExceptionCode;
/**
* Social networks tab of user profile
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ComponentConfig(lifecycle = Lifecycle.class, template = "system:/groovy/portal/webui/portal/UIAccountSocial.gtmpl",
events = { @EventConfig(listeners = UIAccountSocial.UnlinkSocialAccountActionListener.class) })
public class UIAccountSocial extends UIForm {
private static final Logger log = LoggerFactory.getLogger(UIAccountSocial.class);
private static final String PARAM_PROVIDER_FOR_UNLINK = "_paramProviderForUnlink";
public UIAccountSocial() throws Exception {
for (OAuthProviderType oauthPrType : getOAuthProviderTypes()) {
UIFormStringInput uiInput = new UIFormStringInput(oauthPrType.getUserNameAttrName(), null);
uiInput.setReadOnly(true);
addUIFormInput(uiInput);
}
updateUIFields();
}
public Collection<OAuthProviderType> getOAuthProviderTypes() {
// For now return all available oauthProviderTypes
return getApplicationComponent(OAuthProviderTypeRegistry.class).getEnabledOAuthProviders();
}
@Override
public void processRender(WebuiRequestContext context) throws Exception {
updateUIFields();
super.processRender(context);
}
private void updateUIFields() {
UserProfile userProfile = (UserProfile)Util.getPortalRequestContext().getAttribute(UserProfileLifecycle.USER_PROFILE_ATTRIBUTE_NAME);
if (userProfile == null) {
return;
}
for (OAuthProviderType oauthPrType : getOAuthProviderTypes()) {
String usernameAttrName = oauthPrType.getUserNameAttrName();
String oauthUsername = userProfile.getAttribute(usernameAttrName);
getUIStringInput(usernameAttrName).setValue(oauthUsername);
}
}
public void saveURLAfterLinkSocialAccount() {
PortalRequestContext prContext = Util.getPortalRequestContext();
HttpSession session = prContext.getRequest().getSession();
session.setAttribute(OAuthConstants.ATTRIBUTE_URL_TO_REDIRECT_AFTER_LINK_SOCIAL_ACCOUNT, prContext.getRequestURI());
}
public String getLinkSocialAccountURL(OAuthProviderType oauthPrType) {
PortalRequestContext prc = Util.getPortalRequestContext();
return oauthPrType.getInitOAuthURL(prc.getRequestContextPath(), prc.getRequestURI());
}
public String getUnlinkSocialAccountURL(OAuthProviderType oauthPrType) throws Exception {
Parameter[] params = new Parameter[] { new Parameter(PARAM_PROVIDER_FOR_UNLINK, oauthPrType.getKey()) };
return super.event("UnlinkSocialAccount", null, params);
}
public static class UnlinkSocialAccountActionListener extends EventListener<UIAccountSocial> {
public void execute(Event<UIAccountSocial> event) throws Exception {
UIAccountSocial uiForm = event.getSource();
OrganizationService service = uiForm.getApplicationComponent(OrganizationService.class);
WebuiRequestContext context = WebuiRequestContext.getCurrentInstance();
PortalRequestContext prContext = Util.getPortalRequestContext();
UIApplication uiApp = context.getUIApplication();
ConversationState state = ConversationState.getCurrent();
String userName = ((User) state.getAttribute(CacheUserProfileFilter.USER_PROFILE)).getUserName();
User user = service.getUserHandler().findUserByName(userName);
if (user != null) {
UserProfile userProfile = (UserProfile)prContext.getAttribute(UserProfileLifecycle.USER_PROFILE_ATTRIBUTE_NAME);
String unlinkProviderKey = prContext.getRequestParameter(PARAM_PROVIDER_FOR_UNLINK);
OAuthProviderType<AccessTokenContext> oauthProviderTypeToUnlink = uiForm.getApplicationComponent(OAuthProviderTypeRegistry.class).getOAuthProvider(unlinkProviderKey, AccessTokenContext.class);
// Obtain current accessToken
AccessTokenContext accessToken = uiForm.getApplicationComponent(SocialNetworkService.class).getOAuthAccessToken(oauthProviderTypeToUnlink, userName);
// Unlink social account in userProfile (AccessTokenInvalidationListener will automatically remove accessToken)
if (oauthProviderTypeToUnlink != null) {
userProfile.setAttribute(oauthProviderTypeToUnlink.getUserNameAttrName(), null);
} else {
log.warn("Social account field to unlink not found");
}
service.getUserProfileHandler().saveUserProfile(userProfile, true);
// Revoke accessToken remotely
if (accessToken != null) {
try {
oauthProviderTypeToUnlink.getOauthProviderProcessor().revokeToken(accessToken);
} catch (OAuthException oe) {
if (OAuthExceptionCode.TOKEN_REVOCATION_FAILED.equals(oe.getExceptionCode())) {
Throwable t = oe.getCause() != null ? oe.getCause() : oe;
ApplicationMessage appMessage = new ApplicationMessage("UIAccountSocial.msg.failed-revoke", null, ApplicationMessage.WARNING);
appMessage.setArgsLocalized(false);
uiApp.addMessage(appMessage);
log.warn("Revocation of accessToken failed for user " + userName + ". Details: " + t.getClass() + ": " + t.getMessage());
} else {
throw oe;
}
}
}
Object[] args = { oauthProviderTypeToUnlink.getFriendlyName(), userName};
ApplicationMessage appMessage = new ApplicationMessage("UIAccountSocial.msg.successful-unlink", args);
appMessage.setArgsLocalized(false);
uiApp.addMessage(appMessage);
prContext.setAttribute(UserProfileLifecycle.USER_PROFILE_ATTRIBUTE_NAME, userProfile);
uiForm.updateUIFields();
prContext.addUIComponentToUpdateByAjax(uiForm);
UIWorkingWorkspace uiWorkingWS = Util.getUIPortalApplication().getChild(UIWorkingWorkspace.class);
uiWorkingWS.updatePortletsByName("UserInfoPortlet");
uiWorkingWS.updatePortletsByName("OrganizationPortlet");
} else {
JavascriptManager jsManager = Util.getPortalRequestContext().getJavascriptManager();
jsManager.require("SHARED/base").addScripts(
"if(confirm('"
+ Util.getPortalRequestContext().getApplicationResourceBundle()
.getString("UIAccountProfiles.msg.NotExistingAccount") + "')) {eXo.portal.logout();}");
}
}
}
}