status-go/protocol/communities/persistence.go

140 lines
3.7 KiB
Go

package communities
import (
"crypto/ecdsa"
"database/sql"
"github.com/golang/protobuf/proto"
"go.uber.org/zap"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/protocol/protobuf"
)
type Persistence struct {
db *sql.DB
logger *zap.Logger
}
func (p *Persistence) SaveCommunity(community *Community) error {
id := community.ID()
privateKey := community.PrivateKey()
description, err := community.ToBytes()
if err != nil {
return err
}
_, err = p.db.Exec(`INSERT INTO communities_communities (id, private_key, description, joined, verified) VALUES (?, ?, ?,?,?)`, id, crypto.FromECDSA(privateKey), description, community.config.Joined, community.config.Verified)
return err
}
func (p *Persistence) queryCommunities(query string) (response []*Community, err error) {
rows, err := p.db.Query(query)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
// Don't shadow original error
_ = rows.Close()
return
}
err = rows.Close()
}()
for rows.Next() {
var publicKeyBytes, privateKeyBytes, descriptionBytes []byte
var joined bool
var verified bool
err := rows.Scan(&publicKeyBytes, &privateKeyBytes, &descriptionBytes, &joined, &verified)
if err != nil {
return nil, err
}
org, err := unmarshalCommunityFromDB(publicKeyBytes, privateKeyBytes, descriptionBytes, joined, verified, p.logger)
if err != nil {
return nil, err
}
response = append(response, org)
}
return response, nil
}
func (p *Persistence) AllCommunities() ([]*Community, error) {
query := `SELECT id, private_key, description,joined,verified FROM communities_communities`
return p.queryCommunities(query)
}
func (p *Persistence) JoinedCommunities() ([]*Community, error) {
query := `SELECT id, private_key, description,joined,verified FROM communities_communities WHERE joined`
return p.queryCommunities(query)
}
func (p *Persistence) CreatedCommunities() ([]*Community, error) {
query := `SELECT id, private_key, description,joined,verified FROM communities_communities WHERE private_key IS NOT NULL`
return p.queryCommunities(query)
}
func (p *Persistence) GetByID(id []byte) (*Community, error) {
var publicKeyBytes, privateKeyBytes, descriptionBytes []byte
var joined bool
var verified bool
err := p.db.QueryRow(`SELECT id, private_key, description, joined,verified FROM communities_communities WHERE id = ?`, id).Scan(&publicKeyBytes, &privateKeyBytes, &descriptionBytes, &joined, &verified)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
return nil, err
}
return unmarshalCommunityFromDB(publicKeyBytes, privateKeyBytes, descriptionBytes, joined, verified, p.logger)
}
func unmarshalCommunityFromDB(publicKeyBytes, privateKeyBytes, descriptionBytes []byte, joined, verified bool, logger *zap.Logger) (*Community, error) {
var privateKey *ecdsa.PrivateKey
var err error
if privateKeyBytes != nil {
privateKey, err = crypto.ToECDSA(privateKeyBytes)
if err != nil {
return nil, err
}
}
metadata := &protobuf.ApplicationMetadataMessage{}
err = proto.Unmarshal(descriptionBytes, metadata)
if err != nil {
return nil, err
}
description := &protobuf.CommunityDescription{}
err = proto.Unmarshal(metadata.Payload, description)
if err != nil {
return nil, err
}
id, err := crypto.DecompressPubkey(publicKeyBytes)
if err != nil {
return nil, err
}
config := Config{
PrivateKey: privateKey,
CommunityDescription: description,
MarshaledCommunityDescription: descriptionBytes,
Logger: logger,
ID: id,
Verified: verified,
Joined: joined,
}
return New(config)
}