forked from cwtch.im/cwtch
121 lines
3.6 KiB
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)
|
||
|
}
|