package storage import ( "cwtch.im/cwtch/event" "cwtch.im/cwtch/model" "cwtch.im/cwtch/storage/v0" "cwtch.im/cwtch/storage/v1" "git.openprivacy.ca/openprivacy/log" "io/ioutil" "path" "strconv" ) const profileFilename = "profile" const versionFile = "VERSION" const currentVersion = 1 // ProfileStore is an interface to managing the storage of Cwtch Profiles type ProfileStore interface { Shutdown() Delete() GetProfileCopy(timeline bool) *model.Profile GetNewPeerMessage() *event.Event GetStatusMessages() []*event.Event } // CreateProfileWriterStore creates a profile store backed by a filestore listening for events and saving them // directory should be $appDir/profiles/$rand func CreateProfileWriterStore(eventManager event.Manager, directory, password string, profile *model.Profile) ProfileStore { return v1.CreateProfileWriterStore(eventManager, directory, password, profile) } // LoadProfileWriterStore loads a profile store from filestore listening for events and saving them // directory should be $appDir/profiles/$rand func LoadProfileWriterStore(eventManager event.Manager, directory, password string) (ProfileStore, error) { versionCheckUpgrade(directory, password) return v1.LoadProfileWriterStore(eventManager, directory, password) } // ReadProfile reads a profile from storage and returns the profile // Should only be called for cache refresh of the profile after a ProfileWriterStore has opened // (and upgraded) the store, and thus supplied the key/salt func ReadProfile(directory string, key [32]byte, salt [128]byte) (*model.Profile, error) { return v1.ReadProfile(directory, key, salt) } // NewProfile creates a new profile for use in the profile store. func NewProfile(name string) *model.Profile { profile := model.GenerateNewProfile(name) return profile } // ********* Versioning and upgrade ********** func detectVersion(directory string) int { vnumberStr, err := ioutil.ReadFile(path.Join(directory, versionFile)) if err != nil { return 0 } vnumber, err := strconv.Atoi(string(vnumberStr)) if err != nil { log.Errorf("Could not parse VERSION file contents: '%v' - %v\n", vnumber, err) return -1 } return vnumber } func upgradeV0ToV1(directory, password string) error { log.Debugln("Attempting storage v0 to v1: Reading v0 profile...") profile, err := v0.ReadProfile(directory, password) if err != nil { return err } log.Debugln("Attempting storage v0 to v1: Writing v1 profile...") return v1.UpgradeV0Profile(profile, directory, password) } func versionCheckUpgrade(directory, password string) { version := detectVersion(directory) log.Infof("versionCheck: %v\n", version) if version == -1 { return } if version == 0 { err := upgradeV0ToV1(directory, password) if err != nil { return } //version = 1 } }