Skip to main content

User Entities

Entities for user accounts, profiles, authentication, and social relationships.

Core Authentication Entities

User

Purpose: Core user account entity representing an angler, charter captain, DNR researcher, or admin.

Key Fields:

  • Id (Guid): Unique identifier
  • Email (string, required): User's email address
  • PasswordHash (string, required): Hashed password (consider migrating to Cognito-only)
  • CognitoId (string, required): AWS Cognito user ID for authentication
  • StripeCustomerId (string?): Stripe customer ID for subscription billing
  • SubscriptionTier: Free, Basic, or Pro tier
  • Role: Standard, DNR, Researcher, Admin, or Moderator
  • UnitSystem: Metric or Imperial preference
  • DefaultDataSharingConsent: Default consent level for data sharing
  • DefaultAllowDnrAccess: Default DNR access permission

Relationships:

  • One-to-many: FishingSessions, FishingLogEntries, GearSetups, Posts, Comments, etc.
  • One-to-one: CharterCaptain (if user is a charter captain)
  • Many-to-many: Friends (via UserFriend), FavoriteSpecies (via UserFavoriteSpecies), Circles (via CircleMember)

Usage Patterns:

// Get user with all relationships
var user = context.Users
.Include(u => u.FishingSessions)
.Include(u => u.GearSetups)
.Include(u => u.FavoriteSpecies)
.FirstOrDefault(u => u.Id == userId);

// Check if user is DNR
if (user.Role == UserRole.DNR) {{ /* DNR access */ }}

// Get user's consent level
var consentLevel = user.DefaultDataSharingConsent;

Considerations:

  • Future: Consider removing PasswordHash if fully migrating to Cognito
  • Future: Add ProfileImageUrl, Bio, Location for social features
  • Future: Add LastLoginAt, LoginCount for analytics
  • Future: Add EmailVerified, PhoneNumber, PhoneVerified for 2FA
  • Future: Add PreferredLanguage for internationalization
  • Future: Add Timezone for proper time display
  • Security: Ensure CognitoId is always set and validated
  • Privacy: IsProfilePrivate controls visibility of profile

UserFriend

Purpose: Many-to-many relationship for mutual friendships between users.

Key Fields:

  • UserId: User who has the friend
  • FriendId: The friend user
  • CreatedAt: When friendship was established

Relationships:

  • Many-to-one: User (as friend requester)
  • Many-to-one: User (as friend)

Usage Patterns:

// Get user's friends
var friends = context.UserFriends
.Where(uf => uf.UserId == userId)
.Select(uf => uf.Friend)
.ToList();

// Check if users are friends
var areFriends = context.UserFriends
.Any(uf => (uf.UserId == user1Id && uf.FriendId == user2Id) ||
(uf.UserId == user2Id && uf.FriendId == user1Id));

Considerations:

  • Future: Add Status enum (Pending, Accepted, Blocked) for friend requests
  • Future: Add FriendshipType (Close, Acquaintance) for relationship strength
  • Future: Add Notes for personal notes about friend
  • Index: Unique constraint on (UserId, FriendId) prevents duplicates

UserFollow

Purpose: One-way follow relationship (Twitter/Instagram style) for following other users.

Key Fields:

  • FollowerId: User doing the following
  • FollowingId: User being followed
  • NotifyOnPosts: Whether to notify follower of new posts
  • NotifyOnCatches: Whether to notify follower of new catches

Relationships:

  • Many-to-one: User (as follower)
  • Many-to-one: User (as following)

Usage Patterns:

// Get users that a user follows
var following = context.UserFollows
.Where(uf => uf.FollowerId == userId)
.Select(uf => uf.Following)
.ToList();

// Get user's followers
var followers = context.UserFollows
.Where(uf => uf.FollowingId == userId)
.Select(uf => uf.Follower)
.ToList();

Considerations:

  • Future: Add FollowType (Public, Private) for private accounts
  • Future: Add Muted flag to mute notifications without unfollowing
  • Future: Add FollowedAt timestamp (currently using CreatedAt)
  • Index: Unique constraint on (FollowerId, FollowingId)

Circle

Purpose: Friend circles for sharing private logs with custom groups of users.

Key Fields:

  • OwnerUserId: User who created the circle
  • Name: Circle name (e.g., "Fishing Buddies", "Family")
  • CreatedAt, UpdatedAt: Timestamps

Relationships:

  • Many-to-one: User (owner)
  • One-to-many: CircleMembers

Usage Patterns:

// Get user's circles
var circles = context.Circles
.Where(c => c.OwnerUserId == userId)
.Include(c => c.Members)
.ToList();

// Share log with circle
logEntry.SharedWithCircleId = circleId;
logEntry.Visibility = LogVisibility.Circle;

