2
0

MigrateAuthenticationDb.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using Emby.Server.Implementations.Data;
  5. using Jellyfin.Data.Entities.Security;
  6. using Jellyfin.Server.Implementations;
  7. using MediaBrowser.Controller;
  8. using MediaBrowser.Controller.Library;
  9. using Microsoft.Extensions.Logging;
  10. using SQLitePCL.pretty;
  11. namespace Jellyfin.Server.Migrations.Routines
  12. {
  13. /// <summary>
  14. /// A migration that moves data from the authentication database into the new schema.
  15. /// </summary>
  16. public class MigrateAuthenticationDb : IMigrationRoutine
  17. {
  18. private const string DbFilename = "authentication.db";
  19. private readonly ILogger<MigrateAuthenticationDb> _logger;
  20. private readonly JellyfinDbProvider _dbProvider;
  21. private readonly IServerApplicationPaths _appPaths;
  22. private readonly IUserManager _userManager;
  23. /// <summary>
  24. /// Initializes a new instance of the <see cref="MigrateAuthenticationDb"/> class.
  25. /// </summary>
  26. /// <param name="logger">The logger.</param>
  27. /// <param name="dbProvider">The database provider.</param>
  28. /// <param name="appPaths">The server application paths.</param>
  29. /// <param name="userManager">The user manager.</param>
  30. public MigrateAuthenticationDb(
  31. ILogger<MigrateAuthenticationDb> logger,
  32. JellyfinDbProvider dbProvider,
  33. IServerApplicationPaths appPaths,
  34. IUserManager userManager)
  35. {
  36. _logger = logger;
  37. _dbProvider = dbProvider;
  38. _appPaths = appPaths;
  39. _userManager = userManager;
  40. }
  41. /// <inheritdoc />
  42. public Guid Id => Guid.Parse("5BD72F41-E6F3-4F60-90AA-09869ABE0E22");
  43. /// <inheritdoc />
  44. public string Name => "MigrateAuthenticationDatabase";
  45. /// <inheritdoc />
  46. public bool PerformOnNewInstall => false;
  47. /// <inheritdoc />
  48. public void Perform()
  49. {
  50. var dataPath = _appPaths.DataPath;
  51. using (var connection = SQLite3.Open(
  52. Path.Combine(dataPath, DbFilename),
  53. ConnectionFlags.ReadOnly,
  54. null))
  55. {
  56. using var dbContext = _dbProvider.CreateContext();
  57. var authenticatedDevices = connection.Query("SELECT * FROM Tokens");
  58. foreach (var row in authenticatedDevices)
  59. {
  60. var dateCreatedStr = row[9].ToString();
  61. _ = DateTime.TryParse(dateCreatedStr, out var dateCreated);
  62. var dateLastActivityStr = row[10].ToString();
  63. _ = DateTime.TryParse(dateLastActivityStr, out var dateLastActivity);
  64. if (row[6].IsDbNull())
  65. {
  66. dbContext.ApiKeys.Add(new ApiKey(row[3].ToString())
  67. {
  68. AccessToken = row[1].ToString(),
  69. DateCreated = dateCreated,
  70. DateLastActivity = dateLastActivity
  71. });
  72. }
  73. else
  74. {
  75. var userId = new Guid(row[6].ToString());
  76. var user = _userManager.GetUserById(userId);
  77. if (user is null)
  78. {
  79. // User doesn't exist, don't bring over the device.
  80. continue;
  81. }
  82. dbContext.Devices.Add(new Device(
  83. new Guid(row[6].ToString()),
  84. row[3].ToString(),
  85. row[4].ToString(),
  86. row[5].ToString(),
  87. row[2].ToString())
  88. {
  89. AccessToken = row[1].ToString(),
  90. IsActive = row[8].ToBool(),
  91. DateCreated = dateCreated,
  92. DateLastActivity = dateLastActivity
  93. });
  94. }
  95. }
  96. var deviceOptions = connection.Query("SELECT * FROM Devices");
  97. var deviceIds = new HashSet<string>();
  98. foreach (var row in deviceOptions)
  99. {
  100. if (row[2].IsDbNull())
  101. {
  102. continue;
  103. }
  104. var deviceId = row[2].ToString();
  105. if (deviceIds.Contains(deviceId))
  106. {
  107. continue;
  108. }
  109. deviceIds.Add(deviceId);
  110. dbContext.DeviceOptions.Add(new DeviceOptions(deviceId)
  111. {
  112. CustomName = row[1].IsDbNull() ? null : row[1].ToString()
  113. });
  114. }
  115. dbContext.SaveChanges();
  116. }
  117. try
  118. {
  119. File.Move(Path.Combine(dataPath, DbFilename), Path.Combine(dataPath, DbFilename + ".old"));
  120. var journalPath = Path.Combine(dataPath, DbFilename + "-journal");
  121. if (File.Exists(journalPath))
  122. {
  123. File.Move(journalPath, Path.Combine(dataPath, DbFilename + ".old-journal"));
  124. }
  125. }
  126. catch (IOException e)
  127. {
  128. _logger.LogError(e, "Error renaming legacy activity log database to 'authentication.db.old'");
  129. }
  130. }
  131. }
  132. }