DeutschLernen/GermanApp/Domain/Entities/User.cs
Lasse Rune Hansen 50f1b8a8dc feat(backend): Implement mandatory authentication and admin module
- Add Role property to User entity with migration
- Create BootstrapController for first admin user creation
- Remove [AllowAnonymous] from all learning content controllers
- Create AdminController with admin-only endpoints
- Create AdminService for user management
- Create UserReportService for progress reports
- Add UserRepository implementation
- Update AuthService with role support

feat(frontend): Implement authentication system
- Add AuthStore with React context for auth state management
- Create Login, Register, Landing, and Home pages
- Add ProtectedRoute and AdminRoute components
- Create Auth API types and client
- Configure Vite with @/ path alias
- Add comprehensive CSS styles for auth and landing pages

BREAKING CHANGE: All learning content now requires authentication.
Users must register and sign in before accessing lessons, quizzes, and stories.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-14 12:42:15 +02:00

106 lines
2.8 KiB
C#

namespace GermanApp.Domain.Entities;
/// <summary>
/// Represents a user in the DeutschLernen system.
/// </summary>
public class User
{
public int Id { get; private set; }
public string Username { get; private set; } = string.Empty;
public string Email { get; private set; } = string.Empty;
public string PasswordHash { get; private set; } = string.Empty;
public string CurrentLevel { get; private set; } = "A1";
public string Role { get; private set; } = "User"; // Default role is "User", "Admin" for administrators
public int Streak { get; private set; }
public int TotalPoints { get; private set; }
public DateTime CreatedAt { get; private set; }
/// <summary>
/// Constructor for EF Core deserialization.
/// </summary>
private User() { }
/// <summary>
/// Factory method to create a new user.
/// </summary>
public static User Create(string username, string email, string passwordHash)
{
return new User
{
Username = username,
Email = email.ToLowerInvariant(),
PasswordHash = passwordHash,
CurrentLevel = "A1",
Streak = 0,
TotalPoints = 0,
CreatedAt = DateTime.UtcNow
};
}
/// <summary>
/// Updates user's gamification stats.
/// </summary>
public void AddPoints(int points)
{
TotalPoints += points;
}
/// <summary>
/// Updates user's streak.
/// </summary>
public void UpdateStreak(int streak)
{
Streak = streak;
}
/// <summary>
/// Updates user's current level.
/// </summary>
public void UpdateLevel(string level)
{
CurrentLevel = level;
}
/// <summary>
/// Changes user's email.
/// </summary>
public void ChangeEmail(string newEmail)
{
Email = newEmail?.ToLowerInvariant() ?? string.Empty;
}
/// <summary>
/// Changes user's password hash.
/// </summary>
public void ChangePassword(string newPasswordHash)
{
PasswordHash = newPasswordHash;
}
/// <summary>
/// Assigns admin role to user (bootstrap only).
/// </summary>
public void AssignAdminRole()
{
Role = "Admin";
}
/// <summary>
/// Sets the user's role.
/// </summary>
/// <param name="role">The role to assign (User or Admin)</param>
public void SetRole(string role)
{
if (role != "Admin" && role != "User")
throw new ArgumentException("Role must be 'Admin' or 'User'.", nameof(role));
Role = role;
}
/// <summary>
/// Checks if user has admin role.
/// </summary>
public bool IsAdmin() => Role == "Admin";
// Navigation properties
public virtual ICollection<StoryProgress> StoryProgress { get; private set; } = new List<StoryProgress>();
}