blob: c2bae0a44c61bc092e8998c7233e717714603aea [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.openmeetings.web.app;
import static java.text.DateFormat.SHORT;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DASHBOARD_SHOW_MYROOMS_KEY;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DASHBOARD_SHOW_RSS_KEY;
import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DEFAULT_LANG_KEY;
import static org.apache.openmeetings.web.app.Application.getAuthenticationStrategy;
import static org.apache.openmeetings.web.app.Application.getBean;
import static org.apache.openmeetings.web.app.Application.getClientByKeys;
import static org.apache.openmeetings.web.app.Application.getDashboardContext;
import static org.apache.openmeetings.web.app.Application.isInvaldSession;
import static org.apache.openmeetings.web.app.Application.removeInvalidSession;
import static org.apache.openmeetings.web.app.Application.removeOnlineUser;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
import org.apache.openmeetings.db.dao.basic.ConfigurationDao;
import org.apache.openmeetings.db.dao.label.LabelDao;
import org.apache.openmeetings.db.dao.server.SOAPLoginDao;
import org.apache.openmeetings.db.dao.server.SessiondataDao;
import org.apache.openmeetings.db.dao.user.IUserManager;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.server.RemoteSessionObject;
import org.apache.openmeetings.db.entity.server.SOAPLogin;
import org.apache.openmeetings.db.entity.server.Sessiondata;
import org.apache.openmeetings.db.entity.user.State;
import org.apache.openmeetings.db.entity.user.User;
import org.apache.openmeetings.db.entity.user.User.Right;
import org.apache.openmeetings.db.entity.user.User.Type;
import org.apache.openmeetings.db.util.TimezoneUtil;
import org.apache.openmeetings.ldap.LdapLoginManagement;
import org.apache.openmeetings.util.OmException;
import org.apache.openmeetings.web.pages.SwfPage;
import org.apache.openmeetings.web.user.dashboard.MyRoomsWidget;
import org.apache.openmeetings.web.user.dashboard.MyRoomsWidgetDescriptor;
import org.apache.openmeetings.web.user.dashboard.RssWidget;
import org.apache.openmeetings.web.user.dashboard.RssWidgetDescriptor;
import org.apache.openmeetings.web.user.dashboard.StartWidgetDescriptor;
import org.apache.openmeetings.web.user.dashboard.WelcomeWidgetDescriptor;
import org.apache.openmeetings.web.util.OmUrlFragment;
import org.apache.openmeetings.web.util.UserDashboard;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.authentication.IAuthenticationStrategy;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.string.StringValue;
import org.apache.wicket.util.string.Strings;
import ro.fortsoft.wicket.dashboard.Dashboard;
import ro.fortsoft.wicket.dashboard.Widget;
import ro.fortsoft.wicket.dashboard.WidgetFactory;
import ro.fortsoft.wicket.dashboard.web.DashboardContext;
public class WebSession extends AbstractAuthenticatedWebSession {
private static final long serialVersionUID = 1L;
public static int MILLIS_IN_MINUTE = 60000;
public static final String SECURE_HASH = "secureHash";
public static final String INVITATION_HASH = "invitationHash";
private long userId = -1;
private Set<Right> rights = new HashSet<User.Right>(); //TODO renew somehow on user edit !!!!
private long languageId = -1; //TODO renew somehow on user edit !!!!
private String SID = null;
private OmUrlFragment area = null;
private TimeZone tz;
private TimeZone browserTz;
public final static String ISO8601_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssZ";
private DateFormat ISO8601FORMAT = new SimpleDateFormat(ISO8601_FORMAT_STRING); //FIXME not thread safe
private DateFormat sdf;
private UserDashboard dashboard;
private Locale browserLocale = null;
private Long recordingId;
private Long loginError = null;
private String externalType;
public static boolean kickedByAdmin = false;
public final static List<String> AVAILABLE_TIMEZONES = Arrays.asList(TimeZone.getAvailableIDs());
public final static Set<String> AVAILABLE_TIMEZONE_SET = new LinkedHashSet<String>(AVAILABLE_TIMEZONES);
public WebSession(Request request) {
super(request);
browserLocale = getLocale();
}
@Override
public void invalidate() {
removeOnlineUser(getClientByKeys(getUserId(), get().getId()));
super.invalidate();
userId = -1;
rights = new HashSet<User.Right>();
SID = null;
sdf = null;
recordingId = null;
externalType = null;
tz = null;
browserTz = null;
loginError = null;
browserLocale = null;
}
@Override
public Roles getRoles() {
//first of all will check hashes
try {
IRequestParameters params = RequestCycle.get().getRequest().getRequestParameters();
StringValue secureHash = params.getParameterValue(SECURE_HASH);
StringValue invitationHash = params.getParameterValue(INVITATION_HASH);
if (!secureHash.isEmpty() || !invitationHash.isEmpty()) {
PageParameters pp = new PageParameters();
for (String p : params.getParameterNames()) {
List<StringValue> vals = params.getParameterValues(p);
if (vals != null) {
for (StringValue sv : vals) {
if (!sv.isEmpty()) {
pp.add(p, sv.toString());
}
}
}
}
if (isSignedIn()) {
invalidate();
}
throw new RestartResponseAtInterceptPageException(SwfPage.class, pp);
}
} catch (RestartResponseAtInterceptPageException e) {
throw e;
} catch (Exception e) {
//no-op, will continue to sign-in page
}
if (rights.isEmpty()) {
isSignedIn();
}
Roles r = new Roles();
for (Right right : rights) {
r.add(right.name());
}
return r;
}
@Override
public boolean isSignedIn() {
if (userId < 1) {
IAuthenticationStrategy strategy = getAuthenticationStrategy();
// get username and password from persistence store
String[] data = strategy.load();
if (data != null && data.length > 3 && data[2] != null) {
Long domainId = null;
try {
domainId = Long.parseLong(data[3]);
} catch (Exception e) {
//no-op
}
// try to sign in the user
if (!signIn(data[0], data[1], Type.valueOf(data[2]), domainId)) {
// the loaded credentials are wrong. erase them.
strategy.remove();
}
}
}
return userId > -1;
}
public boolean signIn(String secureHash) {
//FIXME code is duplicated from MainService, need to be unified
SOAPLoginDao soapDao = getBean(SOAPLoginDao.class);
SOAPLogin soapLogin = soapDao.get(secureHash);
if (soapLogin != null && !soapLogin.getUsed()) { //add code for || (soapLogin.getAllowSameURLMultipleTimes())
SessiondataDao sessionDao = getBean(SessiondataDao.class);
Sessiondata sd = sessionDao.getSessionByHash(soapLogin.getSessionHash());
if (sd != null && sd.getSessionXml() != null) {
RemoteSessionObject remoteUser = RemoteSessionObject.fromXml(sd.getSessionXml());
if (remoteUser != null && !Strings.isEmpty(remoteUser.getExternalUserId())) {
UserDao userDao = getBean(UserDao.class);
User user = userDao.getExternalUser(remoteUser.getExternalUserId(), remoteUser.getExternalUserType());
if (user == null) {
user = userDao.getNewUserInstance(null);
user.setFirstname(remoteUser.getFirstname());
user.setLastname(remoteUser.getLastname());
user.setLogin(remoteUser.getUsername()); //FIXME check if login UNIQUE
user.setExternalUserId(remoteUser.getExternalUserId());
user.setExternalUserType(remoteUser.getExternalUserType());
user.getRights().add(Right.Room);
user.getAdresses().setEmail(remoteUser.getEmail());
user.setPictureuri(remoteUser.getPictureUrl());
} else {
user.setFirstname(remoteUser.getFirstname());
user.setLastname(remoteUser.getLastname());
user.setPictureuri(remoteUser.getPictureUrl());
}
user = userDao.update(user, null);
soapLogin.setUsed(true);
soapLogin.setUseDate(new Date());
//soapLogin.setClientURL(clientURL); //FIXME
soapDao.update(soapLogin);
sessionDao.updateUser(SID, user.getUser_id());
setUser(user);
recordingId = soapLogin.getRoomRecordingId();
return true;
}
}
}
return false;
}
private void setUser(User u) {
userId = u.getUser_id();
rights = Collections.unmodifiableSet(u.getRights());
languageId = u.getLanguage_id();
externalType = u.getExternalUserType();
tz = getBean(TimezoneUtil.class).getTimeZone(u);
ISO8601FORMAT.setTimeZone(tz);
setLocale(languageId == 3 ? Locale.GERMANY : LabelDao.languages.get(languageId)); //FIXME hack
//FIXMW locale need to be set by User language first
sdf = DateFormat.getDateTimeInstance(SHORT, SHORT, getLocale());
if (null == getId()) {
bind();
}
}
public boolean signIn(String login, String password, Type type, Long domainId) {
try {
User u = null;
switch (type) {
case ldap:
u = getBean(LdapLoginManagement.class).login(login, password, domainId);
break;
case user:
/* we will allow login against internal DB in case user 'guess' LDAP password */
u = getBean(UserDao.class).login(login, password);
break;
case oauth:
// we did all the checks at this stage, just set the user
u = getBean(UserDao.class).getByLogin(login, Type.oauth, domainId);
break;
default:
throw new OmException(-1L);
}
if (u == null) {
return false;
}
signIn(u);
return true;
} catch (OmException oe) {
loginError = oe.getCode() == null ? -1L : oe.getCode();
}
return false;
}
public boolean signIn(User u) {
Sessiondata sessData = getBean(SessiondataDao.class).startsession();
SID = sessData.getSession_id();
if (u == null) {
return false;
}
setUser(u);
return true;
}
public Long getLoginError() {
return loginError;
}
public static WebSession get() {
return (WebSession)AbstractAuthenticatedWebSession.get();
}
public void setLanguage(long languageId) {
this.languageId = languageId;
}
public static long getLanguage() {
checkIsInvalid();
WebSession session = get();
if (session.languageId < 0) {
if (session.isSignedIn()) {
session.languageId = getBean(UserDao.class).get(session.userId).getLanguage_id();
} else {
session.languageId = getBean(ConfigurationDao.class).getConfValue(CONFIG_DEFAULT_LANG_KEY, Long.class, "1");
}
}
return session.languageId;
}
public String getValidatedSid() {
SessiondataDao sessionDao = getBean(SessiondataDao.class);
Long _userId = sessionDao.checkSession(SID);
if (_userId == null || userId != _userId) {
Sessiondata sessionData = sessionDao.getSessionByHash(SID);
if (sessionData == null) {
sessionData = sessionDao.startsession();
}
if (!sessionDao.updateUser(sessionData.getSession_id(), userId, false, languageId)) {
//something bad, force user to re-login
invalidate();
} else {
SID = sessionData.getSession_id();
}
}
return SID;
}
public static String getSid() {
return get().getValidatedSid();
}
public static long getUserId() {
checkIsInvalid();
return get().userId;
}
public static Long getRecordingId() {
return get().recordingId;
}
public static String getExternalType() {
return get().externalType;
}
public static TimeZone getUserTimeZone() {
return get().tz;
}
public static Calendar getCalendar() {
return Calendar.getInstance(get().tz);
}
public static Calendar getClientCalendar() {
return Calendar.getInstance(getClientTimeZone());
}
public static DateFormat getIsoDateFormat() {
return get().ISO8601FORMAT;
}
public static DateFormat getDateFormat() {
return get().sdf;
}
public static Set<Right> getRights() {
checkIsInvalid();
return get().rights;
}
public static void setKickedByAdmin(boolean kicked) {
kickedByAdmin = kicked;
}
public boolean isKickedByAdmin() {
return kickedByAdmin;
}
public OmUrlFragment getArea() {
return area;
}
public void setArea(OmUrlFragment area) {
this.area = area;
}
public static Dashboard getDashboard() {
Dashboard d = get().dashboard;
if (d == null) {
get().initDashboard();
d = get().dashboard;
}
return d;
}
public Locale getBrowserLocale(){
return browserLocale;
}
public Long getLanguageByBrowserLocale() {
return getBean(IUserManager.class).getLanguage(getBrowserLocale());
}
public State getCountryByBrowserLocale() {
return getBean(IUserManager.class).getCountry(getBrowserLocale());
}
public String getClientTZCode() {
TimeZone _zone = browserTz;
if (browserTz == null) {
try {
browserTz = getClientInfo().getProperties().getTimeZone();
if (!AVAILABLE_TIMEZONE_SET.contains(browserTz.getID())) {
for (String availableID : AVAILABLE_TIMEZONES) {
TimeZone zone = TimeZone.getTimeZone(availableID);
if (zone.hasSameRules(browserTz)) {
browserTz = zone;
break;
}
}
}
_zone = browserTz;
} catch (Exception e) {
_zone = Calendar.getInstance(getBrowserLocale()).getTimeZone();
}
}
return _zone == null ? null : _zone.getID();
}
public static TimeZone getClientTimeZone() {
String tzCode = get().getClientTZCode();
return tzCode == null ? null : TimeZone.getTimeZone(tzCode);
}
private void initDashboard() {
DashboardContext dashboardContext = getDashboardContext();
dashboard = (UserDashboard)dashboardContext.getDashboardPersister().load();
boolean existMyRoomWidget = false, existRssWidget = false;
ConfigurationDao cfgDao = getBean(ConfigurationDao.class);
boolean showMyRoomConfValue = 1 == cfgDao.getConfValue(CONFIG_DASHBOARD_SHOW_MYROOMS_KEY, Integer.class, "0");
boolean showRssConfValue = 1 == cfgDao.getConfValue(CONFIG_DASHBOARD_SHOW_RSS_KEY, Integer.class, "0");
boolean save = false;
WidgetFactory widgetFactory = dashboardContext.getWidgetFactory();
if (dashboard == null) {
dashboard = new UserDashboard("default", "Default");
dashboard.addWidget(widgetFactory.createWidget(new WelcomeWidgetDescriptor()));
dashboard.addWidget(widgetFactory.createWidget(new StartWidgetDescriptor()));
if (showMyRoomConfValue) {
dashboard.addWidget(widgetFactory.createWidget(new MyRoomsWidgetDescriptor()));
}
if (showRssConfValue) {
dashboard.addWidget(widgetFactory.createWidget(new RssWidgetDescriptor()));
}
save = true;
} else {
for (Iterator<Widget> iter = dashboard.getWidgets().iterator(); iter.hasNext();) {
Widget w = iter.next();
// PrivateRoomWidget is stored in the profile of user. Now, Show_MyRooms_key is disable.
if (w.getClass().equals(MyRoomsWidget.class)) {
existMyRoomWidget = true;
if (!showMyRoomConfValue) {
iter.remove();
}
} else if ((w.getClass().equals(RssWidget.class))) {
// RssWidget is stored in the profile of user. Now, Show_RSS_Key is disable.
existRssWidget = true;
if (!showRssConfValue) {
iter.remove();
}
} else {
w.init();
}
}
// PrivateRoomWidget was deleted from profile and now it's enabled. It's added again to dashboard.
if (!existMyRoomWidget && showMyRoomConfValue && !dashboard.isWidgetMyRoomsDeleted()) {
dashboard.addWidget(widgetFactory.createWidget(new MyRoomsWidgetDescriptor()));
save = true;
}
// RssWidget was deleted from profile and now it's enabled. It's added again to dashboard.
if (!existRssWidget && showRssConfValue && !dashboard.isWidgetRssDeleted()) {
dashboard.addWidget(widgetFactory.createWidget(new RssWidgetDescriptor()));
save = true;
}
}
if (save) {
dashboardContext.getDashboardPersister().save(dashboard);
}
}
private static void checkIsInvalid() {
if (isInvaldSession(get().getId())) {
setKickedByAdmin(true);
removeInvalidSession(get().getId());
org.apache.wicket.Session session = (org.apache.wicket.Session)get();
session.invalidate();
Application.get().restartResponseAtSignInPage();
}
}
}