Browse Source

Completed account switching functions

Toby Chui 2 years ago
parent
commit
09d7a4e0eb

+ 29 - 2
mod/auth/accountSwitch.go

@@ -3,6 +3,7 @@ package auth
 import (
 	"encoding/json"
 	"errors"
+	"fmt"
 	"net/http"
 	"time"
 
@@ -224,10 +225,11 @@ func (m *SwitchableAccountPoolManager) GetAllPools() ([]*SwitchableAccountsPool,
 	}
 	for _, keypairs := range entries {
 		//thisPoolID := string(keypairs[0])
-		thisPool := new(SwitchableAccountsPool)
+		thisPool := SwitchableAccountsPool{}
 		err = json.Unmarshal(keypairs[1], &thisPool)
 		if err == nil {
-			results = append(results, thisPool)
+			thisPool.parent = m
+			results = append(results, &thisPool)
 		}
 	}
 
@@ -260,6 +262,21 @@ func (p *SwitchableAccountPoolManager) RemoveUserFromAllSwitchableAccountPool(us
 	return nil
 }
 
+func (p *SwitchableAccountPoolManager) ExpireUserFromAllSwitchableAccountPool(username string) error {
+	allAccountPool, err := p.GetAllPools()
+	if err != nil {
+		return err
+	}
+	for _, accountPool := range allAccountPool {
+		fmt.Println(allAccountPool)
+		if accountPool.IsAccessibleBy(username) {
+			//aka this user is in the pool
+			accountPool.ExpireUser(username)
+		}
+	}
+	return nil
+}
+
 /*
 	Switachable Account Pool functions
 */
@@ -323,6 +340,16 @@ func (p *SwitchableAccountsPool) UpdateUserPoolAccountInfo(username string) {
 	}
 }
 
