forked from cwtch.im/cwtch
1
0
Fork 0
cwtch/storage/v0/profile_store.go

121 lines
3.6 KiB
Go

package v0
import (
"cwtch.im/cwtch/event"
"cwtch.im/cwtch/model"
"encoding/json"
"fmt"
"os"
"time"
)
const groupIDLen = 32
const peerIDLen = 56
const profileFilename = "profile"
// ProfileStoreV0 is a legacy profile store used now for upgrading legacy profile stores to newer versions
type ProfileStoreV0 struct {
fs FileStore
streamStores map[string]StreamStore // map [groupId|onion] StreamStore
directory string
password string
profile *model.Profile
}
// NewProfileWriterStore returns a profile store backed by a filestore listening for events and saving them
// directory should be $appDir/profiles/$rand
func NewProfileWriterStore(eventManager event.Manager, directory, password string, profile *model.Profile) *ProfileStoreV0 {
os.Mkdir(directory, 0700)
ps := &ProfileStoreV0{fs: NewFileStore(directory, profileFilename, password), password: password, directory: directory, profile: profile, streamStores: map[string]StreamStore{}}
if profile != nil {
ps.save()
}
return ps
}
// ReadProfile reads a profile from storqage and returns the profile
// directory should be $appDir/profiles/$rand
func ReadProfile(directory, password string) (*model.Profile, error) {
os.Mkdir(directory, 0700)
ps := &ProfileStoreV0{fs: NewFileStore(directory, profileFilename, password), password: password, directory: directory, profile: nil, streamStores: map[string]StreamStore{}}
err := ps.Load()
if err != nil {
return nil, err
}
profile := ps.getProfileCopy(true)
return profile, nil
}
/********************************************************************************************/
// AddGroup For testing, adds a group to the profile (and startsa stream store)
func (ps *ProfileStoreV0) AddGroup(invite []byte, peer string) {
gid, err := ps.profile.ProcessInvite(string(invite), peer)
if err == nil {
ps.save()
group := ps.profile.Groups[gid]
ps.streamStores[group.GroupID] = NewStreamStore(ps.directory, group.LocalID, ps.password)
}
}
// AddGroupMessage for testing, adds a group message
func (ps *ProfileStoreV0) AddGroupMessage(groupid string, timeSent, timeRecvied string, remotePeer, data string) {
received, _ := time.Parse(time.RFC3339Nano, timeRecvied)
sent, _ := time.Parse(time.RFC3339Nano, timeSent)
message := model.Message{Received: received, Timestamp: sent, Message: data, PeerID: remotePeer, Signature: []byte("signature"), PreviousMessageSig: []byte("PreviousSignature")}
ss, exists := ps.streamStores[groupid]
if exists {
ss.Write(message)
} else {
fmt.Println("ERROR")
}
}
// GetNewPeerMessage is for AppService to call on Reload events, to reseed the AppClient with the loaded peers
func (ps *ProfileStoreV0) GetNewPeerMessage() *event.Event {
message := event.NewEventList(event.NewPeer, event.Identity, ps.profile.LocalID, event.Password, ps.password, event.Status, "running")
return &message
}
// Load instantiates a cwtchPeer from the file store
func (ps *ProfileStoreV0) Load() error {
decrypted, err := ps.fs.Read()
if err != nil {
return err
}
cp := new(model.Profile)
err = json.Unmarshal(decrypted, &cp)
if err == nil {
ps.profile = cp
for gid, group := range cp.Groups {
ss := NewStreamStore(ps.directory, group.LocalID, ps.password)
cp.Groups[gid].Timeline.SetMessages(ss.Read())
ps.streamStores[group.GroupID] = ss
}
}
return err
}
func (ps *ProfileStoreV0) getProfileCopy(timeline bool) *model.Profile {
return ps.profile.GetCopy(timeline)
}
// Shutdown saves the storage system
func (ps *ProfileStoreV0) Shutdown() {
ps.save()
}
/************* Writing *************/
func (ps *ProfileStoreV0) save() error {
bytes, _ := json.Marshal(ps.profile)
return ps.fs.Write(bytes)
}