business: add privacy-aware user projection
(cherry picked from commit a636192ef22ee69d792b0ca7db1c6be963be9cb2)
This commit is contained in:
parent
14d220c971
commit
8ff3343ae0
29 changed files with 2239 additions and 112 deletions
|
|
@ -276,6 +276,52 @@ func (s *ContactStore) Get(_ context.Context, userID, contactUserID int64) (doma
|
|||
return domain.Contact{}, false, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) GetMany(_ context.Context, userID int64, contactUserIDs []int64) (map[int64]domain.Contact, error) {
|
||||
out := make(map[int64]domain.Contact, len(contactUserIDs))
|
||||
if userID == 0 || len(contactUserIDs) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
want := make(map[int64]struct{}, len(contactUserIDs))
|
||||
for _, id := range contactUserIDs {
|
||||
if id != 0 {
|
||||
want[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
s.mu.RLock()
|
||||
list := s.m[userID]
|
||||
s.mu.RUnlock()
|
||||
for _, contact := range list.Contacts {
|
||||
if _, ok := want[contact.User.ID]; ok {
|
||||
out[contact.User.ID] = cloneContact(contact)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) GetReverseContacts(_ context.Context, userID int64, ownerUserIDs []int64) (map[int64]domain.Contact, error) {
|
||||
out := make(map[int64]domain.Contact, len(ownerUserIDs))
|
||||
if userID == 0 || len(ownerUserIDs) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
want := make(map[int64]struct{}, len(ownerUserIDs))
|
||||
for _, id := range ownerUserIDs {
|
||||
if id != 0 {
|
||||
want[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
for ownerID := range want {
|
||||
for _, contact := range s.m[ownerID].Contacts {
|
||||
if contact.User.ID == userID {
|
||||
out[ownerID] = cloneContact(contact)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) Upsert(_ context.Context, userID int64, input domain.ContactInput) (domain.Contact, error) {
|
||||
contact := domain.Contact{
|
||||
User: domain.User{
|
||||
|
|
@ -366,6 +412,52 @@ func (s *ContactStore) UpdateNote(_ context.Context, userID, contactUserID int64
|
|||
return domain.Contact{}, false, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) SetPersonalPhoto(_ context.Context, userID, contactUserID int64, photoID int64, date int) (domain.Contact, bool, error) {
|
||||
_ = date
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
list := s.m[userID]
|
||||
for i := range list.Contacts {
|
||||
if list.Contacts[i].User.ID != contactUserID {
|
||||
continue
|
||||
}
|
||||
list.Contacts[i].User.PhotoID = photoID
|
||||
list.Contacts[i].User.PhotoPersonal = photoID != 0
|
||||
list.Hash = contactListHash(list.Contacts)
|
||||
s.m[userID] = list
|
||||
return cloneContact(list.Contacts[i]), true, nil
|
||||
}
|
||||
return domain.Contact{}, false, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) PersonalPhotos(_ context.Context, userID int64, contactUserIDs []int64) (map[int64]domain.ProfilePhotoRef, error) {
|
||||
out := make(map[int64]domain.ProfilePhotoRef, len(contactUserIDs))
|
||||
if userID == 0 || len(contactUserIDs) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
want := make(map[int64]struct{}, len(contactUserIDs))
|
||||
for _, id := range contactUserIDs {
|
||||
if id != 0 {
|
||||
want[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
s.mu.RLock()
|
||||
list := s.m[userID]
|
||||
s.mu.RUnlock()
|
||||
for _, contact := range list.Contacts {
|
||||
if _, ok := want[contact.User.ID]; !ok || contact.User.PhotoID == 0 {
|
||||
continue
|
||||
}
|
||||
out[contact.User.ID] = domain.ProfilePhotoRef{
|
||||
PhotoID: contact.User.PhotoID,
|
||||
DCID: contact.User.PhotoDCID,
|
||||
Stripped: append([]byte(nil), contact.User.PhotoStripped...),
|
||||
Personal: true,
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) Delete(_ context.Context, userID int64, contactUserIDs []int64) (int, error) {
|
||||
remove := make(map[int64]struct{}, len(contactUserIDs))
|
||||
for _, id := range contactUserIDs {
|
||||
|
|
|
|||
75
internal/store/memory/privacy.go
Normal file
75
internal/store/memory/privacy.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
type privacyStoreKey struct {
|
||||
ownerUserID int64
|
||||
key domain.PrivacyKey
|
||||
}
|
||||
|
||||
// PrivacyStore is an in-memory account privacy rule store for tests/dev mode.
|
||||
type PrivacyStore struct {
|
||||
mu sync.RWMutex
|
||||
rules map[privacyStoreKey]domain.PrivacyRules
|
||||
}
|
||||
|
||||
func NewPrivacyStore() *PrivacyStore {
|
||||
return &PrivacyStore{rules: make(map[privacyStoreKey]domain.PrivacyRules)}
|
||||
}
|
||||
|
||||
func (s *PrivacyStore) GetPrivacyRules(_ context.Context, ownerUserID int64, key domain.PrivacyKey) (domain.PrivacyRules, bool, error) {
|
||||
s.mu.RLock()
|
||||
rules, ok := s.rules[privacyStoreKey{ownerUserID: ownerUserID, key: key}]
|
||||
s.mu.RUnlock()
|
||||
return clonePrivacyRules(rules), ok, nil
|
||||
}
|
||||
|
||||
func (s *PrivacyStore) SetPrivacyRules(_ context.Context, rules domain.PrivacyRules) error {
|
||||
s.mu.Lock()
|
||||
s.rules[privacyStoreKey{ownerUserID: rules.OwnerUserID, key: rules.Key}] = clonePrivacyRules(rules)
|
||||
s.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PrivacyStore) ListPrivacyRules(_ context.Context, ownerUserIDs []int64, keys []domain.PrivacyKey) ([]domain.PrivacyRules, error) {
|
||||
if len(ownerUserIDs) == 0 || len(keys) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
owners := make(map[int64]struct{}, len(ownerUserIDs))
|
||||
for _, id := range ownerUserIDs {
|
||||
owners[id] = struct{}{}
|
||||
}
|
||||
keySet := make(map[domain.PrivacyKey]struct{}, len(keys))
|
||||
for _, key := range keys {
|
||||
keySet[key] = struct{}{}
|
||||
}
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
out := make([]domain.PrivacyRules, 0, len(s.rules))
|
||||
for k, rules := range s.rules {
|
||||
if _, ok := owners[k.ownerUserID]; !ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := keySet[k.key]; !ok {
|
||||
continue
|
||||
}
|
||||
out = append(out, clonePrivacyRules(rules))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func clonePrivacyRules(in domain.PrivacyRules) domain.PrivacyRules {
|
||||
out := in
|
||||
out.Rules = make([]domain.PrivacyRule, len(in.Rules))
|
||||
for i, rule := range in.Rules {
|
||||
out.Rules[i] = rule
|
||||
out.Rules[i].UserIDs = append([]int64(nil), rule.UserIDs...)
|
||||
out.Rules[i].ChatIDs = append([]int64(nil), rule.ChatIDs...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue