Add session list for user
authorjoshuaruesweg <ruesweg@woltlab.com>
Fri, 30 Oct 2020 13:55:13 +0000 (14:55 +0100)
committerjoshuaruesweg <ruesweg@woltlab.com>
Mon, 2 Nov 2020 14:43:47 +0000 (15:43 +0100)
com.woltlab.wcf/templates/accountSecurity.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Session/Delete.js [new file with mode: 0644]
wcfsetup/install/files/lib/action/DeleteSessionAction.class.php
wcfsetup/install/files/lib/page/AccountSecurityPage.class.php
wcfsetup/install/files/style/ui/accountSecurity.scss [new file with mode: 0644]
wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/User/Session/Delete.ts [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index ccb4ffae545d5128dc311d2778552c6a3b41ac07..d8581b1b19ef347640b06d3aa4c6fa1c3cb214f6 100644 (file)
@@ -2,6 +2,48 @@
 
 {include file='header' __disableAds=true __sidebarLeftHasMenu=true}
 
-{* @TODO *}
+<section class="section">
+       <h2 class="sectionTitle">{lang}wcf.user.security.activeSessions{/lang}</h2>
+       
+       <ul class="containerList">
+               {foreach from=$activeSessions item=session}
+                       <li class="box64 sessionItem">
+                               <div>
+                                       <span class="icon icon64 fa-{$session->getDeviceIcon()}"></span>
+                               </div>
+                               
+                               <div class="accountSecurityContainer">
+                                       <div class="containerHeadline accountSecurityInformation">
+                                               <h3>{$session->getBrowser()}</h3>
+                                               <small>
+                                                       {$session->getIpAddress()}<br />
+                                                       {if $session->isCurrentSession()}
+                                                               {lang}wcf.user.security.currentSession{/lang}
+                                                       {else}
+                                                               {lang}wcf.user.security.sessionLastActive{/lang}
+                                                       {/if}
+                                               </small>
+                                       </div>
+                                       
+                                       {if !$session->isCurrentSession()}
+                                               <div class="accountSecurityButtons">
+                                                       <button class="small sessionDeleteButton" data-session-id="{$session->getSessionID()}">{lang}wcf.user.security.deleteSession{/lang}</button>
+                                               </div>
+                                       {/if}
+                               </div>
+                       </li>
+               {/foreach}
+       </ul>
+</section>
+
+<script data-relocate="true">
+       require(['Language', 'WoltLabSuite/Core/Ui/User/Session/Delete'], function(Language, UserSessionDelete) {
+               Language.addObject({
+                       'wcf.user.security.deleteSession.confirmMessage': '{jslang}wcf.user.security.deleteSession.confirmMessage{/jslang}',
+               });
+               
+               new (UserSessionDelete.default)();
+       });
+</script>
 
 {include file='footer' __disableAds=true}
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Session/Delete.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Session/Delete.js
new file mode 100644 (file)
index 0000000..bb4c43b
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * Handles the deletion of a user session.
+ *
+ * @author  Joshua Ruesweg
+ * @copyright  2001-2020 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Ui/User/Session/Delete
+ */
+define(["require", "exports", "tslib", "../../../Ajax", "../../Notification", "../../Confirmation", "../../../Language"], function (require, exports, tslib_1, Ajax, UiNotification, UiConfirmation, Language) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.UiUserSessionDelete = void 0;
+    Ajax = tslib_1.__importStar(Ajax);
+    UiNotification = tslib_1.__importStar(UiNotification);
+    UiConfirmation = tslib_1.__importStar(UiConfirmation);
+    Language = tslib_1.__importStar(Language);
+    class UiUserSessionDelete {
+        /**
+         * Initializes the session delete buttons.
+         */
+        constructor() {
+            this.knownElements = new Map();
+            document.querySelectorAll(".sessionDeleteButton").forEach((element) => {
+                if (!element.dataset.sessionId) {
+                    throw new Error(`No sessionId for session delete button given.`);
+                }
+                if (!this.knownElements.has(element.dataset.sessionId)) {
+                    element.addEventListener("click", (ev) => this.delete(element, ev));
+                    this.knownElements.set(element.dataset.sessionId, element);
+                }
+            });
+        }
+        /**
+         * Opens the user trophy list for a specific user.
+         */
+        delete(element, event) {
+            event.preventDefault();
+            UiConfirmation.show({
+                message: Language.get("wcf.user.security.deleteSession.confirmMessage"),
+                confirm: (_parameters) => {
+                    Ajax.api(this, {
+                        sessionID: element.dataset.sessionId,
+                    });
+                },
+            });
+        }
+        _ajaxSuccess(data) {
+            const element = this.knownElements.get(data.sessionID);
+            if (element !== undefined) {
+                const sessionItem = element.closest("li");
+                if (sessionItem !== null) {
+                    sessionItem.remove();
+                }
+            }
+            UiNotification.show();
+        }
+        _ajaxSetup() {
+            return {
+                url: "index.php?delete-session/&t=" + window.SECURITY_TOKEN,
+            };
+        }
+    }
+    exports.UiUserSessionDelete = UiUserSessionDelete;
+    exports.default = UiUserSessionDelete;
+});
index 512b31d8a8388256095a178bc9ae207a6f3fea49..b1ecf7162026bf3000b140e87bfa9fed5bf3d620 100644 (file)
@@ -23,7 +23,7 @@ class DeleteSessionAction extends AbstractAction {
        /**
         * @var string
         */
-       public $sessionID;
+       private $sessionID;
        
        /**
         * @inheritDoc
index dbd0061a78a6c9f5748d07d641fef60758efcff7..5a9fc2b49a784c2d73878cf3c39b5aa2dea51614 100644 (file)
@@ -1,6 +1,9 @@
 <?php
 namespace wcf\page;
 use wcf\system\menu\user\UserMenu;
+use wcf\system\session\Session;
+use wcf\system\session\SessionHandler;
+use wcf\system\WCF;
 
 /**
  * Shows the account security page.
@@ -17,6 +20,31 @@ class AccountSecurityPage extends AbstractPage {
         */
        public $loginRequired = true;
        
+       /**
+        * @var Session[]
+        */
+       private $activeSessions;
+       
+       /**
+        * @inheritDoc
+        */
+       public function readData() {
+               parent::readData();
+       
+               $this->activeSessions = SessionHandler::getInstance()->getUserSessions(WCF::getUser());
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function assignVariables() {
+               parent::assignVariables();
+               
+               WCF::getTPL()->assign([
+                       'activeSessions' => $this->activeSessions
+               ]);
+       }
+       
        /**
         * @inheritDoc
         */
diff --git a/wcfsetup/install/files/style/ui/accountSecurity.scss b/wcfsetup/install/files/style/ui/accountSecurity.scss
new file mode 100644 (file)
index 0000000..a3c7be6
--- /dev/null
@@ -0,0 +1,8 @@
+.accountSecurityContainer {
+       display: flex;
+       flex-wrap: wrap;
+}
+
+.accountSecurityInformation {
+       flex: 1 1 auto;
+}
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/User/Session/Delete.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/User/Session/Delete.ts
new file mode 100644 (file)
index 0000000..dc05dfd
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * Handles the deletion of a user session.
+ *
+ * @author  Joshua Ruesweg
+ * @copyright  2001-2020 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  WoltLabSuite/Core/Ui/User/Session/Delete
+ */
+
+import * as Ajax from "../../../Ajax";
+import { AjaxCallbackObject, AjaxCallbackSetup, DatabaseObjectActionResponse } from "../../../Ajax/Data";
+import * as UiNotification from "../../Notification";
+import * as UiConfirmation from "../../Confirmation";
+import * as Language from "../../../Language";
+
+export class UiUserSessionDelete implements AjaxCallbackObject {
+  private readonly knownElements = new Map<string, HTMLElement>();
+
+  /**
+   * Initializes the session delete buttons.
+   */
+  constructor() {
+    document.querySelectorAll(".sessionDeleteButton").forEach((element: HTMLElement) => {
+      if (!element.dataset.sessionId) {
+        throw new Error(`No sessionId for session delete button given.`);
+      }
+
+      if (!this.knownElements.has(element.dataset.sessionId)) {
+        element.addEventListener("click", (ev) => this.delete(element, ev));
+
+        this.knownElements.set(element.dataset.sessionId, element);
+      }
+    });
+  }
+
+  /**
+   * Opens the user trophy list for a specific user.
+   */
+  private delete(element: HTMLElement, event: MouseEvent): void {
+    event.preventDefault();
+
+    UiConfirmation.show({
+      message: Language.get("wcf.user.security.deleteSession.confirmMessage"),
+      confirm: (_parameters) => {
+        Ajax.api(this, {
+          sessionID: element.dataset.sessionId,
+        });
+      },
+    });
+  }
+
+  _ajaxSuccess(data: AjaxResponse): void {
+    const element = this.knownElements.get(data.sessionID);
+
+    if (element !== undefined) {
+      const sessionItem = element.closest("li");
+
+      if (sessionItem !== null) {
+        sessionItem.remove();
+      }
+    }
+
+    UiNotification.show();
+  }
+
+  _ajaxSetup(): ReturnType<AjaxCallbackSetup> {
+    return {
+      url: "index.php?delete-session/&t=" + window.SECURITY_TOKEN,
+    };
+  }
+}
+
+export default UiUserSessionDelete;
+
+interface AjaxResponse extends DatabaseObjectActionResponse {
+  sessionID: string;
+}
index de506e68455c6e15fda39bd73019c7dcaa76392c..5513869ec57c5a664d80a3f1fc8965342fa1a1bc 100644 (file)
@@ -4822,6 +4822,13 @@ Die E-Mail-Adresse des neuen Benutzers lautet: {@$user->email}
 <p><small><em>Quelle: <a href="http://www.mustervorlage.net/disclaimer-muster" class="externalURL">Mustervorlage.net</a></em></small></p>]]></item>
                <item name="wcf.user.register.error.blacklistMatches"><![CDATA[Die Registrierung kann aufgrund von Einschränkungen nicht fortgesetzt werden, bitte wende{if LANGUAGE_USE_INFORMAL_VARIANT} dich{else}n Sie sich{/if} direkt an den Administrator dieser Seite.]]></item>
        </category>
