You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

678 lines
21 KiB
Go

package valueobjects
import (
"knowfoolery/backend/shared/types"
)
// PrivacySettings represents a user's privacy preferences
type PrivacySettings struct {
// Profile visibility
profileVisibility ProfileVisibility
showRealName bool
showEmail bool
showDateOfBirth bool
showLocation bool
// Statistics visibility
showStatistics bool
showGameHistory bool
showAchievements bool
showRankings bool
// Social features
allowFriendRequests bool
allowGameInvitations bool
allowMessages bool
showOnlineStatus bool
// Leaderboard participation
participateInLeaderboards bool
showInGlobalRankings bool
allowRankingComparison bool
// Data collection
allowAnalytics bool
allowMarketing bool
shareDataWithPartners bool
// Communication preferences
allowContactByEmail bool
allowContactBySMS bool
allowPushNotifications bool
// Search and discovery
allowProfileSearch bool
showInPlayerDirectory bool
allowRecommendations bool
// Update tracking
updatedAt types.Timestamp
}
// ProfileVisibility defines who can see a user's profile
type ProfileVisibility string
const (
ProfileVisibilityPublic ProfileVisibility = "public" // Anyone can see
ProfileVisibilityFriends ProfileVisibility = "friends" // Only friends can see
ProfileVisibilityPrivate ProfileVisibility = "private" // Only user can see
ProfileVisibilityLimited ProfileVisibility = "limited" // Limited public visibility
)
// NewDefaultPrivacySettings creates privacy settings with secure defaults
func NewDefaultPrivacySettings() *PrivacySettings {
return &PrivacySettings{
// Conservative defaults for privacy
profileVisibility: ProfileVisibilityLimited,
showRealName: false,
showEmail: false,
showDateOfBirth: false,
showLocation: false,
showStatistics: true, // Game stats are generally okay to show
showGameHistory: false, // More private
showAchievements: true, // Generally okay to show
showRankings: true, // Part of competitive gaming
allowFriendRequests: true,
allowGameInvitations: true,
allowMessages: false, // Conservative default
showOnlineStatus: false, // Privacy-focused default
participateInLeaderboards: true, // Core feature
showInGlobalRankings: true, // Core feature
allowRankingComparison: true,
allowAnalytics: true, // Needed for game improvement
allowMarketing: false, // User should opt-in
shareDataWithPartners: false, // User should opt-in
allowContactByEmail: true, // Important notifications
allowContactBySMS: false, // User should opt-in
allowPushNotifications: true, // Core functionality
allowProfileSearch: false, // Privacy-focused
showInPlayerDirectory: false, // Privacy-focused
allowRecommendations: true, // Improves experience
updatedAt: types.NewTimestamp(),
}
}
// NewPrivacySettings creates privacy settings with specified values
func NewPrivacySettings(
profileVisibility ProfileVisibility,
showStatistics bool,
allowFriendRequests bool,
) *PrivacySettings {
settings := NewDefaultPrivacySettings()
settings.profileVisibility = profileVisibility
settings.showStatistics = showStatistics
settings.allowFriendRequests = allowFriendRequests
settings.markUpdated()
return settings
}
// Getters
// ProfileVisibility returns the profile visibility setting
func (ps *PrivacySettings) ProfileVisibility() ProfileVisibility {
return ps.profileVisibility
}
// ShowRealName returns true if real name should be shown
func (ps *PrivacySettings) ShowRealName() bool {
return ps.showRealName
}
// ShowEmail returns true if email should be shown
func (ps *PrivacySettings) ShowEmail() bool {
return ps.showEmail
}
// ShowDateOfBirth returns true if date of birth should be shown
func (ps *PrivacySettings) ShowDateOfBirth() bool {
return ps.showDateOfBirth
}
// ShowLocation returns true if location should be shown
func (ps *PrivacySettings) ShowLocation() bool {
return ps.showLocation
}
// ShowStatistics returns true if statistics should be shown
func (ps *PrivacySettings) ShowStatistics() bool {
return ps.showStatistics
}
// ShowGameHistory returns true if game history should be shown
func (ps *PrivacySettings) ShowGameHistory() bool {
return ps.showGameHistory
}
// ShowAchievements returns true if achievements should be shown
func (ps *PrivacySettings) ShowAchievements() bool {
return ps.showAchievements
}
// ShowRankings returns true if rankings should be shown
func (ps *PrivacySettings) ShowRankings() bool {
return ps.showRankings
}
// AllowFriendRequests returns true if friend requests are allowed
func (ps *PrivacySettings) AllowFriendRequests() bool {
return ps.allowFriendRequests
}
// AllowGameInvitations returns true if game invitations are allowed
func (ps *PrivacySettings) AllowGameInvitations() bool {
return ps.allowGameInvitations
}
// AllowMessages returns true if messages are allowed
func (ps *PrivacySettings) AllowMessages() bool {
return ps.allowMessages
}
// ShowOnlineStatus returns true if online status should be shown
func (ps *PrivacySettings) ShowOnlineStatus() bool {
return ps.showOnlineStatus
}
// ParticipateInLeaderboards returns true if user participates in leaderboards
func (ps *PrivacySettings) ParticipateInLeaderboards() bool {
return ps.participateInLeaderboards
}
// ShowInGlobalRankings returns true if user should appear in global rankings
func (ps *PrivacySettings) ShowInGlobalRankings() bool {
return ps.showInGlobalRankings
}
// AllowRankingComparison returns true if ranking comparison is allowed
func (ps *PrivacySettings) AllowRankingComparison() bool {
return ps.allowRankingComparison
}
// AllowAnalytics returns true if analytics are allowed
func (ps *PrivacySettings) AllowAnalytics() bool {
return ps.allowAnalytics
}
// AllowMarketing returns true if marketing is allowed
func (ps *PrivacySettings) AllowMarketing() bool {
return ps.allowMarketing
}
// ShareDataWithPartners returns true if data sharing with partners is allowed
func (ps *PrivacySettings) ShareDataWithPartners() bool {
return ps.shareDataWithPartners
}
// AllowContactByEmail returns true if email contact is allowed
func (ps *PrivacySettings) AllowContactByEmail() bool {
return ps.allowContactByEmail
}
// AllowContactBySMS returns true if SMS contact is allowed
func (ps *PrivacySettings) AllowContactBySMS() bool {
return ps.allowContactBySMS
}
// AllowPushNotifications returns true if push notifications are allowed
func (ps *PrivacySettings) AllowPushNotifications() bool {
return ps.allowPushNotifications
}
// AllowProfileSearch returns true if profile search is allowed
func (ps *PrivacySettings) AllowProfileSearch() bool {
return ps.allowProfileSearch
}
// ShowInPlayerDirectory returns true if user should appear in player directory
func (ps *PrivacySettings) ShowInPlayerDirectory() bool {
return ps.showInPlayerDirectory
}
// AllowRecommendations returns true if recommendations are allowed
func (ps *PrivacySettings) AllowRecommendations() bool {
return ps.allowRecommendations
}
// UpdatedAt returns the last update timestamp
func (ps *PrivacySettings) UpdatedAt() types.Timestamp {
return ps.updatedAt
}
// Business methods
// SetProfileVisibility sets the profile visibility
func (ps *PrivacySettings) SetProfileVisibility(visibility ProfileVisibility) error {
validVisibilities := []ProfileVisibility{
ProfileVisibilityPublic,
ProfileVisibilityFriends,
ProfileVisibilityPrivate,
ProfileVisibilityLimited,
}
isValid := false
for _, valid := range validVisibilities {
if visibility == valid {
isValid = true
break
}
}
if !isValid {
return errors.ErrValidationFailed("profile_visibility", "invalid profile visibility")
}
ps.profileVisibility = visibility
ps.markUpdated()
return nil
}
// SetProfileInfoVisibility sets which profile information is visible
func (ps *PrivacySettings) SetProfileInfoVisibility(
showRealName bool,
showEmail bool,
showDateOfBirth bool,
showLocation bool,
) {
ps.showRealName = showRealName
ps.showEmail = showEmail
ps.showDateOfBirth = showDateOfBirth
ps.showLocation = showLocation
ps.markUpdated()
}
// SetStatisticsVisibility sets which statistics are visible
func (ps *PrivacySettings) SetStatisticsVisibility(
showStatistics bool,
showGameHistory bool,
showAchievements bool,
showRankings bool,
) {
ps.showStatistics = showStatistics
ps.showGameHistory = showGameHistory
ps.showAchievements = showAchievements
ps.showRankings = showRankings
ps.markUpdated()
}
// SetSocialSettings sets social interaction preferences
func (ps *PrivacySettings) SetSocialSettings(
allowFriendRequests bool,
allowGameInvitations bool,
allowMessages bool,
showOnlineStatus bool,
) {
ps.allowFriendRequests = allowFriendRequests
ps.allowGameInvitations = allowGameInvitations
ps.allowMessages = allowMessages
ps.showOnlineStatus = showOnlineStatus
ps.markUpdated()
}
// SetLeaderboardSettings sets leaderboard participation preferences
func (ps *PrivacySettings) SetLeaderboardSettings(
participateInLeaderboards bool,
showInGlobalRankings bool,
allowRankingComparison bool,
) {
ps.participateInLeaderboards = participateInLeaderboards
ps.showInGlobalRankings = showInGlobalRankings
ps.allowRankingComparison = allowRankingComparison
ps.markUpdated()
}
// SetDataCollectionSettings sets data collection preferences
func (ps *PrivacySettings) SetDataCollectionSettings(
allowAnalytics bool,
allowMarketing bool,
shareDataWithPartners bool,
) {
ps.allowAnalytics = allowAnalytics
ps.allowMarketing = allowMarketing
ps.shareDataWithPartners = shareDataWithPartners
ps.markUpdated()
}
// SetCommunicationSettings sets communication preferences
func (ps *PrivacySettings) SetCommunicationSettings(
allowContactByEmail bool,
allowContactBySMS bool,
allowPushNotifications bool,
) {
ps.allowContactByEmail = allowContactByEmail
ps.allowContactBySMS = allowContactBySMS
ps.allowPushNotifications = allowPushNotifications
ps.markUpdated()
}
// SetDiscoverySettings sets search and discovery preferences
func (ps *PrivacySettings) SetDiscoverySettings(
allowProfileSearch bool,
showInPlayerDirectory bool,
allowRecommendations bool,
) {
ps.allowProfileSearch = allowProfileSearch
ps.showInPlayerDirectory = showInPlayerDirectory
ps.allowRecommendations = allowRecommendations
ps.markUpdated()
}
// ApplyPrivacyTemplate applies a privacy template
func (ps *PrivacySettings) ApplyPrivacyTemplate(template PrivacyTemplate) {
switch template {
case PrivacyTemplatePublic:
ps.applyPublicTemplate()
case PrivacyTemplateBalanced:
ps.applyBalancedTemplate()
case PrivacyTemplatePrivate:
ps.applyPrivateTemplate()
case PrivacyTemplateMinimal:
ps.applyMinimalTemplate()
}
ps.markUpdated()
}
// Query methods
// IsProfilePublic returns true if profile is publicly visible
func (ps *PrivacySettings) IsProfilePublic() bool {
return ps.profileVisibility == ProfileVisibilityPublic
}
// IsProfilePrivate returns true if profile is completely private
func (ps *PrivacySettings) IsProfilePrivate() bool {
return ps.profileVisibility == ProfileVisibilityPrivate
}
// CanBeContactedByEmail returns true if user can be contacted by email
func (ps *PrivacySettings) CanBeContactedByEmail() bool {
return ps.allowContactByEmail
}
// CanReceiveGameInvitations returns true if user can receive game invitations
func (ps *PrivacySettings) CanReceiveGameInvitations() bool {
return ps.allowGameInvitations
}
// HasDataSharingEnabled returns true if any data sharing is enabled
func (ps *PrivacySettings) HasDataSharingEnabled() bool {
return ps.allowAnalytics || ps.allowMarketing || ps.shareDataWithPartners
}
// IsDiscoverable returns true if user can be discovered by others
func (ps *PrivacySettings) IsDiscoverable() bool {
return ps.allowProfileSearch || ps.showInPlayerDirectory
}
// GetPrivacyLevel returns a privacy level score (0-100, higher = more private)
func (ps *PrivacySettings) GetPrivacyLevel() int {
score := 0
// Profile visibility (0-25 points)
switch ps.profileVisibility {
case ProfileVisibilityPrivate:
score += 25
case ProfileVisibilityLimited:
score += 15
case ProfileVisibilityFriends:
score += 10
case ProfileVisibilityPublic:
score += 0
}
// Profile information visibility (0-20 points)
if !ps.showRealName { score += 5 }
if !ps.showEmail { score += 5 }
if !ps.showDateOfBirth { score += 5 }
if !ps.showLocation { score += 5 }
// Social settings (0-15 points)
if !ps.allowFriendRequests { score += 3 }
if !ps.allowGameInvitations { score += 3 }
if !ps.allowMessages { score += 4 }
if !ps.showOnlineStatus { score += 5 }
// Data collection (0-20 points)
if !ps.allowAnalytics { score += 5 }
if !ps.allowMarketing { score += 7 }
if !ps.shareDataWithPartners { score += 8 }
// Discovery settings (0-20 points)
if !ps.allowProfileSearch { score += 10 }
if !ps.showInPlayerDirectory { score += 10 }
return score
}
// Validation
// Validate performs validation on the privacy settings
func (ps *PrivacySettings) Validate() *types.ValidationResult {
result := types.NewValidationResult()
// Validate profile visibility
validVisibilities := []ProfileVisibility{
ProfileVisibilityPublic,
ProfileVisibilityFriends,
ProfileVisibilityPrivate,
ProfileVisibilityLimited,
}
isValidVisibility := false
for _, valid := range validVisibilities {
if ps.profileVisibility == valid {
isValidVisibility = true
break
}
}
if !isValidVisibility {
result.AddError("invalid profile visibility")
}
// Logic validation
if ps.profileVisibility == ProfileVisibilityPrivate {
// If profile is private, certain things shouldn't be visible
if ps.showRealName || ps.showEmail || ps.allowProfileSearch || ps.showInPlayerDirectory {
result.AddWarning("private profile has some public visibility settings enabled")
}
}
return result
}
// Helper methods
// markUpdated updates the timestamp
func (ps *PrivacySettings) markUpdated() {
ps.updatedAt = types.NewTimestamp()
}
// applyPublicTemplate applies the public privacy template
func (ps *PrivacySettings) applyPublicTemplate() {
ps.profileVisibility = ProfileVisibilityPublic
ps.showRealName = true
ps.showStatistics = true
ps.showGameHistory = true
ps.showAchievements = true
ps.showRankings = true
ps.allowFriendRequests = true
ps.allowGameInvitations = true
ps.allowMessages = true
ps.showOnlineStatus = true
ps.participateInLeaderboards = true
ps.showInGlobalRankings = true
ps.allowProfileSearch = true
ps.showInPlayerDirectory = true
ps.allowRecommendations = true
}
// applyBalancedTemplate applies the balanced privacy template
func (ps *PrivacySettings) applyBalancedTemplate() {
ps.profileVisibility = ProfileVisibilityLimited
ps.showRealName = false
ps.showStatistics = true
ps.showGameHistory = false
ps.showAchievements = true
ps.showRankings = true
ps.allowFriendRequests = true
ps.allowGameInvitations = true
ps.allowMessages = false
ps.showOnlineStatus = false
ps.participateInLeaderboards = true
ps.showInGlobalRankings = true
ps.allowProfileSearch = false
ps.showInPlayerDirectory = false
ps.allowRecommendations = true
}
// applyPrivateTemplate applies the private privacy template
func (ps *PrivacySettings) applyPrivateTemplate() {
ps.profileVisibility = ProfileVisibilityPrivate
ps.showRealName = false
ps.showEmail = false
ps.showDateOfBirth = false
ps.showLocation = false
ps.showStatistics = false
ps.showGameHistory = false
ps.showAchievements = false
ps.showRankings = false
ps.allowFriendRequests = false
ps.allowGameInvitations = false
ps.allowMessages = false
ps.showOnlineStatus = false
ps.participateInLeaderboards = false
ps.showInGlobalRankings = false
ps.allowProfileSearch = false
ps.showInPlayerDirectory = false
ps.allowMarketing = false
ps.shareDataWithPartners = false
}
// applyMinimalTemplate applies the minimal privacy template (essential features only)
func (ps *PrivacySettings) applyMinimalTemplate() {
ps.profileVisibility = ProfileVisibilityFriends
ps.showRealName = false
ps.showEmail = false
ps.showDateOfBirth = false
ps.showLocation = false
ps.showStatistics = true // Keep for core functionality
ps.showGameHistory = false
ps.showAchievements = true // Keep for core functionality
ps.showRankings = true // Keep for core functionality
ps.allowFriendRequests = true // Essential social feature
ps.allowGameInvitations = true // Essential game feature
ps.allowMessages = false
ps.showOnlineStatus = false
ps.participateInLeaderboards = true // Core feature
ps.showInGlobalRankings = true // Core feature
ps.allowProfileSearch = false
ps.showInPlayerDirectory = false
ps.allowAnalytics = true // Needed for game improvement
ps.allowMarketing = false
ps.shareDataWithPartners = false
}
// ToSnapshot creates a read-only snapshot
func (ps *PrivacySettings) ToSnapshot() *PrivacySettingsSnapshot {
return &PrivacySettingsSnapshot{
ProfileVisibility: ps.profileVisibility,
ShowRealName: ps.showRealName,
ShowEmail: ps.showEmail,
ShowDateOfBirth: ps.showDateOfBirth,
ShowLocation: ps.showLocation,
ShowStatistics: ps.showStatistics,
ShowGameHistory: ps.showGameHistory,
ShowAchievements: ps.showAchievements,
ShowRankings: ps.showRankings,
AllowFriendRequests: ps.allowFriendRequests,
AllowGameInvitations: ps.allowGameInvitations,
AllowMessages: ps.allowMessages,
ShowOnlineStatus: ps.showOnlineStatus,
ParticipateInLeaderboards: ps.participateInLeaderboards,
ShowInGlobalRankings: ps.showInGlobalRankings,
AllowRankingComparison: ps.allowRankingComparison,
AllowAnalytics: ps.allowAnalytics,
AllowMarketing: ps.allowMarketing,
ShareDataWithPartners: ps.shareDataWithPartners,
AllowContactByEmail: ps.allowContactByEmail,
AllowContactBySMS: ps.allowContactBySMS,
AllowPushNotifications: ps.allowPushNotifications,
AllowProfileSearch: ps.allowProfileSearch,
ShowInPlayerDirectory: ps.showInPlayerDirectory,
AllowRecommendations: ps.allowRecommendations,
UpdatedAt: ps.updatedAt,
}
}
// Privacy templates
type PrivacyTemplate string
const (
PrivacyTemplatePublic PrivacyTemplate = "public"
PrivacyTemplateBalanced PrivacyTemplate = "balanced"
PrivacyTemplatePrivate PrivacyTemplate = "private"
PrivacyTemplateMinimal PrivacyTemplate = "minimal"
)
// PrivacySettingsSnapshot represents a read-only view of privacy settings
type PrivacySettingsSnapshot struct {
ProfileVisibility ProfileVisibility `json:"profile_visibility"`
ShowRealName bool `json:"show_real_name"`
ShowEmail bool `json:"show_email"`
ShowDateOfBirth bool `json:"show_date_of_birth"`
ShowLocation bool `json:"show_location"`
ShowStatistics bool `json:"show_statistics"`
ShowGameHistory bool `json:"show_game_history"`
ShowAchievements bool `json:"show_achievements"`
ShowRankings bool `json:"show_rankings"`
AllowFriendRequests bool `json:"allow_friend_requests"`
AllowGameInvitations bool `json:"allow_game_invitations"`
AllowMessages bool `json:"allow_messages"`
ShowOnlineStatus bool `json:"show_online_status"`
ParticipateInLeaderboards bool `json:"participate_in_leaderboards"`
ShowInGlobalRankings bool `json:"show_in_global_rankings"`
AllowRankingComparison bool `json:"allow_ranking_comparison"`
AllowAnalytics bool `json:"allow_analytics"`
AllowMarketing bool `json:"allow_marketing"`
ShareDataWithPartners bool `json:"share_data_with_partners"`
AllowContactByEmail bool `json:"allow_contact_by_email"`
AllowContactBySMS bool `json:"allow_contact_by_sms"`
AllowPushNotifications bool `json:"allow_push_notifications"`
AllowProfileSearch bool `json:"allow_profile_search"`
ShowInPlayerDirectory bool `json:"show_in_player_directory"`
AllowRecommendations bool `json:"allow_recommendations"`
UpdatedAt types.Timestamp `json:"updated_at"`
}
// GetPrivacyLevel returns the privacy level from the snapshot
func (pss *PrivacySettingsSnapshot) GetPrivacyLevel() int {
score := 0
switch pss.ProfileVisibility {
case ProfileVisibilityPrivate:
score += 25
case ProfileVisibilityLimited:
score += 15
case ProfileVisibilityFriends:
score += 10
case ProfileVisibilityPublic:
score += 0
}
if !pss.ShowRealName { score += 5 }
if !pss.ShowEmail { score += 5 }
if !pss.ShowDateOfBirth { score += 5 }
if !pss.ShowLocation { score += 5 }
if !pss.AllowFriendRequests { score += 3 }
if !pss.AllowGameInvitations { score += 3 }
if !pss.AllowMessages { score += 4 }
if !pss.ShowOnlineStatus { score += 5 }
if !pss.AllowAnalytics { score += 5 }
if !pss.AllowMarketing { score += 7 }
if !pss.ShareDataWithPartners { score += 8 }
if !pss.AllowProfileSearch { score += 10 }
if !pss.ShowInPlayerDirectory { score += 10 }
return score
}