package localserver import ( "encoding/json" "os" "path/filepath" "github.com/dgraph-io/badger/v3" ) type BasicRights struct { Create bool `json:"create"` } type ChatRights struct { *BasicRights } type AudioChannelRights struct { *BasicRights } type VideoChannelRights struct { *BasicRights } type MediaRights struct { *BasicRights } type FileRights struct { *BasicRights CreateAtRoot bool `json:"createAtRoot"` } type User struct { ID string `json:"id"` Name string `json:"name"` ChatRights *ChatRights `json:"chatRights"` AudioChannelRights *AudioChannelRights `json:"audioChannelRights"` VideoChannelRights *VideoChannelRights `json:"videoChannelRights"` MediaRights *MediaRights `json:"mediaRights"` FileRights *FileRights `json:"fileRights"` KnownChatsId []string `json:"knownChatsId"` KnownAudioChannelsId []string `json:"knownAudioChannelsId"` KnownVideoChannelsId []string `json:"knownVideoChannelsId"` KnownMediaFolderId []string `json:"knownMediaFolderId"` KnownFileFolderId []string `json:"knownFileFolderId"` Admin bool `json:"admin"` Owner bool `json:"owner"` } type ZoneUsersDBHandler struct { ZoneID string db func(func(*badger.DB) (err error)) (err error) } func NewChatRights(create bool) *ChatRights { return &ChatRights{ BasicRights: &BasicRights{ Create: create, }, } } func NewAudioChannelRights(create bool) *AudioChannelRights { return &AudioChannelRights{ BasicRights: &BasicRights{ Create: create, }, } } func NewVideoChannelRights(create bool) *VideoChannelRights { return &VideoChannelRights{ BasicRights: &BasicRights{ Create: create, }, } } func NewMediaRights(create bool) *MediaRights { return &MediaRights{ BasicRights: &BasicRights{ Create: create, }, } } func NewFileRights(create bool) *FileRights { return &FileRights{ BasicRights: &BasicRights{ Create: create, }, } } func NewZoneUsersDBHandler(zoneId string, owner string, authorizedMembers []string, init bool) (zoneChatDBHandler *ZoneUsersDBHandler, err error) { db := func(f func(*badger.DB) (err error)) (err error) { db, err := badger.Open(badger.DefaultOptions(filepath.Join(dataPath, "data", "zones", zoneId, "users")).WithLogger(dbLogger)) if err != nil { return } defer db.Close() err = f(db) return } if init { admin := &User{ ID: owner, Name: owner, ChatRights: NewChatRights(true), AudioChannelRights: NewAudioChannelRights(true), VideoChannelRights: NewVideoChannelRights(true), MediaRights: NewMediaRights(true), FileRights: NewFileRights(true), KnownChatsId: []string{}, KnownAudioChannelsId: []string{}, KnownVideoChannelsId: []string{}, KnownMediaFolderId: make([]string, 0), KnownFileFolderId: make([]string, 0), Admin: true, Owner: true, } bs, jsonErr := json.Marshal(admin) if jsonErr != nil { return nil, jsonErr } if err = db(func(d *badger.DB) (err error) { err = d.Update(func(txn *badger.Txn) (err error) { err = txn.Set([]byte(owner), bs) return }) return }); err != nil { return } } bs, err := os.ReadFile(filepath.Join(dataPath, "data", "zones", zoneId, "users", "usersConfig.json")) if err != nil { return } var baseUserConfig ZoneUserConfig if err = json.Unmarshal(bs, &baseUserConfig); err != nil { return } if err = db(func(d *badger.DB) (err error) { err = d.Update(func(txn *badger.Txn) (err error) { for _, member := range authorizedMembers { if member != owner { if _, berr := txn.Get([]byte(member)); berr == badger.ErrKeyNotFound { logger.Println("creating new user", member) user := &User{ ID: member, Name: member, ChatRights: baseUserConfig.DefaultChatRights, AudioChannelRights: baseUserConfig.DefaultAudioChannelRights, VideoChannelRights: baseUserConfig.DefaultVideoChannelRights, MediaRights: baseUserConfig.DefaultMediaRights, FileRights: baseUserConfig.DefaultFileRights, KnownChatsId: []string{}, KnownAudioChannelsId: []string{}, KnownVideoChannelsId: []string{}, KnownMediaFolderId: make([]string, 0), KnownFileFolderId: make([]string, 0), Admin: false, Owner: false, } bs, jsonErr := json.Marshal(user) if jsonErr != nil { return jsonErr } if err = txn.Set([]byte(member), bs); err != nil { return } } } } return nil }) return }); err != nil { return } zoneChatDBHandler = &ZoneUsersDBHandler{ db: db, ZoneID: zoneId, } return } func (zcdbh *ZoneUsersDBHandler) AddNewUser(user *User) (err error) { bs, err := json.Marshal(user) if err != nil { return } if err = zcdbh.db(func(d *badger.DB) (err error) { err = d.Update(func(txn *badger.Txn) error { if _, notFoundErr := txn.Get([]byte(user.ID)); notFoundErr == badger.ErrKeyNotFound { if updateErr := txn.Set([]byte(user.ID), bs); updateErr != nil { return updateErr } } return nil }) return }); err != nil { return } return } func (zcdbh *ZoneUsersDBHandler) DeleteUser(id string) (err error) { err = zcdbh.db(func(d *badger.DB) (err error) { err = d.Update(func(txn *badger.Txn) (err error) { err = txn.Delete([]byte(id)) return }) return }) return } func (zcdbh *ZoneUsersDBHandler) ListUsers(lastIndex int, limit int) (users []*User, err error) { err = zcdbh.db(func(d *badger.DB) (err error) { err = d.View(func(txn *badger.Txn) error { opt := badger.DefaultIteratorOptions opt.Reverse = true it := txn.NewIterator(opt) defer it.Close() users = []*User{} for it.Rewind(); it.Valid(); it.Next() { item := it.Item() if err = item.Value(func(val []byte) error { var user *User if jsonErr := json.Unmarshal(val, &user); jsonErr != nil { return jsonErr } users = append(users, user) return nil }); err != nil { return err } } return nil }) return }) return } func (zcdbh *ZoneUsersDBHandler) GetUser(id string) (user *User, err error) { err = zcdbh.db(func(d *badger.DB) (err error) { err = d.View(func(txn *badger.Txn) error { item, err := txn.Get([]byte(id)) if err != nil { return err } err = item.Value(func(val []byte) (err error) { err = json.Unmarshal(val, &user) return }) return err }) return }) return } func (zcdbh *ZoneUsersDBHandler) ModifyUser(id string, user *User) (err error) { bs, err := json.Marshal(user) if err != nil { return } err = zcdbh.db(func(d *badger.DB) (err error) { err = d.Update(func(txn *badger.Txn) (err error) { err = txn.Set([]byte(id), bs) return }) return }) return }