Finish initial adaption of profiles
This commit is contained in:
101
profile/index/index.go
Normal file
101
profile/index/index.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"fmt"
|
||||
"errors"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/Safing/portbase/database/record"
|
||||
"github.com/Safing/portbase/utils"
|
||||
)
|
||||
|
||||
// ProfileIndex links an Identifier to Profiles
|
||||
type ProfileIndex struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
||||
ID string
|
||||
UserProfiles []string
|
||||
StampProfiles []string
|
||||
}
|
||||
|
||||
func makeIndexRecordKey(id string) string {
|
||||
return fmt.Sprintf("core:profiles/index/%s", base64.RawURLEncoding.EncodeToString([]byte(id)))
|
||||
}
|
||||
|
||||
// NewIndex returns a new ProfileIndex.
|
||||
func NewIndex(id string) *ProfileIndex {
|
||||
return &ProfileIndex{
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
|
||||
// AddUserProfile adds a User Profile to the index.
|
||||
func (pi *ProfileIndex) AddUserProfile(id string) (changed bool) {
|
||||
if !utils.StringInSlice(pi.UserProfiles, id) {
|
||||
pi.UserProfiles = append(pi.UserProfiles, id)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AddStampProfile adds a Stamp Profile to the index.
|
||||
func (pi *ProfileIndex) AddStampProfile(id string) (changed bool) {
|
||||
if !utils.StringInSlice(pi.StampProfiles, id) {
|
||||
pi.StampProfiles = append(pi.StampProfiles, id)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveUserProfile removes a profile from the index.
|
||||
func (pi *ProfileIndex) RemoveUserProfile(id string) {
|
||||
pi.UserProfiles = utils.RemoveFromStringSlice(pi.UserProfiles, id)
|
||||
}
|
||||
|
||||
// RemoveStampProfile removes a profile from the index.
|
||||
func (pi *ProfileIndex) RemoveStampProfile(id string) {
|
||||
pi.StampProfiles = utils.RemoveFromStringSlice(pi.StampProfiles, id)
|
||||
}
|
||||
|
||||
// GetIndex gets a ProfileIndex from the database.
|
||||
func GetIndex(id string) (*ProfileIndex, error) {
|
||||
key := makeIndexRecordKey(id)
|
||||
|
||||
r, err := indexDB.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// unwrap
|
||||
if r.IsWrapped() {
|
||||
// only allocate a new struct, if we need it
|
||||
new := &ProfileIndex{}
|
||||
err = record.Unwrap(r, new)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return new, nil
|
||||
}
|
||||
|
||||
// or adjust type
|
||||
new, ok := r.(*ProfileIndex)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("record not of type *ProfileIndex, but %T", r)
|
||||
}
|
||||
return new, nil
|
||||
}
|
||||
|
||||
// Save saves the Identifiers to the database
|
||||
func (pi *ProfileIndex) Save() error {
|
||||
if pi.Key() == "" {
|
||||
if pi.ID != "" {
|
||||
pi.SetKey(makeIndexRecordKey(pi.ID))
|
||||
} else {
|
||||
return errors.New("missing identification Key")
|
||||
}
|
||||
}
|
||||
|
||||
return indexDB.Put(pi)
|
||||
}
|
||||
101
profile/index/indexer.go
Normal file
101
profile/index/indexer.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/Safing/portbase/database"
|
||||
"github.com/Safing/portbase/database/query"
|
||||
"github.com/Safing/portbase/database/record"
|
||||
"github.com/Safing/portbase/log"
|
||||
"github.com/Safing/portbase/modules"
|
||||
|
||||
"github.com/Safing/portmaster/profile"
|
||||
)
|
||||
|
||||
// FIXME: listen for profile changes and update the index
|
||||
|
||||
var (
|
||||
indexDB = database.NewInterface(&database.Options{
|
||||
Local: true, // we want to access crownjewel records
|
||||
AlwaysMakeCrownjewel: true, // never sync the index
|
||||
})
|
||||
indexSub *database.Subscription
|
||||
|
||||
shutdownIndexer = make(chan struct{})
|
||||
)
|
||||
|
||||
func init() {
|
||||
modules.Register("profile:index", nil, start, stop, "database")
|
||||
}
|
||||
|
||||
func start() (err error) {
|
||||
indexSub, err = indexDB.Subscribe(query.New("core:profiles/user/"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stop() error {
|
||||
close(shutdownIndexer)
|
||||
indexSub.Cancel()
|
||||
return nil
|
||||
}
|
||||
|
||||
func indexer() {
|
||||
for {
|
||||
select {
|
||||
case <-shutdownIndexer:
|
||||
return
|
||||
case r := <-indexSub.Feed:
|
||||
prof := ensureProfile(r)
|
||||
if prof != nil {
|
||||
for _, id := range prof.Identifiers {
|
||||
if strings.HasPrefix(id, profile.IdentifierPrefix) {
|
||||
|
||||
// get Profile and ensure identifier is set
|
||||
pi, err := GetIndex(id)
|
||||
if err != nil {
|
||||
if err == database.ErrNotFound {
|
||||
pi = NewIndex(id)
|
||||
} else {
|
||||
log.Errorf("profile/index: could not save updated profile index: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if pi.AddUserProfile(prof.ID) {
|
||||
err := pi.Save()
|
||||
if err != nil {
|
||||
log.Errorf("profile/index: could not save updated profile index: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ensureProfile(r record.Record) *profile.Profile {
|
||||
// unwrap
|
||||
if r.IsWrapped() {
|
||||
// only allocate a new struct, if we need it
|
||||
new := &profile.Profile{}
|
||||
err := record.Unwrap(r, new)
|
||||
if err != nil {
|
||||
log.Errorf("profile/index: could not unwrap Profile: %s", err)
|
||||
return nil
|
||||
}
|
||||
return new
|
||||
}
|
||||
|
||||
// or adjust type
|
||||
new, ok := r.(*profile.Profile)
|
||||
if !ok {
|
||||
log.Errorf("profile/index: record not of type *Profile, but %T", r)
|
||||
return nil
|
||||
}
|
||||
return new
|
||||
}
|
||||
Reference in New Issue
Block a user