mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-19 18:13:41 -05:00
main: add support for logging out
This commit is contained in:
parent
74439be24c
commit
529ffda4ed
12 changed files with 130 additions and 5 deletions
|
@ -148,9 +148,9 @@ func main() {
|
|||
URL: "/",
|
||||
})
|
||||
|
||||
gmx.Client.EventHandler = hicli.JSONEventHandler(func(command *hicli.JSONCommand) {
|
||||
gmx.SubscribeEvents(nil, func(command *hicli.JSONCommand) {
|
||||
app.EmitEvent("hicli_event", command)
|
||||
}).HandleEvent
|
||||
})
|
||||
|
||||
err = app.Run()
|
||||
if err != nil {
|
||||
|
|
|
@ -178,6 +178,7 @@ func (gmx *Gomuks) StartClient() {
|
|||
[]byte("meow"),
|
||||
hicli.JSONEventHandler(gmx.OnEvent).HandleEvent,
|
||||
)
|
||||
gmx.Client.LogoutFunc = gmx.Logout
|
||||
httpClient := gmx.Client.Client.Client
|
||||
httpClient.Transport.(*http.Transport).ForceAttemptHTTP2 = false
|
||||
if !gmx.Config.Matrix.DisableHTTP2 {
|
||||
|
@ -246,7 +247,9 @@ func (gmx *Gomuks) SubscribeEvents(closeForRestart WebsocketCloseFunc, cb func(c
|
|||
gmx.nextListenerID++
|
||||
id := gmx.nextListenerID
|
||||
gmx.eventListeners[id] = cb
|
||||
gmx.websocketClosers[id] = closeForRestart
|
||||
if closeForRestart != nil {
|
||||
gmx.websocketClosers[id] = closeForRestart
|
||||
}
|
||||
return func() {
|
||||
gmx.eventListenersLock.Lock()
|
||||
defer gmx.eventListenersLock.Unlock()
|
||||
|
|
64
pkg/gomuks/logout.go
Normal file
64
pkg/gomuks/logout.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
// gomuks - A Matrix client written in Go.
|
||||
// Copyright (C) 2024 Tulir Asokan
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package gomuks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"maunium.net/go/mautrix"
|
||||
)
|
||||
|
||||
func (gmx *Gomuks) Logout(ctx context.Context) error {
|
||||
log := zerolog.Ctx(ctx)
|
||||
log.Info().Msg("Stopping client and logging out")
|
||||
gmx.Client.Stop()
|
||||
_, err := gmx.Client.Client.Logout(ctx)
|
||||
if err != nil && !errors.Is(err, mautrix.MUnknownToken) {
|
||||
log.Warn().Err(err).Msg("Failed to log out")
|
||||
return err
|
||||
}
|
||||
log.Info().Msg("Logout complete, removing data")
|
||||
err = os.RemoveAll(gmx.CacheDir)
|
||||
if err != nil {
|
||||
log.Err(err).Str("cache_dir", gmx.CacheDir).Msg("Failed to remove cache dir")
|
||||
}
|
||||
if gmx.DataDir == gmx.ConfigDir {
|
||||
err = os.Remove(filepath.Join(gmx.DataDir, "gomuks.db"))
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
log.Err(err).Str("data_dir", gmx.DataDir).Msg("Failed to remove database")
|
||||
}
|
||||
_ = os.Remove(filepath.Join(gmx.DataDir, "gomuks.db-shm"))
|
||||
_ = os.Remove(filepath.Join(gmx.DataDir, "gomuks.db-wal"))
|
||||
} else {
|
||||
err = os.RemoveAll(gmx.DataDir)
|
||||
if err != nil {
|
||||
log.Err(err).Str("data_dir", gmx.DataDir).Msg("Failed to remove data dir")
|
||||
}
|
||||
}
|
||||
log.Info().Msg("Re-initializing directories")
|
||||
gmx.InitDirectories()
|
||||
log.Info().Msg("Restarting client")
|
||||
gmx.StartClient()
|
||||
gmx.Client.EventHandler(gmx.Client.State())
|
||||
gmx.Client.EventHandler(gmx.Client.SyncStatus.Load())
|
||||
log.Info().Msg("Client restarted")
|
||||
return nil
|
||||
}
|
|
@ -32,6 +32,7 @@ import (
|
|||
|
||||
type HiClient struct {
|
||||
DB *database.Database
|
||||
CryptoDB *dbutil.Database
|
||||
Account *database.Account
|
||||
Client *mautrix.Client
|
||||
Crypto *crypto.OlmMachine
|
||||
|
@ -50,6 +51,7 @@ type HiClient struct {
|
|||
lastSync time.Time
|
||||
|
||||
EventHandler func(evt any)
|
||||
LogoutFunc func(context.Context) error
|
||||
|
||||
firstSyncReceived bool
|
||||
syncingID int
|
||||
|
@ -90,6 +92,9 @@ func New(rawDB, cryptoDB *dbutil.Database, log zerolog.Logger, pickleKey []byte,
|
|||
|
||||
EventHandler: evtHandler,
|
||||
}
|
||||
if cryptoDB != rawDB {
|
||||
c.CryptoDB = cryptoDB
|
||||
}
|
||||
c.SyncStatus.Store(syncWaiting)
|
||||
c.ClientStore = &database.ClientStateStore{Database: db}
|
||||
c.Client = &mautrix.Client{
|
||||
|
@ -267,4 +272,10 @@ func (h *HiClient) Stop() {
|
|||
if err != nil {
|
||||
h.Log.Err(err).Msg("Failed to close database cleanly")
|
||||
}
|
||||
if h.CryptoDB != nil {
|
||||
err = h.CryptoDB.Close()
|
||||
if err != nil {
|
||||
h.Log.Err(err).Msg("Failed to close crypto database cleanly")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,6 +114,11 @@ func (h *HiClient) handleJSONCommand(ctx context.Context, req *JSONCommand) (any
|
|||
return unmarshalAndCall(req.Data, func(params *resolveAliasParams) (*mautrix.RespAliasResolve, error) {
|
||||
return h.Client.ResolveAlias(ctx, params.Alias)
|
||||
})
|
||||
case "logout":
|
||||
if h.LogoutFunc == nil {
|
||||
return nil, errors.New("logout not supported")
|
||||
}
|
||||
return true, h.LogoutFunc(ctx)
|
||||
case "login":
|
||||
return unmarshalAndCall(req.Data, func(params *loginParams) (bool, error) {
|
||||
return true, h.LoginPassword(ctx, params.HomeserverURL, params.Username, params.Password)
|
||||
|
|
|
@ -293,4 +293,10 @@ export default class Client {
|
|||
room.paginating = false
|
||||
}
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await this.rpc.logout()
|
||||
localStorage.clear()
|
||||
this.store.clear()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,10 @@ export default abstract class RPCClient {
|
|||
}, this.cancelRequest.bind(this, request_id))
|
||||
}
|
||||
|
||||
logout(): Promise<boolean> {
|
||||
return this.request("logout", {})
|
||||
}
|
||||
|
||||
sendMessage(params: SendMessageParams): Promise<RawDBEvent> {
|
||||
return this.request("send_message", params)
|
||||
}
|
||||
|
|
|
@ -386,4 +386,17 @@ export class StateStore {
|
|||
}
|
||||
return { deletedEvents, deletedState } as const
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.rooms.clear()
|
||||
this.roomList.emit([])
|
||||
this.accountData.clear()
|
||||
this.currentRoomListFilter = ""
|
||||
this.#frequentlyUsedEmoji = null
|
||||
this.#emojiPackKeys = null
|
||||
this.#watchedRoomEmojiPacks = null
|
||||
this.#personalEmojiPack = null
|
||||
this.serverPreferenceCache = {}
|
||||
this.activeRoomID = undefined
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ const BeeperLogin = ({ domain, client }: BeeperLoginProps) => {
|
|||
onChange={onChangeCode}
|
||||
/>}
|
||||
<button
|
||||
className="beeper-login-button"
|
||||
className="beeper-login-button primary-color-button"
|
||||
type="submit"
|
||||
>{requestID ? "Submit Code" : "Request Code"}</button>
|
||||
{error && <div className="error">
|
||||
|
|
|
@ -44,7 +44,7 @@ export const VerificationScreen = ({ client, clientState }: LoginScreenProps) =>
|
|||
value={recoveryKey}
|
||||
onChange={evt => setRecoveryKey(evt.target.value)}
|
||||
/>
|
||||
<button className="mx-login-button" type="submit">Verify</button>
|
||||
<button className="mx-login-button primary-color-button" type="submit">Verify</button>
|
||||
</form>
|
||||
{error && <div className="error">
|
||||
{error}
|
||||
|
|
|
@ -72,4 +72,14 @@ div.settings-view {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.logout {
|
||||
margin-top: 1rem;
|
||||
padding: .5rem 1rem;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: var(--error-color);
|
||||
color: var(--inverted-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,6 +259,14 @@ const SettingsView = ({ room }: SettingsViewProps) => {
|
|||
}
|
||||
}
|
||||
}, [client, room])
|
||||
const onClickLogout = useCallback(() => {
|
||||
if (window.confirm("Really log out and delete all local data?")) {
|
||||
client.logout().then(
|
||||
() => console.info("Successfully logged out"),
|
||||
err => window.alert(`Failed to log out: ${err}`),
|
||||
)
|
||||
}
|
||||
}, [client])
|
||||
usePreferences(client.store, room)
|
||||
const globalServer = client.store.serverPreferenceCache
|
||||
const globalLocal = client.store.localPreferenceCache
|
||||
|
@ -293,6 +301,7 @@ const SettingsView = ({ room }: SettingsViewProps) => {
|
|||
</table>
|
||||
<CustomCSSInput setPref={setPref} room={room} />
|
||||
<AppliedSettingsView room={room} />
|
||||
<button className="logout" onClick={onClickLogout}>Logout</button>
|
||||
</>
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue