Initial open source release
This commit is contained in:
commit
74992e893f
377 changed files with 118084 additions and 0 deletions
158
internal/app/account/service.go
Normal file
158
internal/app/account/service.go
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/store"
|
||||
)
|
||||
|
||||
var defaultSecureRandom = []byte("telesrv-tdesktop-dev-secure-rand")
|
||||
|
||||
// Service 提供账号安全配置查询。
|
||||
type Service struct {
|
||||
passwords store.PasswordStore
|
||||
reactions store.AccountReactionSettingsStore
|
||||
}
|
||||
|
||||
// ServiceOption 调整 account 服务依赖。
|
||||
type ServiceOption func(*Service)
|
||||
|
||||
// WithReactionSettings 注入账号级 reaction 设置持久化。
|
||||
func WithReactionSettings(reactions store.AccountReactionSettingsStore) ServiceOption {
|
||||
return func(s *Service) {
|
||||
s.reactions = reactions
|
||||
}
|
||||
}
|
||||
|
||||
// NewService 创建 account 服务。
|
||||
func NewService(passwords store.PasswordStore, opts ...ServiceOption) *Service {
|
||||
s := &Service{passwords: passwords}
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// GetPassword 返回当前账号 2FA 配置。未登录或无记录时返回持久化策略的默认 no-password 配置。
|
||||
func (s *Service) GetPassword(ctx context.Context, userID int64) (domain.PasswordSettings, error) {
|
||||
if s == nil || s.passwords == nil || userID == 0 {
|
||||
return defaultPasswordSettings(), nil
|
||||
}
|
||||
settings, found, err := s.passwords.GetByUser(ctx, userID)
|
||||
if err != nil {
|
||||
return domain.PasswordSettings{}, err
|
||||
}
|
||||
if !found {
|
||||
return defaultPasswordSettings(), nil
|
||||
}
|
||||
if len(settings.SecureRandom) == 0 {
|
||||
settings.SecureRandom = append([]byte(nil), defaultSecureRandom...)
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
func defaultPasswordSettings() domain.PasswordSettings {
|
||||
return domain.PasswordSettings{SecureRandom: append([]byte(nil), defaultSecureRandom...)}
|
||||
}
|
||||
|
||||
// GetReactionSettings returns account-level reaction preferences.
|
||||
func (s *Service) GetReactionSettings(ctx context.Context, userID int64) (domain.AccountReactionSettings, error) {
|
||||
if s == nil || s.reactions == nil || userID == 0 {
|
||||
return domain.DefaultAccountReactionSettings(), nil
|
||||
}
|
||||
settings, found, err := s.reactions.GetReactionSettings(ctx, userID)
|
||||
if err != nil {
|
||||
return domain.AccountReactionSettings{}, err
|
||||
}
|
||||
if !found {
|
||||
return domain.DefaultAccountReactionSettings(), nil
|
||||
}
|
||||
return normalizeReactionSettings(settings), nil
|
||||
}
|
||||
|
||||
// SetReactionsNotifySettings stores reaction notification preferences.
|
||||
func (s *Service) SetReactionsNotifySettings(ctx context.Context, userID int64, notify domain.ReactionsNotifySettings) (domain.AccountReactionSettings, error) {
|
||||
settings, err := s.GetReactionSettings(ctx, userID)
|
||||
if err != nil {
|
||||
return domain.AccountReactionSettings{}, err
|
||||
}
|
||||
settings.Notify = normalizeNotifySettings(notify)
|
||||
return s.saveReactionSettings(ctx, userID, settings)
|
||||
}
|
||||
|
||||
// SetDefaultReaction stores the account default quick reaction.
|
||||
func (s *Service) SetDefaultReaction(ctx context.Context, userID int64, reaction domain.MessageReaction) (domain.AccountReactionSettings, error) {
|
||||
settings, err := s.GetReactionSettings(ctx, userID)
|
||||
if err != nil {
|
||||
return domain.AccountReactionSettings{}, err
|
||||
}
|
||||
if reaction.Type == "" || reaction.Emoticon == "" {
|
||||
reaction = domain.DefaultAccountReactionSettings().DefaultReaction
|
||||
}
|
||||
settings.DefaultReaction = reaction
|
||||
return s.saveReactionSettings(ctx, userID, settings)
|
||||
}
|
||||
|
||||
// SetPaidReactionPrivacy stores the account default paid reaction privacy.
|
||||
func (s *Service) SetPaidReactionPrivacy(ctx context.Context, userID int64, privacy domain.PaidReactionPrivacy) (domain.AccountReactionSettings, error) {
|
||||
settings, err := s.GetReactionSettings(ctx, userID)
|
||||
if err != nil {
|
||||
return domain.AccountReactionSettings{}, err
|
||||
}
|
||||
settings.PaidPrivacy = normalizePaidPrivacy(privacy)
|
||||
return s.saveReactionSettings(ctx, userID, settings)
|
||||
}
|
||||
|
||||
func (s *Service) saveReactionSettings(ctx context.Context, userID int64, settings domain.AccountReactionSettings) (domain.AccountReactionSettings, error) {
|
||||
settings = normalizeReactionSettings(settings)
|
||||
if s == nil || s.reactions == nil || userID == 0 {
|
||||
return settings, nil
|
||||
}
|
||||
return settings, s.reactions.SaveReactionSettings(ctx, userID, settings)
|
||||
}
|
||||
|
||||
func normalizeReactionSettings(settings domain.AccountReactionSettings) domain.AccountReactionSettings {
|
||||
defaults := domain.DefaultAccountReactionSettings()
|
||||
settings.Notify = normalizeNotifySettings(settings.Notify)
|
||||
if settings.DefaultReaction.Type == "" || settings.DefaultReaction.Emoticon == "" {
|
||||
settings.DefaultReaction = defaults.DefaultReaction
|
||||
}
|
||||
settings.PaidPrivacy = normalizePaidPrivacy(settings.PaidPrivacy)
|
||||
return settings
|
||||
}
|
||||
|
||||
func normalizeNotifySettings(settings domain.ReactionsNotifySettings) domain.ReactionsNotifySettings {
|
||||
if !validNotifyFrom(settings.MessagesFrom) {
|
||||
settings.MessagesFrom = domain.ReactionNotifyFromContacts
|
||||
}
|
||||
if !validNotifyFrom(settings.StoriesFrom) {
|
||||
settings.StoriesFrom = domain.ReactionNotifyFromContacts
|
||||
}
|
||||
if !validNotifyFrom(settings.PollVotesFrom) {
|
||||
settings.PollVotesFrom = domain.ReactionNotifyFromContacts
|
||||
}
|
||||
return settings
|
||||
}
|
||||
|
||||
func validNotifyFrom(value domain.ReactionNotifyFrom) bool {
|
||||
switch value {
|
||||
case domain.ReactionNotifyFromNone, domain.ReactionNotifyFromContacts, domain.ReactionNotifyFromAll:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func normalizePaidPrivacy(privacy domain.PaidReactionPrivacy) domain.PaidReactionPrivacy {
|
||||
switch privacy.Kind {
|
||||
case domain.PaidReactionPrivacyAnonymous:
|
||||
return domain.PaidReactionPrivacy{Kind: domain.PaidReactionPrivacyAnonymous}
|
||||
case domain.PaidReactionPrivacyPeer:
|
||||
if privacy.Peer != nil && privacy.Peer.ID != 0 {
|
||||
peer := *privacy.Peer
|
||||
return domain.PaidReactionPrivacy{Kind: domain.PaidReactionPrivacyPeer, Peer: &peer}
|
||||
}
|
||||
}
|
||||
return domain.PaidReactionPrivacy{Kind: domain.PaidReactionPrivacyDefault}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue