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 identifierEmail(string, required): User's email addressPasswordHash(string, required): Hashed password (consider migrating to Cognito-only)CognitoId(string, required): AWS Cognito user ID for authenticationStripeCustomerId(string?): Stripe customer ID for subscription billingSubscriptionTier: Free, Basic, or Pro tierRole: Standard, DNR, Researcher, Admin, or ModeratorUnitSystem: Metric or Imperial preferenceDefaultDataSharingConsent: Default consent level for data sharingDefaultAllowDnrAccess: 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
PasswordHashif fully migrating to Cognito - Future: Add
ProfileImageUrl,Bio,Locationfor social features - Future: Add
LastLoginAt,LoginCountfor analytics - Future: Add
EmailVerified,PhoneNumber,PhoneVerifiedfor 2FA - Future: Add
PreferredLanguagefor internationalization - Future: Add
Timezonefor proper time display - Security: Ensure
CognitoIdis always set and validated - Privacy:
IsProfilePrivatecontrols visibility of profile
UserFriend
Purpose: Many-to-many relationship for mutual friendships between users.
Key Fields:
UserId: User who has the friendFriendId: The friend userCreatedAt: 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
Statusenum (Pending, Accepted, Blocked) for friend requests - Future: Add
FriendshipType(Close, Acquaintance) for relationship strength - Future: Add
Notesfor 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 followingFollowingId: User being followedNotifyOnPosts: Whether to notify follower of new postsNotifyOnCatches: 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
Mutedflag to mute notifications without unfollowing - Future: Add
FollowedAttimestamp (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 circleName: 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
Descriptionfor circle purpose - Future: Add
ColororIconfor visual identification - Future: Add
IsDefaultflag for default sharing circle - Future: Add
MaxMemberslimit - Future: Consider
CircleImagefor custom circle images
CircleMember
Purpose: Many-to-many relationship between Circles and Users (members).
Key Fields:
CircleId: The circleUserId: The member userAddedAt: 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
Roleenum (Member, Admin) for circle management - Future: Add
InvitedByUserIdto 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 userFishSpeciesId: The favorite speciesAddedAt: 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
PriorityorOrderfor ranking favorites - Future: Add
Notesfor why it's a favorite - Future: Add
CaughtCountdenormalized count - Index: Unique constraint on (UserId, FishSpeciesId)
Additional User Entities
UserProfile
Purpose: Extended user profile information.
Key Fields:
Id(int): Unique identifierUserId: Associated userBio: User biographyLocation: User locationProfileImageUrl: Profile image URLCoverImageUrl: Cover image URLWebsite: Personal websiteSocialLinks: Social media links (JSON)FishingExperience: Years of experienceFavoriteFishingMethod: Favorite fishing methodIsProfilePrivate: 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 identifierUserId: Banned userBannedByUserId: Admin who bannedBanReason: Ban reasonBanType: Temporary, PermanentStartDate: Ban start dateEndDate: 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 identifierReportedByUserId: Reporting userReportedUserId: Reported userReportType: Spam, Harassment, Inappropriate, etc.ReportReason: Report reasonStatus: Pending, Reviewed, Resolved, DismissedReviewedByUserId: Admin reviewerReviewedAt: Review timestamp
Relationships:
- Many-to-one: User (reporter, reported user, reviewer)
CircleApplication
Purpose: Circle membership applications.
Key Fields:
Id(int): Unique identifierCircleId: Applied circleApplicantUserId: Applicant userStatus: Pending, Approved, RejectedAppliedAt: Application timestampReviewedAt: 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 identifierPostId: Shared postCircleId: Shared circleSharedAt: Share timestamp
Relationships:
- Many-to-one: Post, Circle
UserDefinedModel
Purpose: User-defined 3D models for customization.
Key Fields:
Id(int): Unique identifierUserId: Model ownerModelName: Model nameModelType: Model typeModelData: Model data (JSON)IsPublic: Public model flag
Relationships:
- Many-to-one: User
Related Documentation
- User Profile - User profile features
- Social Features - Circle sharing and privacy