From 0d608248c5ccb667bc2f88915bd7ef6012ed6cdc Mon Sep 17 00:00:00 2001 From: Lukasz Janyst Date: Mon, 9 May 2022 15:02:36 +0200 Subject: [PATCH] cleanup: Move the store handling code to the store package Issue #6 --- pkg/store/factory.go | 78 ++++++++++++++++++++++++++++++++++++++++++++ pkg/store/utils.go | 71 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 pkg/store/factory.go create mode 100644 pkg/store/utils.go diff --git a/pkg/store/factory.go b/pkg/store/factory.go new file mode 100644 index 0000000..7fbfcf3 --- /dev/null +++ b/pkg/store/factory.go @@ -0,0 +1,78 @@ +// Copyright (c) 2022 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +package store + +import ( + "fmt" + "path/filepath" + + "github.com/ljanyst/peroxide/pkg/config/settings" + "github.com/ljanyst/peroxide/pkg/listener" + "github.com/ljanyst/peroxide/pkg/message" + "github.com/ljanyst/peroxide/pkg/store/cache" +) + +type StoreFactory struct { + settings *settings.Settings + listener listener.Listener + events *Events + cache cache.Cache + builder *message.Builder +} + +func NewStoreFactory( + settingsObj *settings.Settings, + listener listener.Listener, + cache cache.Cache, + builder *message.Builder, +) *StoreFactory { + eventsCachePath := filepath.Join(settingsObj.Get(settings.CacheDir), "store_events.json") + return &StoreFactory{ + settings: settingsObj, + listener: listener, + events: NewEvents(eventsCachePath), + cache: cache, + builder: builder, + } +} + +// New creates new store for given user. +func (f *StoreFactory) New(user BridgeUser) (*Store, error) { + return New( + user, + f.listener, + f.cache, + f.builder, + getUserStorePath(f.settings.Get(settings.CacheDir), user.ID()), + f.events, + ) +} + +// Remove removes all store files for given user. +func (f *StoreFactory) Remove(userID string) error { + return RemoveStore( + f.events, + getUserStorePath(f.settings.Get(settings.CacheDir), userID), + userID, + ) +} + +// getUserStorePath returns the file path of the store database for the given userID. +func getUserStorePath(storeDir string, userID string) (path string) { + return filepath.Join(storeDir, fmt.Sprintf("mailbox-%v.db", userID)) +} diff --git a/pkg/store/utils.go b/pkg/store/utils.go new file mode 100644 index 0000000..51a5932 --- /dev/null +++ b/pkg/store/utils.go @@ -0,0 +1,71 @@ +// Copyright (c) 2022 Lukasz Janyst +// +// This file is part of Peroxide. +// +// Peroxide is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Peroxide 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Peroxide. If not, see . + +package store + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + + "github.com/ljanyst/peroxide/pkg/files" +) + +const Version = "c11" + +type StoreInfo struct { + StoreVersion string +} + +func recreateStore(storeDir, storeInfoPath string) error { + if err := files.Remove(storeDir).Do(); err != nil { + return err + } + + if err := os.MkdirAll(storeDir, 0700); err != nil { + return err + } + + f, err := os.Create(storeInfoPath) + if err != nil { + return err + } + defer f.Close() + + return json.NewEncoder(f).Encode(StoreInfo{Version}) +} + +func ClearIncompatibleStore(storeDir string) error { + storeInfoPath := filepath.Join(storeDir, "store_info.json") + data, err := ioutil.ReadFile(storeInfoPath) + if err != nil { + return recreateStore(storeDir, storeInfoPath) + } + + var info StoreInfo + if err := json.Unmarshal(data, &info); err != nil { + // Nuke the store if we can't unmarshal the info + return recreateStore(storeDir, storeInfoPath) + } + + if info.StoreVersion != Version { + return recreateStore(storeDir, storeInfoPath) + } + + return nil +}