+       <category name="wcf.user.security">
+               <item name="wcf.user.security.activeSessions"><![CDATA[Aktive Sitzungen]]></item>
+               <item name="wcf.user.security.currentSession"><![CDATA[Aktuelle Sitzung]]></item>
+               <item name="wcf.user.security.sessionLastActive"><![CDATA[Sitzung zuletzt aktiv: {@$session->getLastActivityTime()|time}]]></item>
+               <item name="wcf.user.security.deleteSession"><![CDATA[Sitzung beenden]]></item>
+               <item name="wcf.user.security.deleteSession.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} die Sitzung wirklich beenden?]]></item>
+       </category>
        <category name="wcf.user.trophy">
                <item name="wcf.user.trophy.trophyPoints"><![CDATA[Trophäen]]></item>
                <item name="wcf.user.trophy.showTrophies"><![CDATA[Trophäen von {$user->username} anzeigen]]></item>
index b05416d05209f9d5d6fad37a54c66f5f56692e3a..659a52c14023940f31f8121ad19f146196d1408a 100644 (file)
@@ -4819,6 +4819,13 @@ Open the link below to access the user profile:
 <p><small><em>Source: <a href="http://www.mustervorlage.net/disclaimer-muster" class="externalURL">Mustervorlage.net</a></em></small></p>]]></item>
                <item name="wcf.user.register.error.blacklistMatches"><![CDATA[The registration could not be completed due to active restrictions, please contact the site administrator.]]></item>
        </category>
+       <category name="wcf.user.security">
+               <item name="wcf.user.security.activeSessions"><![CDATA[Active Sessions]]></item>
+               <item name="wcf.user.security.currentSession"><![CDATA[Current Session]]></item>
+               <item name="wcf.user.security.sessionLastActive"><![CDATA[Last active: {@$session->getLastActivityTime()|time}]]></item>
+               <item name="wcf.user.security.deleteSession"><![CDATA[Revoke Session]]></item>
+               <item name="wcf.user.security.deleteSession.confirmMessage"><![CDATA[Do you really want to revoke the session?]]></item>
+       </category>
        <category name="wcf.user.trophy">
                <item name="wcf.user.trophy.trophyPoints"><![CDATA[Trophies]]></item>
                <item name="wcf.user.trophy.showTrophies"><![CDATA[Display Trophies of {$user->username}]]></item>