139 lines
4.8 KiB
Go
139 lines
4.8 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
|
|
"forge.redroom.link/yves/meowlib"
|
|
"github.com/ProtonMail/gopenpgp/v2/helper"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Identity struct {
|
|
Nickname string `json:"nickname,omitempty"`
|
|
RootKp meowlib.KeyPair `json:"id_kp,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
Peers PeerList `json:"peers,omitempty"`
|
|
HiddenPeers [][]byte `json:"hiddend_peers,omitempty"`
|
|
Device meowlib.KeyPair `json:"device,omitempty"`
|
|
KnownServers InternalServerList `json:"known_servers,omitempty"`
|
|
MessageServers InternalServerList `json:"message_servers,omitempty"`
|
|
ArchiveServers InternalServerList `json:"archive_servers,omitempty"`
|
|
OwnedServers InternalServerList `json:"owned_servers,omitempty"`
|
|
DefaultDbPassword string `json:"default_db_password,omitempty"`
|
|
DbPasswordStore bool `json:"db_password_store,omitempty"`
|
|
OwnedDevices PeerList `json:"owned_devices,omitempty"`
|
|
StaticMtkServerPaths []InternalServerList `json:"static_mtk_server_paths,omitempty"`
|
|
DynamicMtkServeRules []string `json:"dynamic_mtk_serve_rules,omitempty"`
|
|
}
|
|
|
|
func CreateIdentity(nickname string) *Identity {
|
|
var id Identity
|
|
id.Nickname = nickname
|
|
id.RootKp = meowlib.NewKeyPair()
|
|
return &id
|
|
}
|
|
|
|
func (id *Identity) InvitePeer(MyName string, ContactName string, MessageServerIdxs []int) (*meowlib.ContactCard, error) {
|
|
var peer Peer
|
|
var myContactCard meowlib.ContactCard
|
|
peer.MyIdentity = meowlib.NewKeyPair()
|
|
peer.MyEncryptionKp = meowlib.NewKeyPair()
|
|
peer.MyLookupKp = meowlib.NewKeyPair()
|
|
peer.Name = ContactName
|
|
peer.InvitationId = uuid.New().String()
|
|
if id.MessageServers.Servers == nil {
|
|
return nil, errors.New("no message servers defined in your identity")
|
|
}
|
|
for _, i := range MessageServerIdxs {
|
|
if i > len(id.MessageServers.Servers)-1 {
|
|
return nil, errors.New("requested server out of range of defined message servers")
|
|
}
|
|
}
|
|
for _, i := range MessageServerIdxs {
|
|
srv := &id.MessageServers.Servers[i].ServerData
|
|
myContactCard.PullServers = append(myContactCard.PullServers, srv)
|
|
}
|
|
myContactCard.Name = MyName
|
|
myContactCard.ContactPublicKey = peer.MyIdentity.Public
|
|
myContactCard.EncryptionPublicKey = peer.MyEncryptionKp.Public
|
|
myContactCard.LookupPublicKey = peer.MyLookupKp.Public
|
|
myContactCard.InvitationId = peer.InvitationId
|
|
id.Peers = append(id.Peers, peer)
|
|
|
|
return &myContactCard, nil
|
|
}
|
|
|
|
func (id *Identity) CheckInvitation(ReceivedContact *meowlib.ContactCard) (isAnswer bool, proposedNick string, receivedNick string) {
|
|
for _, p := range id.Peers {
|
|
if p.InvitationId == ReceivedContact.InvitationId {
|
|
return true, p.Name, ReceivedContact.Name
|
|
}
|
|
}
|
|
return false, "", ReceivedContact.Name
|
|
}
|
|
|
|
func (id *Identity) AnswerInvitation(MyName string, ContactName string, MessageServerIdxs []int, ReceivedContact *meowlib.ContactCard) *meowlib.ContactCard {
|
|
var peer Peer
|
|
var myContactCard meowlib.ContactCard
|
|
peer.MyIdentity = meowlib.NewKeyPair()
|
|
peer.MyEncryptionKp = meowlib.NewKeyPair()
|
|
peer.MyLookupKp = meowlib.NewKeyPair()
|
|
if ContactName != "" {
|
|
peer.Name = ContactName
|
|
} else {
|
|
peer.Name = ReceivedContact.Name
|
|
}
|
|
peer.Contact = *ReceivedContact
|
|
for _, i := range MessageServerIdxs {
|
|
srv := id.MessageServers.Servers[i].ServerData
|
|
myContactCard.PullServers = append(myContactCard.PullServers, &srv)
|
|
}
|
|
myContactCard.Name = MyName
|
|
myContactCard.ContactPublicKey = peer.MyIdentity.Public
|
|
myContactCard.EncryptionPublicKey = peer.MyEncryptionKp.Public
|
|
myContactCard.LookupPublicKey = peer.MyLookupKp.Public
|
|
myContactCard.InvitationId = ReceivedContact.InvitationId
|
|
|
|
id.Peers = append(id.Peers, peer)
|
|
|
|
return &myContactCard
|
|
}
|
|
|
|
func (id *Identity) FinalizeInvitation(ReceivedContact *meowlib.ContactCard) error {
|
|
for i, p := range id.Peers {
|
|
if p.InvitationId == ReceivedContact.InvitationId {
|
|
id.Peers[i].Contact = *ReceivedContact
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("no matching contact found for invitationId " + ReceivedContact.InvitationId)
|
|
}
|
|
|
|
func LoadIdentity(filename string, password string) (*Identity, error) {
|
|
var id Identity
|
|
GetConfig().memoryPassword = password
|
|
GetConfig().identityFile = filename
|
|
indata, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pass, err := helper.DecryptMessageWithPassword([]byte(password), string(indata))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = json.Unmarshal([]byte(pass), &id)
|
|
return &id, err
|
|
}
|
|
|
|
func (id *Identity) Save() error {
|
|
b, _ := json.Marshal(id)
|
|
armor, err := helper.EncryptMessageWithPassword([]byte(GetConfig().memoryPassword), string(b))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = os.WriteFile(GetConfig().identityFile, []byte(armor), 0600)
|
|
return err
|
|
}
|