Considerations:

  • Future: Add Description for circle purpose
  • Future: Add Color or Icon for visual identification
  • Future: Add IsDefault flag for default sharing circle
  • Future: Add MaxMembers limit
  • Future: Consider CircleImage for custom circle images

CircleMember

Purpose: Many-to-many relationship between Circles and Users (members).

Key Fields:

  • CircleId: The circle
  • UserId: The member user
  • AddedAt: When user was added to circle

Relationships:

  • Many-to-one: Circle
  • Many-to-one: User

Usage Patterns:

// Add member to circle
var member = new CircleMember
{{
CircleId = circleId,
UserId = userId,
AddedAt = DateTime.UtcNow
}};

// Get circle members
var members = context.CircleMembers
.Where(cm => cm.CircleId == circleId)
.Select(cm => cm.User)
.ToList();

Considerations:

  • Future: Add Role enum (Member, Admin) for circle management
  • Future: Add InvitedByUserId to track who invited the member
  • Future: Add Status (Active, Removed) for soft removal
  • Index: Unique constraint on (CircleId, UserId)

UserFavoriteSpecies

Purpose: Many-to-many relationship for users' favorite fish species.

Key Fields:

  • UserId: The user
  • FishSpeciesId: The favorite species
  • AddedAt: When added to favorites

Relationships:

  • Many-to-one: User
  • Many-to-one: FishSpecies

Usage Patterns:

// Add favorite species
var favorite = new UserFavoriteSpecies
{{
UserId = userId,
FishSpeciesId = speciesId,
AddedAt = DateTime.UtcNow
}};

// Get user's favorite species
var favorites = context.UserFavoriteSpecies
.Where(ufs => ufs.UserId == userId)
.Select(ufs => ufs.FishSpecies)
.ToList();

Considerations:

  • Future: Add Priority or Order for ranking favorites
  • Future: Add Notes for why it's a favorite
  • Future: Add CaughtCount denormalized count
  • Index: Unique constraint on (UserId, FishSpeciesId)

Additional User Entities

UserProfile

Purpose: Extended user profile information.

Key Fields:

  • Id (int): Unique identifier
  • UserId: Associated user
  • Bio: User biography
  • Location: User location
  • ProfileImageUrl: Profile image URL
  • CoverImageUrl: Cover image URL
  • Website: Personal website
  • SocialLinks: Social media links (JSON)
  • FishingExperience: Years of experience
  • FavoriteFishingMethod: Favorite fishing method
  • IsProfilePrivate: Profile privacy flag

Relationships:

  • Many-to-one: User (one-to-one)

Usage Patterns:

// Get user profile
var profile = context.UserProfiles
.Include(up => up.User)
.FirstOrDefault(up => up.UserId == userId);

UserBan

Purpose: User ban records for moderation.

Key Fields:

  • Id (int): Unique identifier
  • UserId: Banned user
  • BannedByUserId: Admin who banned
  • BanReason: Ban reason
  • BanType: Temporary, Permanent
  • StartDate: Ban start date
  • EndDate: Ban end date (if temporary)
  • IsActive: Whether ban is active

Relationships:

  • Many-to-one: User (banned user and admin)

UserReport

Purpose: User reports for content moderation.

Key Fields:

  • Id (int): Unique identifier
  • ReportedByUserId: Reporting user
  • ReportedUserId: Reported user
  • ReportType: Spam, Harassment, Inappropriate, etc.
  • ReportReason: Report reason
  • Status: Pending, Reviewed, Resolved, Dismissed
  • ReviewedByUserId: Admin reviewer
  • ReviewedAt: Review timestamp

Relationships:

  • Many-to-one: User (reporter, reported user, reviewer)

CircleApplication

Purpose: Circle membership applications.

Key Fields:

  • Id (int): Unique identifier
  • CircleId: Applied circle
  • ApplicantUserId: Applicant user
  • Status: Pending, Approved, Rejected
  • AppliedAt: Application timestamp
  • ReviewedAt: Review timestamp

Relationships:

  • Many-to-one: Circle, User

CircleShare

Purpose: Multiple circle sharing for posts (replaces deprecated single circle sharing).

Key Fields:

  • Id (int): Unique identifier
  • PostId: Shared post
  • CircleId: Shared circle
  • SharedAt: Share timestamp

Relationships:

  • Many-to-one: Post, Circle

UserDefinedModel

Purpose: User-defined 3D models for customization.

Key Fields:

  • Id (int): Unique identifier
  • UserId: Model owner
  • ModelName: Model name
  • ModelType: Model type
  • ModelData: Model data (JSON)
  • IsPublic: Public model flag

Relationships:

  • Many-to-one: User