aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs
blob: 21f153623e634d4d630977219cd1be0e47d40a29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.IO;
using Emby.Server.Implementations.Data;
using Jellyfin.Data.Entities.Security;
using Jellyfin.Server.Implementations;
using MediaBrowser.Controller;
using Microsoft.Extensions.Logging;
using SQLitePCL.pretty;

namespace Jellyfin.Server.Migrations.Routines
{
    /// <summary>
    /// A migration that moves data from the authentication database into the new schema.
    /// </summary>
    public class MigrateAuthenticationDb : IMigrationRoutine
    {
        private const string DbFilename = "authentication.db";

        private readonly ILogger<MigrateAuthenticationDb> _logger;
        private readonly JellyfinDbProvider _dbProvider;
        private readonly IServerApplicationPaths _appPaths;

        /// <summary>
        /// Initializes a new instance of the <see cref="MigrateAuthenticationDb"/> class.
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="dbProvider">The database provider.</param>
        /// <param name="appPaths">The server application paths.</param>
        public MigrateAuthenticationDb(ILogger<MigrateAuthenticationDb> logger, JellyfinDbProvider dbProvider, IServerApplicationPaths appPaths)
        {
            _logger = logger;
            _dbProvider = dbProvider;
            _appPaths = appPaths;
        }

        /// <inheritdoc />
        public Guid Id => Guid.Parse("5BD72F41-E6F3-4F60-90AA-09869ABE0E22");

        /// <inheritdoc />
        public string Name => "MigrateAuthenticationDatabase";

        /// <inheritdoc />
        public bool PerformOnNewInstall => false;

        /// <inheritdoc />
        public void Perform()
        {
            var dataPath = _appPaths.DataPath;
            using (var connection = SQLite3.Open(
                Path.Combine(dataPath, DbFilename),
                ConnectionFlags.ReadOnly,
                null))
            {
                using var dbContext = _dbProvider.CreateContext();

                var authenticatedDevices = connection.Query("SELECT * FROM Tokens");

                foreach (var row in authenticatedDevices)
                {
                    if (row[6].IsDbNull())
                    {
                        dbContext.ApiKeys.Add(new ApiKey(row[3].ToString())
                        {
                            AccessToken = row[1].ToString(),
                            DateCreated = row[9].ToDateTime(),
                            DateLastActivity = row[10].ToDateTime()
                        });
                    }
                    else
                    {
                        dbContext.Devices.Add(new Device(
                            new Guid(row[6].ToString()),
                            row[3].ToString(),
                            row[4].ToString(),
                            row[5].ToString(),
                            row[2].ToString())
                        {
                            AccessToken = row[1].ToString(),
                            IsActive = row[8].ToBool(),
                            DateCreated = row[9].ToDateTime(),
                            DateLastActivity = row[10].ToDateTime()
                        });
                    }
                }

                var deviceOptions = connection.Query("SELECT * FROM Devices");
                var deviceIds = new HashSet<string>();
                foreach (var row in deviceOptions)
                {
                    if (row[2].IsDbNull())
                    {
                        continue;
                    }

                    var deviceId = row[2].ToString();
                    if (deviceIds.Contains(deviceId))
                    {
                        continue;
                    }

                    deviceIds.Add(deviceId);

                    dbContext.DeviceOptions.Add(new DeviceOptions(deviceId)
                    {
                        CustomName = row[1].IsDbNull() ? null : row[1].ToString()
                    });
                }

                dbContext.SaveChanges();
            }

            try
            {
                File.Move(Path.Combine(dataPath, DbFilename), Path.Combine(dataPath, DbFilename + ".old"));

                var journalPath = Path.Combine(dataPath, DbFilename + "-journal");
                if (File.Exists(journalPath))
                {
                    File.Move(journalPath, Path.Combine(dataPath, DbFilename + ".old-journal"));
                }
            }
            catch (IOException e)
            {
                _logger.LogError(e, "Error renaming legacy activity log database to 'authentication.db.old'");
            }
        }
    }
}