summaryrefslogtreecommitdiff
path: root/owner
diff options
context:
space:
mode:
authorVitaly Minko <vitaly.minko@gmail.com>2018-11-08 18:29:47 +0300
committerVitaly Minko <vitaly.minko@gmail.com>2018-11-08 18:29:47 +0300
commitce1cc2c86dc19a9b26eb6c9376986195a5c5fe8b (patch)
tree873374d68dfa4eabb15592e728fcd09aa7117461 /owner
parentc4e516b5ee21d6a08bf0cdd81ad8bdee1775af2b (diff)
Minor improvements before proof-of-concept release.
Subscriptions moved to the Profile. User API divided in two parts: root API (which is always available) and LoginHandle (which is available only after Login()).
Diffstat (limited to 'owner')
-rw-r--r--owner/owner.go88
-rw-r--r--owner/profile.go44
2 files changed, 94 insertions, 38 deletions
diff --git a/owner/owner.go b/owner/owner.go
index 709cc5f..a866a69 100644
--- a/owner/owner.go
+++ b/owner/owner.go
@@ -35,20 +35,19 @@ import (
// Owner represents the owner of the current node in the network.
type Owner struct {
User *entity.User
- Subs subs.Subscriptions
+ Storage *storage.Storage
Profile *Profile
Signer *crypto.Signer
View *View
- storage *storage.Storage
}
const (
privKeyFileName string = "privkey.pem"
- subscriptionsFileName string = "subscriptions.txt"
profileDatabaseFileName string = "profile.db"
+ entityDatabaseFileName string = "entity.db"
)
-func Register(dir, nickname, info string, subs subs.Subscriptions, s *storage.Storage) error {
+func Register(dir, nickname, info string, subs subs.Subscriptions) error {
log.Debugf("Registering user %s", nickname)
// Nickname will be validated via regexp later during EmergeUser
if nickname == "" {
@@ -68,13 +67,6 @@ func Register(dir, nickname, info string, subs subs.Subscriptions, s *storage.St
}
}
- subsPath := filepath.Join(userDir, subscriptionsFileName)
- err = ioutil.WriteFile(subsPath, []byte(subs.String()), 0640)
- if err != nil {
- log.Errorf("Can't save user subscriptions as file %s: %v", subsPath, err)
- return errors.Filesystem
- }
-
privKey, err := crypto.NewPrivateKey()
if err != nil {
log.Errorf("Can't generate new private key: %v", err)
@@ -91,24 +83,54 @@ func Register(dir, nickname, info string, subs subs.Subscriptions, s *storage.St
pow := crypto.NewPowFinder(privKey.Public().EncodeToDER())
proof := pow.Find()
- user, err := entity.EmergeUser(nickname, info, proof, crypto.NewSigner(privKey))
+ u, err := entity.EmergeUser(nickname, info, proof, crypto.NewSigner(privKey))
if err != nil {
log.Errorf("Can't create user '%s': %v", nickname, err)
return err
}
log.Debugf("Dumping emerged User %s:", nickname)
- log.Debug(user.Dump())
+ log.Debug(u.Dump())
- err = s.PutEntity((entity.Entity)(user), nil)
+ entityDatabasePath := filepath.Join(userDir, entityDatabaseFileName)
+ sDB, err := sqlite.OpenEntityDatabase(entityDatabasePath)
if err != nil {
- log.Errorf("Can't add user '%s' to the storage: %v", user.Nickname, err)
+ log.Errorf("Can't open entity database file %s: %v", entityDatabasePath, err)
+ return errors.Database
+ }
+ s := storage.New(sDB)
+ err = s.PutEntity((entity.Entity)(u), nil)
+ if err != nil {
+ log.Errorf("Can't add user '%s' to the storage: %v", u.Nickname, err)
return errors.Database
}
+ profileDatabasePath := filepath.Join(userDir, profileDatabaseFileName)
+ pDB, err := sqlite.OpenProfileDatabase(profileDatabasePath)
+ if err != nil {
+ log.Errorf("Can't open profile database file %s: %v", profileDatabasePath, err)
+ return errors.Database
+ }
+ prf := NewProfile(pDB, u.ID())
+ for _, t := range subs {
+ err := prf.PutSubscription(t)
+ log.Errorf("Failed to put subscription %s into the owner's profile: %v", t, err)
+ return err
+ }
+
+ err = s.Close()
+ if err != nil {
+ log.Errorf("Error closing entity storage: %v", err)
+ }
+
+ err = prf.Close()
+ if err != nil {
+ log.Errorf("Error closing owner's profile: %v", err)
+ }
+
return nil
}
-func New(dir, nickname string, stor *storage.Storage) (*Owner, error) {
+func New(dir, nickname string) (*Owner, error) {
userDir := filepath.Join(dir, nickname)
log.Debugf("Owner uses the following user directory: %s", userDir)
if _, err := os.Stat(userDir); os.IsNotExist(err) {
@@ -129,8 +151,16 @@ func New(dir, nickname string, stor *storage.Storage) (*Owner, error) {
return nil, err
}
+ entityDatabasePath := filepath.Join(userDir, entityDatabaseFileName)
+ sDB, err := sqlite.OpenEntityDatabase(entityDatabasePath)
+ if err != nil {
+ log.Errorf("Can't open entity database file %s: %v", entityDatabasePath, err)
+ return nil, errors.Database
+ }
+ s := storage.New(sDB)
+
eid := entity.NewID(privKey.Public().EncodeToDER())
- u, err := stor.GetUser(&eid)
+ u, err := s.GetUser(&eid)
if err != nil {
log.Errorf("Can't fetch the user with id '%x' from the storage: %v", eid, err)
return nil, err
@@ -138,34 +168,30 @@ func New(dir, nickname string, stor *storage.Storage) (*Owner, error) {
log.Debug("Dumping fetched User:")
log.Debug(u.Dump())
- subsPath := filepath.Join(userDir, subscriptionsFileName)
- sub, err := subs.ReadFile(subsPath)
- if err != nil {
- log.Errorf("Error reading subscriptions of the user '%s': %v", nickname, err)
- return nil, err
- }
-
profileDatabasePath := filepath.Join(userDir, profileDatabaseFileName)
- db, err := sqlite.OpenProfileDatabase(profileDatabasePath)
+ pDB, err := sqlite.OpenProfileDatabase(profileDatabasePath)
if err != nil {
log.Errorf("Can't open profile database file %s: %v", profileDatabasePath, err)
return nil, errors.Database
}
+ p := NewProfile(pDB, u.ID())
- prf := NewProfile(db, u.ID())
return &Owner{
User: u,
- Subs: sub,
- Profile: prf,
+ Storage: s,
+ Profile: p,
Signer: crypto.NewSigner(privKey),
- View: NewView(prf, stor),
- storage: stor,
+ View: NewView(p, s),
}, nil
}
func (o *Owner) Close() {
- err := o.Profile.Close()
+ err := o.Storage.Close()
if err != nil {
log.Errorf("Error closing entity storage: %v", err)
}
+ err = o.Profile.Close()
+ if err != nil {
+ log.Errorf("Error closing owner's profile: %v", err)
+ }
}
diff --git a/owner/profile.go b/owner/profile.go
index 8ff8cf9..e74d1e9 100644
--- a/owner/profile.go
+++ b/owner/profile.go
@@ -21,7 +21,9 @@ import (
"sync"
"vminko.org/dscuss/entity"
"vminko.org/dscuss/errors"
+ "vminko.org/dscuss/log"
"vminko.org/dscuss/sqlite"
+ "vminko.org/dscuss/subs"
)
// Profile is a proxy for the profile database, which implements caching and
@@ -30,6 +32,8 @@ type Profile struct {
db *sqlite.ProfileDatabase
moderators []*entity.ID
modersMx sync.Mutex
+ subs subs.Subscriptions
+ subsMx sync.Mutex
selfID *entity.ID
}
@@ -65,10 +69,7 @@ func (p *Profile) HasModerator(id *entity.ID) (bool, error) {
if *id == *p.selfID {
return true, nil
}
- mm, err := p.GetModerators()
- if err != nil {
- return false, err
- }
+ mm := p.GetModerators()
for _, m := range mm {
if *m == *id {
return true, nil
@@ -77,18 +78,47 @@ func (p *Profile) HasModerator(id *entity.ID) (bool, error) {
return false, nil
}
-func (p *Profile) GetModerators() ([]*entity.ID, error) {
+func (p *Profile) GetModerators() []*entity.ID {
p.modersMx.Lock()
defer p.modersMx.Unlock()
if p.moderators == nil {
var err error
p.moderators, err = p.db.GetModerators()
if err != nil {
- return nil, err
+ log.Fatalf("Failed to fetch owner's subscriptions from "+
+ "the profile database: %v", err)
}
p.moderators = append(p.moderators, p.selfID)
}
res := make([]*entity.ID, len(p.moderators))
copy(res, p.moderators)
- return res, nil
+ return res
+}
+
+func (p *Profile) PutSubscription(t subs.Topic) error {
+ p.subsMx.Lock()
+ defer p.subsMx.Unlock()
+ p.subs = nil
+ return p.db.PutSubscription(t)
+}
+
+func (p *Profile) RemoveSubscription(t subs.Topic) error {
+ p.subsMx.Lock()
+ defer p.subsMx.Unlock()
+ p.subs = nil
+ return p.db.RemoveSubscription(t)
+}
+
+func (p *Profile) GetSubscriptions() subs.Subscriptions {
+ p.subsMx.Lock()
+ defer p.subsMx.Unlock()
+ if p.subs == nil {
+ var err error
+ p.subs, err = p.db.GetSubscriptions()
+ if err != nil {
+ log.Fatalf("Failed to fetch owner's subscriptions from "+
+ "the profile database: %v", err)
+ }
+ }
+ return p.subs.Copy()
}