/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
/**
*
*/
package org.roda.wui.client.common;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import org.roda.core.data.v2.user.Group;
import org.roda.core.data.v2.user.RODAMember;
import org.roda.core.data.v2.user.User;
import org.roda.wui.client.common.dialogs.Dialogs;
import org.roda.wui.client.common.utils.StringUtils;
import org.roda.wui.client.welcome.Welcome;
import org.roda.wui.common.client.ClientLogger;
import org.roda.wui.common.client.HistoryResolver;
import org.roda.wui.common.client.LoginStatusListener;
import org.roda.wui.common.client.tools.CachedAsynRequest;
import org.roda.wui.common.client.tools.HistoryUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import config.i18n.client.ClientMessages;
/**
* @author Luis Faria
*
*
*
*/
public class UserLogin {
private static final ClientLogger logger = new ClientLogger(UserLogin.class.getName());
private static final ClientMessages messages = (ClientMessages) GWT.create(ClientMessages.class);
private static UserLoginServiceAsync userLoginService;
private static UserLogin instance = null;
private static Map<String, String> rodaProperties;
private static boolean initialized = false;
private static void init(final AsyncCallback<Map<String, String>> callback) {
if (!initialized) {
userLoginService = UserLoginService.Util.getInstance();
userLoginService.getRodaProperties(new AsyncCallback<Map<String, String>>() {
@Override
public void onFailure(Throwable caught) {
logger.fatal("Error getting role mapping", caught);
callback.onFailure(caught);
}
@Override
public void onSuccess(Map<String, String> properties) {
rodaProperties = properties;
initialized = true;
callback.onSuccess(properties);
}
});
} else {
callback.onSuccess(rodaProperties);
}
}
static {
init(new AsyncCallback<Map<String, String>>() {
@Override
public void onFailure(Throwable caught) {
logger.error("Error initializing", caught);
}
@Override
public void onSuccess(Map<String, String> properties) {
// nothing to do
}
});
}
/**
* Get the singleton instance
*
* @return the instance
*/
public static UserLogin getInstance() {
if (instance == null) {
instance = new UserLogin();
}
return instance;
}
private final List<LoginStatusListener> listeners;
private UserLogin() {
listeners = new Vector<>();
}
private final CachedAsynRequest<User> getUserRequest = new CachedAsynRequest<User>() {
@Override
public void getFromServer(AsyncCallback<User> callback) {
userLoginService.getAuthenticatedUser(callback);
}
};
/**
* Get current authenticated user. User is cached and only refreshed when
* login or logout actions are called.
*
* @param callback
* call back handler that receives error if failed or AuthOfficeUser
* if success.
*/
public void getAuthenticatedUser(final AsyncCallback<User> callback) {
getAuthenticatedUser(callback, false);
}
public void getAuthenticatedUser(final AsyncCallback<User> callback, boolean ensureIsFresh) {
if (ensureIsFresh) {
getUserRequest.clearCache();
}
getUserRequest.request(callback);
}
/**
* Login into RODA Core
*/
public void login() {
String currentURL = Window.Location.getHref().replaceAll("#", "%23");
String hash = Window.Location.getHash();
if (hash.length() > 0) {
hash = hash.substring(1);
hash = UriUtils.encode(hash);
}
String locale = LocaleInfo.getCurrentLocale().getLocaleName();
String moduleBaseURL = GWT.getModuleBaseURL();
moduleBaseURL = moduleBaseURL.substring(0, moduleBaseURL.length() - 2).substring(0, moduleBaseURL.indexOf('/'));
Window.open(moduleBaseURL + "login?service=" + currentURL + "&hash=" + hash + "&locale=" + locale, "_self", "");
}
public void login(String username, String password, final AsyncCallback<User> callback) {
userLoginService.login(username, password, new AsyncCallback<User>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(User newUser) {
getUserRequest.setCached(newUser);
onLoginStatusChanged(newUser);
callback.onSuccess(newUser);
}
});
}
/**
*
*/
public void logout() {
String currentURL = Window.Location.getHref().replaceAll("#", "%23");
String locale = LocaleInfo.getCurrentLocale().getLocaleName();
String moduleBaseURL = GWT.getModuleBaseURL();
moduleBaseURL = moduleBaseURL.substring(0, moduleBaseURL.length() - 2).substring(0, moduleBaseURL.indexOf('/'));
Window.open(moduleBaseURL + "logout?service=" + currentURL + "&locale=" + locale, "_self", "");
getUserRequest.clearCache();
}
/**
* Add a login status listener
*
* @param listener
*/
public void addLoginStatusListener(LoginStatusListener listener) {
listeners.add(listener);
}
/**
* Remove a login status listener
*
* @param listener
*/
public void removeLoginStatusListener(LoginStatusListener listener) {
listeners.remove(listener);
}
public void onLoginStatusChanged(User newUser) {
for (LoginStatusListener listener : listeners) {
listener.onLoginStatusChanged(newUser);
}
}
/**
* Check if the changing of the permissions of the RODA member affects current
* authenticated user and alert login status listeners
*
* @param member
* the member which had his permissions changed
*/
public void permissionsChanged(final RODAMember member) {
getAuthenticatedUser(new AsyncCallback<User>() {
@Override
public void onFailure(Throwable caught) {
// do nothing
}
@Override
public void onSuccess(User user) {
User authUser = user;
if (member instanceof User && member.getName().equals(authUser.getName())) {
onLoginStatusChanged(authUser);
}
if (member instanceof Group && Arrays.asList(authUser.getGroups()).contains(member.getName())) {
onLoginStatusChanged(authUser);
}
}
});
}
/**
* Get RODA properties
*
* @param callback
*/
public static void getRodaProperties(final AsyncCallback<Map<String, String>> callback) {
init(new AsyncCallback<Map<String, String>>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(Map<String, String> properties) {
callback.onSuccess(properties);
}
});
}
/**
* Get a RODA property
*
* @param key
* @param callback
*/
public static void getRodaProperty(final String key, final AsyncCallback<String> callback) {
init(new AsyncCallback<Map<String, String>>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(Map<String, String> properties) {
callback.onSuccess(properties.get(key));
}
});
}
/**
* Check if current user has permission to access a history resolver
*
* @param res
* @param callback
*/
public void checkRole(final HistoryResolver res, final AsyncCallback<Boolean> callback) {
String historyKey = StringUtils.join(res.getHistoryPath(), HistoryUtils.HISTORY_PERMISSION_SEP);
String propertyName = "ui.menu." + historyKey + ".role";
UserLogin.getRodaProperty(propertyName, new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(final String role) {
getAuthenticatedUser(new AsyncCallback<User>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(User authUser) {
callback.onSuccess(authUser.hasRole(role));
}
});
}
});
}
/**
* Check if current authenticated user can access some history resolvers
*
* @param res
* @param exclusive
* @param callback
*/
public void checkRoles(HistoryResolver[] res, final boolean exclusive, final AsyncCallback<Boolean> callback) {
final Boolean[] results = new Boolean[res.length];
for (int i = 0; i < res.length; i++) {
final int index = i;
checkRole(res[i], new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(Boolean rolePermitted) {
results[index] = rolePermitted;
boolean lastOne = true;
for (int i = 0; i < results.length; i++) {
if (results[i] == null) {
lastOne = false;
}
}
if (lastOne) {
if (exclusive) {
boolean ret = true;
for (int i = 0; i < results.length; i++) {
ret = results[i].booleanValue() ? ret : false;
}
callback.onSuccess(ret);
} else {
boolean ret = false;
for (int i = 0; i < results.length; i++) {
ret = results[i].booleanValue() ? true : ret;
}
callback.onSuccess(ret);
}
}
}
});
}
}
public void showSuggestLoginDialog() {
Dialogs.showConfirmDialog(messages.loginDialogTitle(), messages.casForwardWarning(), messages.loginDialogCancel(),
messages.loginDialogLogin(), new AsyncCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
if (result) {
UserLogin.getInstance().login();
} else {
HistoryUtils.newHistory(Welcome.RESOLVER);
}
}
@Override
public void onFailure(Throwable caught) {
HistoryUtils.newHistory(Welcome.RESOLVER);
}
});
}
public void updateLoggedUser(User u) {
getUserRequest.setCached(u);
}
}