001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.apps.sessions;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsUser;
032import org.opencms.main.CmsException;
033import org.opencms.main.CmsLog;
034import org.opencms.main.CmsSessionInfo;
035import org.opencms.main.CmsSystemInfo;
036import org.opencms.main.OpenCms;
037import org.opencms.ui.A_CmsUI;
038import org.opencms.ui.CmsVaadinUtils;
039import org.opencms.ui.apps.A_CmsWorkplaceApp;
040import org.opencms.ui.apps.CmsFileExplorerConfiguration;
041import org.opencms.ui.apps.Messages;
042import org.opencms.ui.apps.sessions.CmsSessionsTable.TableProperty;
043import org.opencms.ui.components.CmsBasicDialog;
044import org.opencms.ui.components.CmsUserInfo;
045import org.opencms.ui.components.OpenCmsTheme;
046import org.opencms.util.CmsDateUtil;
047
048import java.text.DateFormat;
049import java.util.ArrayList;
050import java.util.Date;
051import java.util.HashMap;
052import java.util.Iterator;
053import java.util.List;
054import java.util.Map;
055
056import org.apache.commons.logging.Log;
057
058import com.vaadin.ui.Button;
059import com.vaadin.ui.Button.ClickEvent;
060import com.vaadin.ui.Button.ClickListener;
061import com.vaadin.ui.VerticalLayout;
062import com.vaadin.ui.Window;
063
064/**
065 * Dialog to show user information and to switch to user session.<p>
066 */
067public class CmsUserInfoDialog extends CmsBasicDialog {
068
069    /**vaadin serial id.*/
070    private static final long serialVersionUID = -8358238253459658269L;
071
072    /** Log instance for this class. */
073    static final Log LOG = CmsLog.getLog(CmsUserInfoDialog.class);
074
075    /**CmsObject.*/
076    protected CmsObject m_cms;
077
078    /**Session info (if showing specific session). */
079    protected CmsSessionInfo m_session;
080
081    /**vaadin component. */
082    private Button m_cancelButton;
083
084    /**vaadin component.*/
085    private VerticalLayout m_layout;
086
087    /**vaadin component. */
088    private Button m_okButton;
089
090    /**User to show iformation for. */
091    private CmsUser m_user;
092
093    /**
094     * private empty constructor.<p>
095     */
096    private CmsUserInfoDialog() {
097
098        //
099    }
100
101    /**
102     * private constructor.<p>
103     *
104     * @param sessionInfo id to session
105     * @param closeRunnable runnable called by closing window
106     */
107    private CmsUserInfoDialog(final CmsSessionInfo sessionInfo, final Runnable closeRunnable) {
108
109        m_session = sessionInfo;
110
111        m_cms = A_CmsUI.getCmsObject();
112        try {
113            m_user = m_cms.readUser(sessionInfo.getUserId());
114            init(closeRunnable);
115        } catch (CmsException e) {
116            LOG.error("Can not read user.", e);
117        }
118
119    }
120
121    /**
122     * private constructor.<p>
123     *
124     * @param user to show dialog for
125     * @param closeRunnable runnable called by closing window
126     */
127    private CmsUserInfoDialog(final CmsUser user, final Runnable closeRunnable) {
128
129        m_cms = A_CmsUI.getCmsObject();
130        m_user = user;
131        init(closeRunnable);
132
133    }
134
135    /**
136     * Gets the status text from given session.
137     *
138     * @param lastActivity miliseconds since last activity
139     * @return status string
140     */
141    public static String getStatusForItem(Long lastActivity) {
142
143        if (lastActivity.longValue() < CmsSessionsTable.INACTIVE_LIMIT) {
144            return CmsVaadinUtils.getMessageText(Messages.GUI_MESSAGES_BROADCAST_COLS_STATUS_ACTIVE_0);
145        }
146        return CmsVaadinUtils.getMessageText(Messages.GUI_MESSAGES_BROADCAST_COLS_STATUS_INACTIVE_0);
147    }
148
149    /**
150     * Gets the status style for given session.<p>
151     *
152     * @param lastActivity miliseconds since last activity
153     * @return style
154     */
155    public static String getStatusStyleForItem(Long lastActivity) {
156
157        if (lastActivity.longValue() < CmsSessionsTable.INACTIVE_LIMIT) {
158            return OpenCmsTheme.TABLE_COLUMN_BOX_CYAN;
159        }
160        return OpenCmsTheme.TABLE_COLUMN_BOX_GRAY;
161    }
162
163    /**
164     * Shows a dialog with user information for given session.
165     *
166     * @param session to show information for
167     */
168    public static void showUserInfo(CmsSessionInfo session) {
169
170        final Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
171        CmsUserInfoDialog dialog = new CmsUserInfoDialog(session, new Runnable() {
172
173            public void run() {
174
175                window.close();
176            }
177
178        });
179        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MESSAGES_SHOW_USER_0));
180        window.setContent(dialog);
181        A_CmsUI.get().addWindow(window);
182    }
183
184    /**
185     * Shows a dialog with user information.<p>
186     *
187     * @param user to show information for.
188     */
189    public static void showUserInfo(CmsUser user) {
190
191        final Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide);
192        CmsBasicDialog dialog = new CmsUserInfoDialog(user, new Runnable() {
193
194            public void run() {
195
196                window.close();
197
198            }
199
200        });
201        window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_MESSAGES_SHOW_USER_0));
202        window.setContent(dialog);
203        A_CmsUI.get().addWindow(window);
204    }
205
206    /**
207     * Adds information lines to the user dialog.<p>
208     * @param currentSession the session which gets displayed or null
209     * @return list of lines
210     */
211    private List<String> getFurtherInfoLines(CmsSessionInfo currentSession) {
212
213        boolean neverActive = false;
214        Long inacTime = Long.valueOf(0L);
215        List<String> res = new ArrayList<String>();
216        if (currentSession == null) {
217            inacTime = Long.valueOf(System.currentTimeMillis() - m_user.getLastlogin());
218            neverActive = m_user.getLastlogin() == 0L;
219        } else {
220            inacTime = Long.valueOf(System.currentTimeMillis() - currentSession.getTimeLastAction());
221        }
222
223        String[] inactiveTime = CmsSessionInfo.getHourMinuteSecondTimeString(inacTime.longValue());
224
225        if (!neverActive) {
226            if (currentSession != null) {
227                res.add("");
228                res.add("<p>" + CmsVaadinUtils.getMessageText(Messages.GUI_SESSIONS_SESSION_INFO_0) + "</p>");
229                res.add(
230                    CmsVaadinUtils.getMessageText(
231                        Messages.GUI_MESSAGES_LAST_ACTIVITY_2,
232                        inactiveTime[1] + ":" + inactiveTime[2],
233                        CmsVaadinUtils.getMessageText(Messages.GUI_MESSAGES_MINUTES_0)) + getStatusHTML(inacTime));
234            } else {
235                res.add(getLastLoginMessage(inacTime));
236            }
237        }
238        res.add(
239            CmsVaadinUtils.getMessageText(Messages.GUI_USERMANAGEMENT_USER_DATE_CREATED_0)
240                + ": "
241                + CmsDateUtil.getDateTime(
242                    new Date(m_user.getDateCreated()),
243                    DateFormat.SHORT,
244                    A_CmsUI.get().getLocale()));
245        if (currentSession != null) {
246            res.add(TableProperty.Site.getLocalizedMessage() + ": " + getSiteTitle(currentSession));
247
248            try {
249                res.add(
250                    TableProperty.Project.getLocalizedMessage()
251                        + ": "
252                        + A_CmsUI.getCmsObject().readProject(currentSession.getProject()).getName());
253            } catch (CmsException e) {
254                LOG.error("Unable to read project", e);
255            }
256        }
257        return res;
258    }
259
260    /**
261     * Get Message for show last login information.<p>
262     *
263     * @param inacTime time since last login in milli sec
264     * @return HTML String
265     */
266    private String getLastLoginMessage(Long inacTime) {
267
268        int days = (int)(inacTime.longValue() / (1000 * 60 * 60 * 24));
269        if (days == 0) {
270            return CmsVaadinUtils.getMessageText(Messages.GUI_USER_INFO_LAST_LOGIN_LESS_A_DAY_0);
271        }
272        if (days == 1) {
273            return CmsVaadinUtils.getMessageText(Messages.GUI_USER_INFO_LAST_LOGIN_YESTERDAY_0);
274        }
275        return CmsVaadinUtils.getMessageText(Messages.GUI_USER_INFO_LAST_LOGIN_DAYS_AGO_1, Integer.valueOf(days));
276    }
277
278    /**
279     * Gets the most current session for given user.<p>
280     *
281     * @param user CmsUser to get session for
282     * @return CmsSessionInfo or null if no session is available for user
283     */
284    private CmsSessionInfo getSessionForUser(CmsUser user) {
285
286        List<CmsSessionInfo> sessions = OpenCms.getSessionManager().getSessionInfos(user.getId());
287
288        if (sessions.isEmpty()) {
289            return null;
290        }
291
292        CmsSessionInfo currentSession = sessions.get(0);
293        for (CmsSessionInfo session : sessions) {
294            if (session.getTimeUpdated() > currentSession.getTimeUpdated()) {
295                currentSession = session;
296            }
297        }
298        return currentSession;
299    }
300
301    /**
302     * Gets the title for the site of the session.<p>
303     *
304     * @param currentSession to get site-title for
305     * @return title of site as string
306     */
307    private String getSiteTitle(CmsSessionInfo currentSession) {
308
309        String siteRoot = currentSession.getSiteRoot();
310        return (siteRoot.isEmpty() | siteRoot.equals("/"))
311        ? CmsVaadinUtils.getMessageText(org.opencms.ade.galleries.Messages.GUI_ROOT_SITE_0)
312        : OpenCms.getSiteManager().getSiteForSiteRoot(siteRoot).getTitle();
313    }
314
315    /**
316     * Get status span.<p>
317     *
318     * @param inacTime time
319     * @return html
320     */
321    private String getStatusHTML(Long inacTime) {
322
323        return "<span class=\"" + getStatusStyleForItem(inacTime) + "\">" + getStatusForItem(inacTime) + "</span> ";
324    }
325
326    /**
327     * Initializes the dialog.<p>
328     *
329     * @param closeRunnable runnable
330     */
331    private void init(final Runnable closeRunnable) {
332
333        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
334
335        //Fix the width. Dialog can only be used by calling static method which creates a wide window.
336        CmsUserInfo info = new CmsUserInfo(m_user.getId(), "640px");
337        CmsSessionInfo session = m_session == null ? getSessionForUser(m_user) : m_session;
338        Iterator<String> iterator = getFurtherInfoLines(session).iterator();
339
340        while (iterator.hasNext()) {
341            info.addDetailLine(iterator.next());
342        }
343        m_layout.addComponent(info);
344
345        if (session != null) {
346            m_okButton.addClickListener(new ClickListener() {
347
348                private static final long serialVersionUID = 3096577957489665752L;
349
350                public void buttonClick(ClickEvent event) {
351
352                    try {
353                        A_CmsUI.get().changeProject(m_cms.readProject(session.getProject()));
354                        A_CmsUI.get().changeSite(session.getSiteRoot());
355
356                        String path = OpenCms.getSessionManager().switchUserFromSession(
357                            m_cms,
358                            CmsVaadinUtils.getRequest(),
359                            m_cms.readUser(session.getUserId()),
360                            session);
361
362                        if (path == null) {
363                            Map<String, String[]> parameters = new HashMap<>();
364                            parameters.put("_lrid", new String[] {String.valueOf(System.currentTimeMillis())});
365                            path = CmsVaadinUtils.getWorkplaceLink(
366                                CmsFileExplorerConfiguration.APP_ID,
367                                session.getProject().getStringValue()
368                                    + A_CmsWorkplaceApp.PARAM_SEPARATOR
369                                    + session.getSiteRoot()
370                                    + A_CmsWorkplaceApp.PARAM_SEPARATOR
371                                    + A_CmsWorkplaceApp.PARAM_SEPARATOR,
372                                parameters);
373                        }
374                        A_CmsUI.get().getPage().setLocation(path);
375                        if (path.contains(CmsSystemInfo.WORKPLACE_PATH + "#")) {
376                            A_CmsUI.get().getPage().reload();
377                        }
378                    } catch (CmsException e) {
379                        //
380                    }
381                    closeRunnable.run();
382                }
383
384            });
385        }
386        setHideSwitchButton(session);
387
388        m_cancelButton.addClickListener(new ClickListener() {
389
390            private static final long serialVersionUID = -1033076596404978498L;
391
392            public void buttonClick(ClickEvent event) {
393
394                closeRunnable.run();
395
396            }
397        });
398    }
399
400    /**
401     * Hides the switch user button.<p>
402     *
403     * @param session to be checked
404     */
405    @SuppressWarnings("null")
406    private void setHideSwitchButton(CmsSessionInfo session) {
407
408        boolean visible = session != null;
409
410        if (visible) {
411            visible = !OpenCms.getSessionManager().getSessionInfo(CmsVaadinUtils.getRequest()).getSessionId().equals(
412                session.getSessionId());
413        }
414        m_okButton.setVisible(visible);
415
416    }
417
418}