aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Data/Entities/User.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Data/Entities/User.cs')
-rw-r--r--Jellyfin.Data/Entities/User.cs283
1 files changed, 192 insertions, 91 deletions
diff --git a/Jellyfin.Data/Entities/User.cs b/Jellyfin.Data/Entities/User.cs
index a81d5215b..17913959e 100644
--- a/Jellyfin.Data/Entities/User.cs
+++ b/Jellyfin.Data/Entities/User.cs
@@ -2,11 +2,20 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
+using System.Globalization;
+using System.Linq;
+using System.Text.Json.Serialization;
+using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
public partial class User
{
+ /// <summary>
+ /// The values being delimited here are Guids, so commas work as they do not appear in Guids.
+ /// </summary>
+ private const char Delimiter = ',';
+
partial void Init();
/// <summary>
@@ -18,69 +27,90 @@ namespace Jellyfin.Data.Entities
Permissions = new HashSet<Permission>();
ProviderMappings = new HashSet<ProviderMapping>();
Preferences = new HashSet<Preference>();
+ AccessSchedules = new HashSet<AccessSchedule>();
Init();
}
/// <summary>
- /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
- /// </summary>
- public static User CreateUserUnsafe()
- {
- return new User();
- }
-
- /// <summary>
/// Public constructor with required data
/// </summary>
/// <param name="username"></param>
- /// <param name="mustupdatepassword"></param>
- /// <param name="audiolanguagepreference"></param>
- /// <param name="authenticationproviderid"></param>
- /// <param name="invalidloginattemptcount"></param>
- /// <param name="subtitlemode"></param>
- /// <param name="playdefaultaudiotrack"></param>
- public User(string username, bool mustupdatepassword, string audiolanguagepreference, string authenticationproviderid, int invalidloginattemptcount, string subtitlemode, bool playdefaultaudiotrack)
+ /// <param name="mustUpdatePassword"></param>
+ /// <param name="authenticationProviderId"></param>
+ /// <param name="invalidLoginAttemptCount"></param>
+ /// <param name="subtitleMode"></param>
+ /// <param name="playDefaultAudioTrack"></param>
+ public User(
+ string username,
+ bool mustUpdatePassword,
+ string authenticationProviderId,
+ int invalidLoginAttemptCount,
+ SubtitlePlaybackMode subtitleMode,
+ bool playDefaultAudioTrack)
{
- if (string.IsNullOrEmpty(username)) throw new ArgumentNullException(nameof(username));
- this.Username = username;
-
- this.MustUpdatePassword = mustupdatepassword;
-
- if (string.IsNullOrEmpty(audiolanguagepreference)) throw new ArgumentNullException(nameof(audiolanguagepreference));
- this.AudioLanguagePreference = audiolanguagepreference;
-
- if (string.IsNullOrEmpty(authenticationproviderid)) throw new ArgumentNullException(nameof(authenticationproviderid));
- this.AuthenticationProviderId = authenticationproviderid;
-
- this.InvalidLoginAttemptCount = invalidloginattemptcount;
+ if (string.IsNullOrEmpty(username))
+ {
+ throw new ArgumentNullException(nameof(username));
+ }
+
+ if (string.IsNullOrEmpty(authenticationProviderId))
+ {
+ throw new ArgumentNullException(nameof(authenticationProviderId));
+ }
+
+ Username = username;
+ MustUpdatePassword = mustUpdatePassword;
+ AuthenticationProviderId = authenticationProviderId;
+ InvalidLoginAttemptCount = invalidLoginAttemptCount;
+ SubtitleMode = subtitleMode;
+ PlayDefaultAudioTrack = playDefaultAudioTrack;
- if (string.IsNullOrEmpty(subtitlemode)) throw new ArgumentNullException(nameof(subtitlemode));
- this.SubtitleMode = subtitlemode;
-
- this.PlayDefaultAudioTrack = playdefaultaudiotrack;
-
- this.Groups = new HashSet<Group>();
- this.Permissions = new HashSet<Permission>();
- this.ProviderMappings = new HashSet<ProviderMapping>();
- this.Preferences = new HashSet<Preference>();
+ Groups = new HashSet<Group>();
+ Permissions = new HashSet<Permission>();
+ ProviderMappings = new HashSet<ProviderMapping>();
+ Preferences = new HashSet<Preference>();
+ AccessSchedules = new HashSet<AccessSchedule>();
+
+ // Set default values
+ Id = Guid.NewGuid();
+ DisplayMissingEpisodes = false;
+ DisplayCollectionsView = false;
+ HidePlayedInLatest = true;
+ RememberAudioSelections = true;
+ RememberSubtitleSelections = true;
+ EnableNextEpisodeAutoPlay = true;
+ EnableAutoLogin = false;
Init();
}
/// <summary>
+ /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
+ /// </summary>
+ public static User CreateUserUnsafe()
+ {
+ return new User();
+ }
+
+ /// <summary>
/// Static create function (for use in LINQ queries, etc.)
/// </summary>
/// <param name="username"></param>
- /// <param name="mustupdatepassword"></param>
- /// <param name="audiolanguagepreference"></param>
- /// <param name="authenticationproviderid"></param>
- /// <param name="invalidloginattemptcount"></param>
- /// <param name="subtitlemode"></param>
- /// <param name="playdefaultaudiotrack"></param>
- public static User Create(string username, bool mustupdatepassword, string audiolanguagepreference, string authenticationproviderid, int invalidloginattemptcount, string subtitlemode, bool playdefaultaudiotrack)
+ /// <param name="mustUpdatePassword"></param>
+ /// <param name="authenticationProviderId"></param>
+ /// <param name="invalidLoginAttemptCount"></param>
+ /// <param name="subtitleMode"></param>
+ /// <param name="playDefaultAudioTrack"></param>
+ public static User Create(
+ string username,
+ bool mustUpdatePassword,
+ string authenticationProviderId,
+ int invalidLoginAttemptCount,
+ SubtitlePlaybackMode subtitleMode,
+ bool playDefaultAudioTrack)
{
- return new User(username, mustupdatepassword, audiolanguagepreference, authenticationproviderid, invalidloginattemptcount, subtitlemode, playdefaultaudiotrack);
+ return new User(username, mustUpdatePassword, authenticationProviderId, invalidLoginAttemptCount, subtitleMode, playDefaultAudioTrack);
}
/*************************************************************************
@@ -92,8 +122,8 @@ namespace Jellyfin.Data.Entities
/// </summary>
[Key]
[Required]
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- public int Id { get; protected set; }
+ [JsonIgnore]
+ public Guid Id { get; set; }
/// <summary>
/// Required, Max length = 255
@@ -101,6 +131,7 @@ namespace Jellyfin.Data.Entities
[Required]
[MaxLength(255)]
[StringLength(255)]
+ [JsonPropertyName("Name")]
public string Username { get; set; }
/// <summary>
@@ -111,15 +142,21 @@ namespace Jellyfin.Data.Entities
public string Password { get; set; }
/// <summary>
+ /// Max length = 65535.
+ /// </summary>
+ [MaxLength(65535)]
+ [StringLength(65535)]
+ public string EasyPassword { get; set; }
+
+ /// <summary>
/// Required
/// </summary>
[Required]
public bool MustUpdatePassword { get; set; }
/// <summary>
- /// Required, Max length = 255
+ /// Max length = 255.
/// </summary>
- [Required]
[MaxLength(255)]
[StringLength(255)]
public string AudioLanguagePreference { get; set; }
@@ -132,12 +169,10 @@ namespace Jellyfin.Data.Entities
[StringLength(255)]
public string AuthenticationProviderId { get; set; }
- /// <summary>
- /// Max length = 65535
- /// </summary>
- [MaxLength(65535)]
- [StringLength(65535)]
- public string GroupedFolders { get; set; }
+ [Required]
+ [MaxLength(255)]
+ [StringLength(255)]
+ public string PasswordResetProviderId { get; set; }
/// <summary>
/// Required
@@ -145,36 +180,17 @@ namespace Jellyfin.Data.Entities
[Required]
public int InvalidLoginAttemptCount { get; set; }
- /// <summary>
- /// Max length = 65535
- /// </summary>
- [MaxLength(65535)]
- [StringLength(65535)]
- public string LatestItemExcludes { get; set; }
-
- public int? LoginAttemptsBeforeLockout { get; set; }
+ public DateTime LastActivityDate { get; set; }
- /// <summary>
- /// Max length = 65535
- /// </summary>
- [MaxLength(65535)]
- [StringLength(65535)]
- public string MyMediaExcludes { get; set; }
+ public DateTime LastLoginDate { get; set; }
- /// <summary>
- /// Max length = 65535
- /// </summary>
- [MaxLength(65535)]
- [StringLength(65535)]
- public string OrderedViews { get; set; }
+ public int? LoginAttemptsBeforeLockout { get; set; }
/// <summary>
- /// Required, Max length = 255
+ /// Required.
/// </summary>
[Required]
- [MaxLength(255)]
- [StringLength(255)]
- public string SubtitleMode { get; set; }
+ public SubtitlePlaybackMode SubtitleMode { get; set; }
/// <summary>
/// Required
@@ -187,21 +203,47 @@ namespace Jellyfin.Data.Entities
/// </summary>
[MaxLength(255)]
[StringLength(255)]
- public string SubtitleLanguagePrefernce { get; set; }
+ public string SubtitleLanguagePreference { get; set; }
+
+ [Required]
+ public bool DisplayMissingEpisodes { get; set; }
+
+ [Required]
+ public bool DisplayCollectionsView { get; set; }
+
+ [Required]
+ public bool EnableLocalPassword { get; set; }
- public bool? DisplayMissingEpisodes { get; set; }
+ [Required]
+ public bool HidePlayedInLatest { get; set; }
+
+ [Required]
+ public bool RememberAudioSelections { get; set; }
+
+ [Required]
+ public bool RememberSubtitleSelections { get; set; }
+
+ [Required]
+ public bool EnableNextEpisodeAutoPlay { get; set; }
- public bool? DisplayCollectionsView { get; set; }
+ [Required]
+ public bool EnableAutoLogin { get; set; }
- public bool? HidePlayedInLatest { get; set; }
+ [Required]
+ public bool EnableUserPreferenceAccess { get; set; }
- public bool? RememberAudioSelections { get; set; }
+ public int? MaxParentalAgeRating { get; set; }
- public bool? RememberSubtitleSelections { get; set; }
+ public int? RemoteClientBitrateLimit { get; set; }
- public bool? EnableNextEpisodeAutoPlay { get; set; }
+ /// <summary>
+ /// This is a temporary stopgap for until the library db is migrated.
+ /// This corresponds to the value of the index of this user in the library db.
+ /// </summary>
+ [Required]
+ public long InternalId { get; set; }
- public bool? EnableUserPreferenceAccess { get; set; }
+ public ImageInfo ProfileImage { get; set; }
/// <summary>
/// Required, ConcurrenyToken
@@ -219,17 +261,76 @@ namespace Jellyfin.Data.Entities
* Navigation properties
*************************************************************************/
[ForeignKey("Group_Groups_Id")]
- public virtual ICollection<Group> Groups { get; protected set; }
+ public ICollection<Group> Groups { get; protected set; }
[ForeignKey("Permission_Permissions_Id")]
- public virtual ICollection<Permission> Permissions { get; protected set; }
+ public ICollection<Permission> Permissions { get; protected set; }
[ForeignKey("ProviderMapping_ProviderMappings_Id")]
- public virtual ICollection<ProviderMapping> ProviderMappings { get; protected set; }
+ public ICollection<ProviderMapping> ProviderMappings { get; protected set; }
[ForeignKey("Preference_Preferences_Id")]
- public virtual ICollection<Preference> Preferences { get; protected set; }
+ public ICollection<Preference> Preferences { get; protected set; }
+
+ public ICollection<AccessSchedule> AccessSchedules { get; protected set; }
+
+ public bool HasPermission(PermissionKind permission)
+ {
+ return Permissions.Select(p => p.Kind).Contains(permission);
+ }
+
+ public void SetPermission(PermissionKind kind, bool value)
+ {
+ var permissionObj = Permissions.First(p => p.Kind == kind);
+ permissionObj.Value = value;
+ }
+
+ public string[] GetPreference(PreferenceKind preference)
+ {
+ return Preferences
+ .Where(p => p.Kind == preference)
+ .Select(p => p.Value)
+ .First()
+ .Split(Delimiter);
+ }
+
+ public void SetPreference(PreferenceKind preference, string[] values)
+ {
+ var pref = Preferences.First(p => p.Kind == preference);
+
+ pref.Value = string.Join(Delimiter.ToString(CultureInfo.InvariantCulture), values);
+ }
+
+ public bool IsParentalScheduleAllowed()
+ {
+ var schedules = this.AccessSchedules;
+ return schedules.Count == 0 || schedules.Any(i => IsParentalScheduleAllowed(i, DateTime.Now));
+ }
+
+ public bool IsFolderGrouped(Guid id)
+ {
+ return GetPreference(PreferenceKind.GroupedFolders).Any(i => new Guid(i) == id);
+ }
+
+ private bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
+ {
+ if (date.Kind != DateTimeKind.Utc)
+ {
+ throw new ArgumentException("Utc date expected");
+ }
+
+ var localTime = date.ToLocalTime();
+
+ return DayOfWeekHelper.GetDaysOfWeek(schedule.DayOfWeek).Contains(localTime.DayOfWeek) &&
+ IsWithinTime(schedule, localTime);
+ }
+
+ private bool IsWithinTime(AccessSchedule schedule, DateTime localTime)
+ {
+ var hour = localTime.TimeOfDay.TotalHours;
+
+ return hour >= schedule.StartHour && hour <= schedule.EndHour;
+ }
}
}
-