< Summary - Jellyfin

Information
Class: Jellyfin.Server.Migrations.Routines.MigrateAuthenticationDb
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 61
Coverable lines: 61
Total lines: 149
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 16
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
get_Id()100%210%
get_Name()100%210%
get_PerformOnNewInstall()100%210%
Perform()0%272160%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using Emby.Server.Implementations.Data;
 5using Jellyfin.Data.Entities.Security;
 6using Jellyfin.Server.Implementations;
 7using MediaBrowser.Controller;
 8using MediaBrowser.Controller.Library;
 9using Microsoft.Data.Sqlite;
 10using Microsoft.EntityFrameworkCore;
 11using Microsoft.Extensions.Logging;
 12
 13namespace Jellyfin.Server.Migrations.Routines
 14{
 15    /// <summary>
 16    /// A migration that moves data from the authentication database into the new schema.
 17    /// </summary>
 18    public class MigrateAuthenticationDb : IMigrationRoutine
 19    {
 20        private const string DbFilename = "authentication.db";
 21
 22        private readonly ILogger<MigrateAuthenticationDb> _logger;
 23        private readonly IDbContextFactory<JellyfinDbContext> _dbProvider;
 24        private readonly IServerApplicationPaths _appPaths;
 25        private readonly IUserManager _userManager;
 26
 27        /// <summary>
 28        /// Initializes a new instance of the <see cref="MigrateAuthenticationDb"/> class.
 29        /// </summary>
 30        /// <param name="logger">The logger.</param>
 31        /// <param name="dbProvider">The database provider.</param>
 32        /// <param name="appPaths">The server application paths.</param>
 33        /// <param name="userManager">The user manager.</param>
 34        public MigrateAuthenticationDb(
 35            ILogger<MigrateAuthenticationDb> logger,
 36            IDbContextFactory<JellyfinDbContext> dbProvider,
 37            IServerApplicationPaths appPaths,
 38            IUserManager userManager)
 39        {
 040            _logger = logger;
 041            _dbProvider = dbProvider;
 042            _appPaths = appPaths;
 043            _userManager = userManager;
 044        }
 45
 46        /// <inheritdoc />
 047        public Guid Id => Guid.Parse("5BD72F41-E6F3-4F60-90AA-09869ABE0E22");
 48
 49        /// <inheritdoc />
 050        public string Name => "MigrateAuthenticationDatabase";
 51
 52        /// <inheritdoc />
 053        public bool PerformOnNewInstall => false;
 54
 55        /// <inheritdoc />
 56        public void Perform()
 57        {
 058            var dataPath = _appPaths.DataPath;
 059            using (var connection = new SqliteConnection($"Filename={Path.Combine(dataPath, DbFilename)}"))
 60            {
 061                connection.Open();
 062                using var dbContext = _dbProvider.CreateDbContext();
 63
 064                var authenticatedDevices = connection.Query("SELECT * FROM Tokens");
 65
 066                foreach (var row in authenticatedDevices)
 67                {
 068                    var dateCreatedStr = row.GetString(9);
 069                    _ = DateTime.TryParse(dateCreatedStr, out var dateCreated);
 070                    var dateLastActivityStr = row.GetString(10);
 071                    _ = DateTime.TryParse(dateLastActivityStr, out var dateLastActivity);
 72
 073                    if (row.IsDBNull(6))
 74                    {
 075                        dbContext.ApiKeys.Add(new ApiKey(row.GetString(3))
 076                        {
 077                            AccessToken = row.GetString(1),
 078                            DateCreated = dateCreated,
 079                            DateLastActivity = dateLastActivity
 080                        });
 81                    }
 82                    else
 83                    {
 084                        var userId = row.GetGuid(6);
 085                        var user = _userManager.GetUserById(userId);
 086                        if (user is null)
 87                        {
 88                            // User doesn't exist, don't bring over the device.
 89                            continue;
 90                        }
 91
 092                        dbContext.Devices.Add(new Device(
 093                            userId,
 094                            row.GetString(3),
 095                            row.GetString(4),
 096                            row.GetString(5),
 097                            row.GetString(2))
 098                        {
 099                            AccessToken = row.GetString(1),
 0100                            IsActive = row.GetBoolean(8),
 0101                            DateCreated = dateCreated,
 0102                            DateLastActivity = dateLastActivity
 0103                        });
 104                    }
 105                }
 106
 0107                var deviceOptions = connection.Query("SELECT * FROM Devices");
 0108                var deviceIds = new HashSet<string>();
 0109                foreach (var row in deviceOptions)
 110                {
 0111                    if (row.IsDBNull(2))
 112                    {
 113                        continue;
 114                    }
 115
 0116                    var deviceId = row.GetString(2);
 0117                    if (deviceIds.Contains(deviceId))
 118                    {
 119                        continue;
 120                    }
 121
 0122                    deviceIds.Add(deviceId);
 123
 0124                    dbContext.DeviceOptions.Add(new DeviceOptions(deviceId)
 0125                    {
 0126                        CustomName = row.IsDBNull(1) ? null : row.GetString(1)
 0127                    });
 128                }
 129
 0130                dbContext.SaveChanges();
 131            }
 132
 133            try
 134            {
 0135                File.Move(Path.Combine(dataPath, DbFilename), Path.Combine(dataPath, DbFilename + ".old"));
 136
 0137                var journalPath = Path.Combine(dataPath, DbFilename + "-journal");
 0138                if (File.Exists(journalPath))
 139                {
 0140                    File.Move(journalPath, Path.Combine(dataPath, DbFilename + ".old-journal"));
 141                }
 0142            }
 0143            catch (IOException e)
 144            {
 0145                _logger.LogError(e, "Error renaming legacy activity log database to 'authentication.db.old'");
 0146            }
 0147        }
 148    }
 149}