User.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.DataAnnotations;
  4. using System.ComponentModel.DataAnnotations.Schema;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Text.Json.Serialization;
  8. using Jellyfin.Data.Enums;
  9. namespace Jellyfin.Data.Entities
  10. {
  11. /// <summary>
  12. /// An entity representing a user.
  13. /// </summary>
  14. public partial class User : IHasPermissions, ISavingChanges
  15. {
  16. /// <summary>
  17. /// The values being delimited here are Guids, so commas work as they do not appear in Guids.
  18. /// </summary>
  19. private const char Delimiter = ',';
  20. /// <summary>
  21. /// Initializes a new instance of the <see cref="User"/> class.
  22. /// Public constructor with required data.
  23. /// </summary>
  24. /// <param name="username">The username for the new user.</param>
  25. /// <param name="authenticationProviderId">The authentication provider's Id</param>
  26. public User(string username, string authenticationProviderId, string passwordResetProviderId)
  27. {
  28. if (string.IsNullOrEmpty(username))
  29. {
  30. throw new ArgumentNullException(nameof(username));
  31. }
  32. if (string.IsNullOrEmpty(authenticationProviderId))
  33. {
  34. throw new ArgumentNullException(nameof(authenticationProviderId));
  35. }
  36. Username = username;
  37. AuthenticationProviderId = authenticationProviderId;
  38. PasswordResetProviderId = passwordResetProviderId;
  39. Groups = new HashSet<Group>();
  40. Permissions = new HashSet<Permission>();
  41. ProviderMappings = new HashSet<ProviderMapping>();
  42. Preferences = new HashSet<Preference>();
  43. AccessSchedules = new HashSet<AccessSchedule>();
  44. // Set default values
  45. Id = Guid.NewGuid();
  46. InvalidLoginAttemptCount = 0;
  47. MustUpdatePassword = false;
  48. DisplayMissingEpisodes = false;
  49. DisplayCollectionsView = false;
  50. HidePlayedInLatest = true;
  51. RememberAudioSelections = true;
  52. RememberSubtitleSelections = true;
  53. EnableNextEpisodeAutoPlay = true;
  54. EnableAutoLogin = false;
  55. PlayDefaultAudioTrack = true;
  56. SubtitleMode = SubtitlePlaybackMode.Default;
  57. AddDefaultPermissions();
  58. AddDefaultPreferences();
  59. Init();
  60. }
  61. /// <summary>
  62. /// Initializes a new instance of the <see cref="User"/> class.
  63. /// Default constructor. Protected due to required properties, but present because EF needs it.
  64. /// </summary>
  65. protected User()
  66. {
  67. Groups = new HashSet<Group>();
  68. Permissions = new HashSet<Permission>();
  69. ProviderMappings = new HashSet<ProviderMapping>();
  70. Preferences = new HashSet<Preference>();
  71. AccessSchedules = new HashSet<AccessSchedule>();
  72. Init();
  73. }
  74. /// <summary>
  75. /// Static create function (for use in LINQ queries, etc.)
  76. /// </summary>
  77. /// <param name="username">The username for the created user.</param>
  78. /// <param name="authenticationProviderId">The Id of the user's authentication provider.</param>
  79. /// <param name="passwordResetProviderId">The Id of the user's password reset provider.</param>
  80. /// <returns>The created instance.</returns>
  81. public static User Create(string username, string authenticationProviderId, string passwordResetProviderId)
  82. {
  83. return new User(username, authenticationProviderId, passwordResetProviderId);
  84. }
  85. /*************************************************************************
  86. * Properties
  87. *************************************************************************/
  88. /// <summary>
  89. /// Identity, Indexed, Required
  90. /// </summary>
  91. [Key]
  92. [Required]
  93. [JsonIgnore]
  94. public Guid Id { get; set; }
  95. /// <summary>
  96. /// Required, Max length = 255
  97. /// </summary>
  98. [Required]
  99. [MaxLength(255)]
  100. [StringLength(255)]
  101. public string Username { get; set; }
  102. /// <summary>
  103. /// Max length = 65535
  104. /// </summary>
  105. [MaxLength(65535)]
  106. [StringLength(65535)]
  107. public string Password { get; set; }
  108. /// <summary>
  109. /// Max length = 65535.
  110. /// </summary>
  111. [MaxLength(65535)]
  112. [StringLength(65535)]
  113. public string EasyPassword { get; set; }
  114. /// <summary>
  115. /// Required
  116. /// </summary>
  117. [Required]
  118. public bool MustUpdatePassword { get; set; }
  119. /// <summary>
  120. /// Max length = 255.
  121. /// </summary>
  122. [MaxLength(255)]
  123. [StringLength(255)]
  124. public string AudioLanguagePreference { get; set; }
  125. /// <summary>
  126. /// Required, Max length = 255
  127. /// </summary>
  128. [Required]
  129. [MaxLength(255)]
  130. [StringLength(255)]
  131. public string AuthenticationProviderId { get; set; }
  132. [Required]
  133. [MaxLength(255)]
  134. [StringLength(255)]
  135. public string PasswordResetProviderId { get; set; }
  136. /// <summary>
  137. /// Required
  138. /// </summary>
  139. [Required]
  140. public int InvalidLoginAttemptCount { get; set; }
  141. public DateTime LastActivityDate { get; set; }
  142. public DateTime LastLoginDate { get; set; }
  143. public int? LoginAttemptsBeforeLockout { get; set; }
  144. /// <summary>
  145. /// Required.
  146. /// </summary>
  147. [Required]
  148. public SubtitlePlaybackMode SubtitleMode { get; set; }
  149. /// <summary>
  150. /// Required
  151. /// </summary>
  152. [Required]
  153. public bool PlayDefaultAudioTrack { get; set; }
  154. /// <summary>
  155. /// Gets or sets the subtitle language preference.
  156. /// Max length = 255
  157. /// </summary>
  158. [MaxLength(255)]
  159. [StringLength(255)]
  160. public string SubtitleLanguagePreference { get; set; }
  161. [Required]
  162. public bool DisplayMissingEpisodes { get; set; }
  163. [Required]
  164. public bool DisplayCollectionsView { get; set; }
  165. [Required]
  166. public bool EnableLocalPassword { get; set; }
  167. [Required]
  168. public bool HidePlayedInLatest { get; set; }
  169. [Required]
  170. public bool RememberAudioSelections { get; set; }
  171. [Required]
  172. public bool RememberSubtitleSelections { get; set; }
  173. [Required]
  174. public bool EnableNextEpisodeAutoPlay { get; set; }
  175. [Required]
  176. public bool EnableAutoLogin { get; set; }
  177. [Required]
  178. public bool EnableUserPreferenceAccess { get; set; }
  179. public int? MaxParentalAgeRating { get; set; }
  180. public int? RemoteClientBitrateLimit { get; set; }
  181. /// <summary>
  182. /// Gets or sets the internal id.
  183. /// This is a temporary stopgap for until the library db is migrated.
  184. /// This corresponds to the value of the index of this user in the library db.
  185. /// </summary>
  186. [Required]
  187. public long InternalId { get; set; }
  188. public virtual ImageInfo ProfileImage { get; set; }
  189. /// <summary>
  190. /// Gets or sets the row version.
  191. /// Required, ConcurrenyToken.
  192. /// </summary>
  193. [ConcurrencyCheck]
  194. [Required]
  195. public uint RowVersion { get; set; }
  196. public void OnSavingChanges()
  197. {
  198. RowVersion++;
  199. }
  200. /*************************************************************************
  201. * Navigation properties
  202. *************************************************************************/
  203. [ForeignKey("Group_Groups_Guid")]
  204. public virtual ICollection<Group> Groups { get; protected set; }
  205. [ForeignKey("Permission_Permissions_Guid")]
  206. public virtual ICollection<Permission> Permissions { get; protected set; }
  207. [ForeignKey("ProviderMapping_ProviderMappings_Id")]
  208. public virtual ICollection<ProviderMapping> ProviderMappings { get; protected set; }
  209. [ForeignKey("Preference_Preferences_Guid")]
  210. public virtual ICollection<Preference> Preferences { get; protected set; }
  211. public virtual ICollection<AccessSchedule> AccessSchedules { get; protected set; }
  212. partial void Init();
  213. public bool HasPermission(PermissionKind permission)
  214. {
  215. var list = Permissions.Where(p => p.Kind == permission);
  216. return list.First().Value;
  217. }
  218. public void SetPermission(PermissionKind kind, bool value)
  219. {
  220. var permissionObj = Permissions.First(p => p.Kind == kind);
  221. permissionObj.Value = value;
  222. }
  223. public string[] GetPreference(PreferenceKind preference)
  224. {
  225. var val = Preferences
  226. .Where(p => p.Kind == preference)
  227. .Select(p => p.Value)
  228. .First();
  229. return Equals(val, string.Empty) ? Array.Empty<string>() : val.Split(Delimiter);
  230. }
  231. public void SetPreference(PreferenceKind preference, string[] values)
  232. {
  233. var pref = Preferences.First(p => p.Kind == preference);
  234. pref.Value = string.Join(Delimiter.ToString(CultureInfo.InvariantCulture), values);
  235. }
  236. public bool IsParentalScheduleAllowed()
  237. {
  238. var schedules = this.AccessSchedules;
  239. return schedules.Count == 0 || schedules.Any(i => IsParentalScheduleAllowed(i, DateTime.Now));
  240. }
  241. public bool IsFolderGrouped(Guid id)
  242. {
  243. return GetPreference(PreferenceKind.GroupedFolders).Any(i => new Guid(i) == id);
  244. }
  245. private bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
  246. {
  247. if (date.Kind != DateTimeKind.Utc)
  248. {
  249. throw new ArgumentException("Utc date expected");
  250. }
  251. var localTime = date.ToLocalTime();
  252. return DayOfWeekHelper.GetDaysOfWeek(schedule.DayOfWeek).Contains(localTime.DayOfWeek) &&
  253. IsWithinTime(schedule, localTime);
  254. }
  255. private bool IsWithinTime(AccessSchedule schedule, DateTime localTime)
  256. {
  257. var hour = localTime.TimeOfDay.TotalHours;
  258. return hour >= schedule.StartHour && hour <= schedule.EndHour;
  259. }
  260. // TODO: make these user configurable?
  261. private void AddDefaultPermissions()
  262. {
  263. Permissions.Add(new Permission(PermissionKind.IsAdministrator, false));
  264. Permissions.Add(new Permission(PermissionKind.IsDisabled, false));
  265. Permissions.Add(new Permission(PermissionKind.IsHidden, false));
  266. Permissions.Add(new Permission(PermissionKind.EnableAllChannels, false));
  267. Permissions.Add(new Permission(PermissionKind.EnableAllDevices, true));
  268. Permissions.Add(new Permission(PermissionKind.EnableAllFolders, false));
  269. Permissions.Add(new Permission(PermissionKind.EnableContentDeletion, false));
  270. Permissions.Add(new Permission(PermissionKind.EnableContentDownloading, true));
  271. Permissions.Add(new Permission(PermissionKind.EnableMediaConversion, true));
  272. Permissions.Add(new Permission(PermissionKind.EnableMediaPlayback, true));
  273. Permissions.Add(new Permission(PermissionKind.EnablePlaybackRemuxing, true));
  274. Permissions.Add(new Permission(PermissionKind.EnablePublicSharing, true));
  275. Permissions.Add(new Permission(PermissionKind.EnableRemoteAccess, true));
  276. Permissions.Add(new Permission(PermissionKind.EnableSyncTranscoding, true));
  277. Permissions.Add(new Permission(PermissionKind.EnableAudioPlaybackTranscoding, true));
  278. Permissions.Add(new Permission(PermissionKind.EnableLiveTvAccess, true));
  279. Permissions.Add(new Permission(PermissionKind.EnableLiveTvManagement, true));
  280. Permissions.Add(new Permission(PermissionKind.EnableSharedDeviceControl, true));
  281. Permissions.Add(new Permission(PermissionKind.EnableVideoPlaybackTranscoding, true));
  282. Permissions.Add(new Permission(PermissionKind.ForceRemoteSourceTranscoding, false));
  283. Permissions.Add(new Permission(PermissionKind.EnableRemoteControlOfOtherUsers, false));
  284. }
  285. private void AddDefaultPreferences()
  286. {
  287. foreach (var val in Enum.GetValues(typeof(PreferenceKind)).Cast<PreferenceKind>())
  288. {
  289. Preferences.Add(new Preference(val, string.Empty));
  290. }
  291. }
  292. }
  293. }