+// Expire the session of a user manually
+func (p *SwitchableAccountsPool) ExpireUser(username string) {
+	for _, acc := range p.Accounts {
+		if acc.Username == username {
+			acc.LastSwitch = 0
+		}
+	}
+	p.Save()
+}
+
 // Remove a user from the pool
 func (p *SwitchableAccountsPool) RemoveUser(username string) {
 	newAccountList := []*SwitchableAccount{}

+ 2 - 0
mod/auth/auth.go

@@ -551,11 +551,13 @@ func (a *AuthAgent) UpdateSessionExpireTime(w http.ResponseWriter, r *http.Reque
 // Create user account
 func (a *AuthAgent) CreateUserAccount(newusername string, password string, group []string) error {
 	key := newusername
+
 	hashedPassword := Hash(password)
 	err := a.Database.Write("auth", "passhash/"+key, hashedPassword)
 	if err != nil {
 		return err
 	}
+
 	//Store this user's usergroup settings
 	err = a.Database.Write("auth", "group/"+newusername, group)
 	if err != nil {

+ 6 - 2
user.go

@@ -88,7 +88,7 @@ func UserSystemInit() {
 	adminRouter.HandleFunc("/system/users/removeUser", user_handleUserRemove)
 }
 
-//Remove a user from the system
+// Remove a user from the system
 func user_handleUserRemove(w http.ResponseWriter, r *http.Request) {
 	username, err := utils.PostPara(r, "username")
 	if err != nil {
@@ -279,7 +279,7 @@ func user_handleUserEdit(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
-//Get the user interface info for the user to launch into
+// Get the user interface info for the user to launch into
 func user_getInterfaceInfo(w http.ResponseWriter, r *http.Request) {
 	userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
 	if err != nil {
@@ -349,6 +349,10 @@ func user_handleUserInfo(w http.ResponseWriter, r *http.Request) {
 			utils.SendErrorResponse(w, "Invalid old password.")
 			return
 		}
+
+		//Logout users from all switchable accounts
+		authAgent.SwitchableAccountManager.ExpireUserFromAllSwitchableAccountPool(username)
+
 		//OK! Change user password
 		newHashedPassword := auth.Hash(newpw)
 		sysdb.Write("auth", "passhash/"+username, newHashedPassword)

+ 35 - 18
web/SystemAO/advance/switchAccount.html

@@ -9,6 +9,7 @@
     <script type="application/javascript" src="../../script/jquery.min.js"></script>
     <script type="application/javascript" src="../../script/ao_module.js"></script>
     <script type="application/javascript" src="../../script/semantic/semantic.js"></script>
+    <script type="text/javascript" src="../../script/applocale.js"></script>
     <style>
         body{
             background-color: rgb(240, 240, 240);
@@ -36,9 +37,9 @@
     <div class="ui container" align="center">
         <div class="ui segment" style="max-width:400px;" align="left">
             <!-- Current In Use Account -->
-            <p>Current account</p>
+            <p locale="desc/currentAccount">Current account</p>
             <div class="ui small basic right floated button" onclick="logout();">
-                <i class="log out icon"></i> <span locale="quickAccess/logout">Logout</span>
+                <i class="log out icon"></i> <span locale="button/logout">Logout</span>
             </div>
             <div class="ui header">
                 <img id="currentUserIcon" src="/images/icons/plugin.png">
@@ -49,30 +50,30 @@
             </div>
            
             <div class="ui divider"></div>
-            <p>Saved accounts on this browser</p>
+            <p locale="desc/savedAccount">Saved accounts on this browser</p>
             <div id="alternativeAccountList">
 
             </div>
             
             
             <div style="margin-top: 1em !important;">
-                <div id="signoutAllButton" class="ui fluid small black basic button" onclick="logoutAllAccounts();"><i class="log out icon icon"></i> Sign-out all accounts</div>
+                <div id="signoutAllButton" class="ui fluid small black basic button" onclick="logoutAllAccounts();"><i class="log out icon icon"></i> <span locale="desc/signoutAll">Sign-out all accounts</span></div>
             </div>
             <div class="ui divider"></div>
-                <p>Sign-in to new account</p>
+                <p locale="desc/sign-in-new">Sign-in to new account</p>
             <form class="ui form" onsubmit="handleFormSubmit(event, this);">
                 <div class="field">
-                    <label>Username</label>
+                    <label locale="desc/username">Username</label>
                     <input id="username" type="text" name="username" value="">
                 </div>
                 <div class="field">
-                    <label>Password</label>
+                    <label locale="desc/password">Password</label>
                     <input id="magic" type="password" name="magic">
                 </div>
-                <button id="submitbtn" class="ui basic button"><i class="ui green sign in icon"></i> Login</button>
+                <button id="submitbtn" class="ui basic button"><i class="ui green sign in icon"></i> <span locale="desc/addAccount">Add Local Account</span></button>
             </form>
             <div id="restoreSessionMessage" class="ui blue inverted segment" style="display:none;">
-                <span>Enter password to resume session</span>
+                <span locale="desc/enterPassword">Enter password to resume session</span>
             </div>
             <div id="errmsg" class="ui red inverted segment" style="display:none;">
                 <i class="remove icon"></i> <span id="errtext">Internal Server Error</span>
@@ -88,6 +89,26 @@
         let currentUserInfo = {};
         let browserAccountPoolUUID = localStorage.getItem("ao_acc");
 
+        //Initalized localization
+        if (typeof(applocale) != "undefined"){
+            applocale.init("../../SystemAO/locale/switchAccount.json", function(){
+                applocale.translate();
+                initCurrentAccountInfo(function(){
+                    listAllStoredAccounts();
+                });
+            });
+        }else{
+            //Applocale not found
+            var applocale = {};
+            applocale.getString = function(key, defaultString){
+                return defaultString;
+            }
+
+            initCurrentAccountInfo(function(){
+                listAllStoredAccounts();
+            });
+        }
+
         function handleFormSubmit(event, form){
             event.preventDefault();
 
@@ -164,7 +185,7 @@
         }
 
         function logoutAllAccounts(){
-            if (confirm("This will logout all other accounts from this browser. Confirm?")){
+            if (confirm(applocale.getString("msg/logout/confirm", "This will logout all other accounts from this browser. Confirm?"))){
                 $.ajax({
                     url: "/system/auth/u/logoutAll",
                     data: {pid: browserAccountPoolUUID},
@@ -200,7 +221,7 @@
             if (browserAccountPoolUUID == undefined){
                  //Empty or no stored accounts
                  $("#alternativeAccountList").append(`<div class="ui message">
-                    <i class="ui green check circle icon"></i> No other account stored on this browser
+                    <i class="ui green check circle icon"></i> ${applocale.getString("desc/noAlternative", "No other account stored on this browser")}
                 </div>`);
                 $("#signoutAllButton").addClass('disabled');
                 return;
@@ -228,7 +249,7 @@
                                                 <img class="usericon" src="${userIcon}">
                                                 <div class="content" style="font-size: 95% !important;">
                                                     <span class="username">${account.Username}</span> ${(data.IsAdmin)?'<i style="margin-left: 0.4em; color: rgb(38, 50, 56);" title="Admin" class="small shield alternate icon themed text"></i>':""}
-                                                    <div class="sub header usergroup">${!account.IsExpired?"<i class='ui green check circle icon' style='margin-right: 0px;'></i> Session Valid":"<i class='ui red times circle icon' style='margin-right: 0px;'></i> Session Expired"}</div>
+                                                    <div class="sub header usergroup">${!account.IsExpired?"<i class='ui green check circle icon' style='margin-right: 0px;'></i> " + applocale.getString("desc/sessionValid", "Session Valid"):"<i class='ui red times circle icon' style='margin-right: 0px;'></i> " + applocale.getString("desc/sessionExpired", "Session Expired")}</div>
                                                 </div>
                                             </div>
                                         </div>
@@ -239,7 +260,7 @@
                         }else{
                             $("#signoutAllButton").addClass('disabled');
                             $("#alternativeAccountList").append(`<div class="ui message">
-                                <i class="ui green check circle icon"></i> No other account stored on this browser
+                                <i class="ui green check circle icon"></i> ${applocale.getString("desc/noAlternative", "No other account stored on this browser")}
                             </div>`);
                             return;
                         }
@@ -282,13 +303,9 @@
             });
         }
 
-        initCurrentAccountInfo(function(){
-            listAllStoredAccounts();
-        });
-
         function logout() {
             loggingOut = true;
-            if (confirm("Exiting Session. Confirm?")){
+            if (confirm(applocale.getString("msg/logout/thisAcConfirm", "Exiting Session. Confirm?"))){
                 $.get("../../system/auth/logout", function() {
                     window.location.href = "./";
                 });

BIN
web/SystemAO/desktop/img/account-switch.png


BIN
web/SystemAO/desktop/img/account-switch.psd


BIN
web/SystemAO/desktop/img/baseline_brush_black_48dp.png


BIN
web/SystemAO/desktop/img/switch_account_FILL0_wght400_GRAD0_opsz48.png


+ 38 - 1
web/SystemAO/locale/desktop.json

@@ -96,7 +96,16 @@
                 "power/restart/text":"重啟伺服器主機",
                 "power/restart/instruction":"請輸入你的管理員密碼以確認重啟伺服器",
 
+                "account/switch/logout/confirm":"確認登出所有其他儲存在本瀏覽器的帳戶?",
+                "account/switch/noAlternative":"此瀏覽器上沒有儲存其他帳戶",
+                "account/switch/sessionValid":"登錄狀態可用",
+                "account/switch/sessionExpired":"登錄狀態已過期",
+                "account/switch/addAccount":"新增本機帳戶",
+                "account/switch/signoutAll":"登出其他已儲存的帳戶",
+
                 "upload/message/uploading": "上載中…",
+                "upload/message/failed": "上載失敗",
+
                 "":""
             },
             "placeholder":{
@@ -194,6 +203,13 @@
                 "power/restart/title":"重新啟動 - 輸入密碼以作確認",
                 "power/restart/text":"重啟伺服器主機",
                 "power/restart/instruction":"請輸入你的管理員密碼以確認重啟伺服器",
+                
+                "account/switch/logout/confirm":"確認登出所有其他儲存在本瀏覽器的帳戶?",
+                "account/switch/noAlternative":"此瀏覽器上沒有儲存其他帳戶",
+                "account/switch/sessionValid":"登錄狀態可用",
+                "account/switch/sessionExpired":"登錄狀態已過期",
+                "account/switch/addAccount":"新增本機帳戶",
+                "account/switch/signoutAll":"登出其他已儲存的帳戶",
 
                 "upload/message/uploading": "上載中…",
                 "upload/message/failed": "上載失敗",
@@ -295,6 +311,13 @@
                 "power/restart/text":"服务器重启",
                 "power/restart/instruction":"请输入你的管理员密码以确认重启服务器",
 
+                "account/switch/logout/confirm": "确认登出所有其他储存在本浏览器的帐户?",
+                "account/switch/noAlternative": "此浏览器上没有储存其他帐户",
+                "account/switch/sessionValid": "登录状态可用",
+                "account/switch/sessionExpired": "登录状态已过期",
+                "account/switch/addAccount": "新增本机帐户",
+                "account/switch/signoutAll": "登出其他已储存的帐户",
+
                 "upload/message/uploading": "上传中…",
                 "upload/message/failed": "上传失败",
                 "":""
@@ -395,7 +418,14 @@
                 "power/restart/title": "Restart - Enter Password to Confirm",
                 "power/restart/text": "Restart server",
                 "power/restart/instruction": "Enter your admin password to continue server restart.",
-    
+                
+                "account/switch/logout/confirm": "Confirm Logout from All Other Accounts Stored in this Browser?",
+                "account/switch/noAlternative": "No Other Logged-in Accounts Found on this Browser",
+                "account/switch/sessionValid": "Session Valid",
+                "account/switch/sessionExpired": "Session Expired",
+                "account/switch/addAccount": "Add another account",
+                "account/switch/signoutAll": "Sign-out all accounts",
+
                 "upload/message/uploading": "Uploading...",
                 "":""
             },
@@ -496,6 +526,13 @@
                 "power/restart/title": "再起動 - パスワードを入力して確認してください",
                 "power/restart/text": "サーバーを再起動します",
                 "power/restart/instruction": "サーバーの再起動を確認するには、管理者パスワードを入力してください。",
+                
+                "account/switch/logout/confirm": "このブラウザに保存されている他のすべてのアカウントからログアウトしますか?",
+                "account/switch/noAlternative": "このブラウザで他のログイン中のアカウントは見つかりません",
+                "account/switch/sessionValid": "セッションが有効です",
+                "account/switch/sessionExpired": "セッションが期限切れです",
+                "account/switch/addAccount": "別のアカウントを追加",
+                "account/switch/signoutAll": "すべてのアカウントからサインアウト",
 
                 "upload/message/uploading": "アップロード中...",
                 "":""

+ 148 - 0
web/SystemAO/locale/switchAccount.json

@@ -0,0 +1,148 @@
+{
+    "author": "tobychui",
+    "version": "1.0",
+    "keys": {
+        "zh-tw": {
+            "fwtitle" : "帳戶切換管理員",
+            "strings":{
+                "desc/currentAccount":"使用中的帳戶",
+                "desc/savedAccount":"已在此瀏覽器登入之帳戶",
+                "desc/sign-in-new":"切換至其他帳戶",
+                "desc/username":"用戶名稱",
+                "desc/password":"密碼",
+                "desc/enterPassword":"輸入密碼以恢復階段",
+                "desc/switchAccount": "切換帳戶",
+                "desc/noAlternative":"此瀏覽器上沒有儲存其他帳戶",
+                "desc/sessionValid":"登錄狀態可用",
+                "desc/sessionExpired":"登錄狀態已過期",
+                "desc/addAccount":"新增本機帳戶",
+                "desc/signoutAll":"登出其他已儲存的帳戶",
+                
+                "msg/logout/confirm":"確認登出所有其他儲存在本瀏覽器的帳戶?",
+                "msg/logout/thisAcConfirm": "確認登出本帳戶?",
+                "button/login":"登入",
+                "button/logout":"登出",
+
+
+                "":""
+            },
+            "titles":{
+
+            },
+            "placeholder":{
+
+            }
+        },
+        "zh-hk": {
+            "fwtitle" : "帳戶切換管理員",
+            "strings":{
+                "desc/currentAccount":"使用中的帳戶",
+                "desc/savedAccount":"已在此瀏覽器登入之帳戶",
+                "desc/sign-in-new":"切換至其他帳戶",
+                "desc/username":"用戶名稱",
+                "desc/password":"密碼",
+                "desc/enterPassword":"輸入密碼以恢復階段",
+                "desc/switchAccount": "切換帳戶",
+                "desc/noAlternative":"此瀏覽器上沒有儲存其他帳戶",
+                "desc/sessionValid":"登錄狀態可用",
+                "desc/sessionExpired":"登錄狀態已過期",
+                "desc/addAccount":"新增本機帳戶",
+                "desc/signoutAll":"登出其他已儲存的帳戶",
+
+                "msg/logout/confirm":"確認登出所有其他儲存在本瀏覽器的帳戶?",
+                "msg/logout/thisAcConfirm": "確認登出本帳戶?",
+                "button/login":"登入",
+                "button/logout":"登出",
+                "":""
+            },
+            "titles":{
+
+            },
+            "placeholder":{
+
+            }
+        },
+        "zh-cn": {
+            "fwtitle" : "帐户切换管理员",
+            "strings":{
+                "desc/currentAccount":"使用中的帐户",
+                "desc/savedAccount":"已在此浏览器登入之帐户",
+                "desc/sign-in-new":"切换至其他帐户",
+                "desc/username":"用户名称",
+                "desc/password":"密码",
+                "desc/enterPassword":"输入密码以恢复阶段",
+                "desc/switchAccount": "切换帐户",
+                "desc/noAlternative":"此浏览器上没有储存其他帐户",
+                "desc/sessionValid":"登录状态可用",
+                "desc/sessionExpired":"登录状态已过期",
+                "desc/addAccount":"新增本机帐户",
+                "desc/signoutAll":"登出其他已储存的帐户",
+
+                "msg/logout/confirm":"确认登出所有其他储存在本浏览器的帐户?",
+                "msg/logout/thisAcConfirm": "确认登出本帐户?",
+                "button/login":"登入",
+                "button/logout":"登出",
+                "":""
+            },
+            "titles":{
+
+            },
+            "placeholder":{
+
+            }
+        },
+        "en-us": {
+            "fwtitle" : "Account Manager",
+            "strings":{
+                "desc/currentAccount": "Current Account",
+                "desc/savedAccount": "Saved accounts on this browser",
+                "desc/sign-in-new":"Sign-in to new account",
+                "desc/username": "Username",
+                "desc/password": "Password",
+                "desc/enterPassword": "Enter password to resume session",
+                "desc/switchAccount": "Add Local Account",
+                "desc/noAlternative":"No other account stored on this browser",
+                "desc/sessionValid": "Session Valid",
+                "desc/sessionExpired": "Session Expired",
+                "desc/addAccount": "Add local account",
+                "desc/signoutAll":"Sign out other saved accounts",
+
+                "msg/logout/confirm": "This will logout all other accounts from this browser. Confirm?",
+                "msg/logout/thisAcConfirm": "Exiting Session. Confirm?",
+                "button/login": "login",
+                "button/logout": "Logout",
+                "":""
+            },
+            "titles":{
+
+            },
+            "placeholder":{
+
+            }
+        },
+        "ja-jp":{
+            "name":"日本語",
+            "fwtitle" : "アカウントマネージャー",
+            "fontFamily":"\"Meiryo UI\", \"Arial Unicode MS\", \"Hiragino Kaku Gothic Pro\"",
+            "strings":{
+                "desc/currentAccount": "現在のアカウント",
+                "desc/savedAccount": "このブラウザに保存されたアカウント",
+                "desc/sign-in-new":"新しいアカウントにサインイン",
+                "desc/username": "ユーザー名",
+                "desc/password": "パスワード",
+                "desc/enterPassword": "セッションを再開するためにパスワードを入力してください",
+                "desc/switchAccount": "ローカルアカウントを追加",
+                "desc/noAlternative":"このブラウザに他のアカウントは保存されていません",
+                "desc/sessionValid": "セッション有効",
+                "desc/sessionExpired": "セッションの有効期限が切れました",
+                "desc/addAccount": "ローカルアカウントを追加",
+                "desc/signoutAll":"他の保存されたアカウントからログアウト",
+
+                "msg/logout/confirm": "これにより、このブラウザから他のすべてのアカウントがログアウトされます。確認しますか?",
+                "msg/logout/thisAcConfirm": "セッションを終了します。確認しますか?",
+                "button/login": "ログイン",
+                "button/logout": "ログアウト"
+            }   
+        }
+    }
+}

+ 4 - 1
web/SystemAO/locale/template.json

@@ -3,6 +3,7 @@
     "version": "1.0",
     "keys": {
         "zh-tw": {
+            "name": "繁體中文(台灣)",
             "fwtitle" : "",
             "strings":{
 
@@ -15,6 +16,7 @@
             }
         },
         "zh-hk": {
+            "name": "繁體中文(香港)",
             "fwtitle" : "",
             "strings":{
 
@@ -27,9 +29,10 @@
             }
         },
         "zh-cn": {
+            "name": "简体中文(简体)",
             "fwtitle" : "",
             "strings":{
-
+                
             },
             "titles":{
 

+ 26 - 20
web/desktop.system

@@ -601,7 +601,7 @@
         }
 
         .qtwrapper.backgroundtask i{
-            margin-top: -1px;
+            margin-top: -5px;
             margin-right: 1px;
         }
 
@@ -811,6 +811,10 @@
            color: var(--text_color);
         }
 
+        body.darkTheme #quickAccessPanel .ui.basic.button{
+            color: var(--text_color_secondary) !important;
+        }
+
         .item.module{
             cursor:pointer;
         }
@@ -1207,7 +1211,7 @@
             </div>
             <div class="ui divider"></div>
             <div class="item" style="padding-left: 8px;">
-                <div id="alternativeAccountList" class="ui small items" style="margin-bottom: 0; width: 100%;">
+                <div id="alternativeAccountList" class="ui small items" style="margin-bottom: 0; padding-bottom: 8px; width: 100%;">
                     <div class="alternativeUsableAccount item"  style="padding-left: 0px;">
                         <div class="ui mini image">
                             <img class="accountIcon" src="img/desktop/system_icon/user.svg">
@@ -1221,15 +1225,12 @@
                     </div>
                 </div>
             </div>
-            <div class="item" style="cursor: auto;">
-                <div class="ui small items" style="margin-bottom: 0; width: 100%;cursor: auto;">
-                    <div class="item" style="margin-bottom: 0px !important;">
-                        <div class="ui fluid small basic button" onclick="openSwitchAccountPanel(); hideToolPanel();"><i class="ui user plus icon"></i> Add another account</div>
-                    </div>
-                    <div class="item" style="margin-top: 0px !important;">
-                        <div id="signoutAllButton" class="ui fluid small black basic button" onclick="logoutAllAccounts();"><i class="log out icon icon"></i> Sign-out all accounts</div>
-                    </div>
-                </div>
+            <div class="ui divider" style="margin-left: 2em; margin-right: 2em;"></div>
+            <div class="item" style="padding-top: 6px; padding-bottom:6px; margin: 0px !important;" onclick="openSwitchAccountPanel(); hideToolPanel();">
+                <i class="ui user plus icon" style="margin-right: 0.6em;"></i> <span locale="account/switch/addAccount">Add another account</span>
+            </div>
+            <div id="signoutAllButton" style="padding-top: 6px; padding-bottom:6px; margin: 0px !important;" class="item" onclick="logoutAllAccounts();">
+                <i class="log out icon icon" style="margin-right: 0.6em;"></i> <span locale="account/switch/signoutAll">Sign-out all accounts</span>
             </div>
             <div class="ui divider"></div>
         </div>
@@ -1352,7 +1353,7 @@
         var isTouchScreen = window.matchMedia("(any-pointer: coarse)").matches;
 
         //Check and prepare localization
-        if (applocale){
+        if (typeof(applocale) != "undefined"){
             //Applocale found. Do localization
             applocale.init("./SystemAO/locale/desktop.json", function(){
                 applocale.translate();
@@ -1678,6 +1679,8 @@
                     $("#usergroups").attr("title",userInfo.UserGroups.join(" / "));
                     if (data.UserIcon !== ""){
                         $(".usericon").attr("src",data.UserIcon);
+                    }else{
+                        $(".usericon").attr("src", "img/desktop/system_icon/user.svg")
                     }
 
                     if (data.IsAdmin == false){
@@ -5147,7 +5150,7 @@
                 url: 'SystemAO/advance/switchAccount.html',
                 width: 470,
                 height: 680,
-                appicon: "",
+                appicon: "SystemAO/desktop/img/account-switch.png",
                 title: "Switch Account"
             });
         }
@@ -6888,6 +6891,8 @@
                 $.get("system/file_system/preference?key=file_explorer/theme", function(data){
                     if (data == "darkTheme"){
                         setDarkTheme();
+                    }else{
+                        setWhiteTheme();
                     }
                 });
             }else{
@@ -7264,7 +7269,7 @@
             if (getBrowserAccountPoolUUID() == undefined){
                  //Empty or no stored accounts
                  $("#alternativeAccountList").append(`<div class="ui message">
-                    <i class="ui green check circle icon"></i> No other account stored on this browser
+                    <i class="ui green check circle icon"></i> ${applocale.getString("account/switch/noAlternative", "No other account stored on this browser")}
                 </div>`);
                 $("#signoutAllButton").addClass('disabled');
                 return;
@@ -7273,7 +7278,7 @@
                 $.get("system/auth/u/list?pid=" + getBrowserAccountPoolUUID(), function(data){
                     if (data.error != undefined){
                         $("#alternativeAccountList").append(`<div class="ui message">
-                            <i class="ui green check circle icon"></i> No other account stored on this browser
+                            <i class="ui green check circle icon"></i> ${applocale.getString("account/switch/noAlternative", "No other account stored on this browser")}
                         </div>`);
                     }else{
                         if (data.length > 0){
@@ -7289,12 +7294,12 @@
                                         userIcon = "img/desktop/system_icon/user.svg"
                                     }
                                     $("#alternativeAccountList").append(`
-                                        <div class="alternativeAccount ${account.IsExpired?"expired":""}" acname="${account.Username}" onclick="switchAccount(this);" style="margin-top: 0.4em;">
+                                        <div class="alternativeAccount ${account.IsExpired?"expired":""}" acname="${account.Username}" onclick="switchAccount(this);" style="margin-top: 0.6em;">
                                             <div class="ui header">
-                                                <img class="usericon" src="${userIcon}">
+                                                <img class="usericon ui circular image" src="${userIcon}">
                                                 <div class="content" style="font-size: 95% !important;">
                                                     <span class="username">${account.Username}</span> ${(data.IsAdmin)?'<i style="margin-left: 0.4em; color: rgb(38, 50, 56);" title="Admin" class="small shield alternate icon themed text"></i>':""}
-                                                    <div class="sub header usergroup">${!account.IsExpired?"<i class='ui green check circle icon' style='margin-right: 0px;'></i> Session Valid":"<i class='ui red times circle icon' style='margin-right: 0px;'></i> Session Expired"}</div>
+                                                    <div class="sub header usergroup">${!account.IsExpired?"<i class='ui green check circle icon' style='margin-right: 0px;'></i> " + applocale.getString("account/switch/sessionValid", "Session Valid"):"<i class='ui red times circle icon' style='margin-right: 0px;'></i> " + applocale.getString("account/switch/sessionExpired", "Session Expired")}</div>
                                                 </div>
                                             </div>
                                         </div>
@@ -7305,7 +7310,7 @@
                         }else{
                             $("#signoutAllButton").addClass('disabled');
                             $("#alternativeAccountList").append(`<div class="ui message">
-                                <i class="ui green check circle icon"></i> No other account stored on this browser
+                                <i class="ui green check circle icon"></i> ${applocale.getString("account/switch/noAlternative", "No other account stored on this browser")}
                             </div>`);
                             return;
                         }
@@ -7344,7 +7349,7 @@
         }
 
         function logoutAllAccounts(){
-            if (confirm("This will logout all other accounts from this browser. Confirm?")){
+            if (confirm(applocale.getString("account/switch/logout/confirm", "This will logout all other accounts from this browser. Confirm?"))){
                 $.ajax({
                     url: "system/auth/u/logoutAll",
                     data: {pid: getBrowserAccountPoolUUID()},
@@ -7355,6 +7360,7 @@
                             //Reset the browser pool id
                             localStorage.removeItem("ao_acc");
                             listAllStoredAccounts();
+                            hideToolPanel();
                         }
                     }
                 })