|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using MediaBrowser.Controller;
|
|
|
|
|
using MediaBrowser.Controller.Entities;
|
|
|
|
|
using MediaBrowser.Controller.Persistence;
|
|
|
|
|
using MediaBrowser.Model.IO;
|
|
|
|
|
using MediaBrowser.Model.Logging;
|
|
|
|
|
using MediaBrowser.Model.Serialization;
|
|
|
|
|
using SQLitePCL.pretty;
|
|
|
|
|
|
|
|
|
|
namespace Emby.Server.Implementations.Data
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Class SQLiteUserRepository
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
|
|
|
|
|
{
|
|
|
|
|
private readonly IJsonSerializer _jsonSerializer;
|
|
|
|
|
private readonly IMemoryStreamFactory _memoryStreamProvider;
|
|
|
|
|
|
|
|
|
|
public SqliteUserRepository(ILogger logger, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IMemoryStreamFactory memoryStreamProvider)
|
|
|
|
|
: base(logger)
|
|
|
|
|
{
|
|
|
|
|
_jsonSerializer = jsonSerializer;
|
|
|
|
|
_memoryStreamProvider = memoryStreamProvider;
|
|
|
|
|
|
|
|
|
|
DbFilePath = Path.Combine(appPaths.DataPath, "users.db");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the name of the repository
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The name.</value>
|
|
|
|
|
public string Name
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return "SQLite";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Opens the connection to the database
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>Task.</returns>
|
|
|
|
|
public void Initialize()
|
|
|
|
|
{
|
|
|
|
|
using (var connection = CreateConnection())
|
|
|
|
|
{
|
|
|
|
|
RunDefaultInitialization(connection);
|
|
|
|
|
|
|
|
|
|
string[] queries = {
|
|
|
|
|
|
|
|
|
|
"create table if not exists users (guid GUID primary key NOT NULL, data BLOB NOT NULL)",
|
|
|
|
|
"create index if not exists idx_users on users(guid)",
|
|
|
|
|
|
|
|
|
|
"pragma shrink_memory"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
connection.RunQueries(queries);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Save a user in the repo
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="user">The user.</param>
|
|
|
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
|
|
|
/// <returns>Task.</returns>
|
|
|
|
|
/// <exception cref="System.ArgumentNullException">user</exception>
|
|
|
|
|
public void SaveUser(User user, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
if (user == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("user");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
|
|
|
|
var serialized = _jsonSerializer.SerializeToBytes(user, _memoryStreamProvider);
|
|
|
|
|
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
|
|
|
|
using (WriteLock.Write())
|
|
|
|
|
{
|
|
|
|
|
using (var connection = CreateConnection())
|
|
|
|
|
{
|
|
|
|
|
connection.RunInTransaction(db =>
|
|
|
|
|
{
|
|
|
|
|
using (var statement = db.PrepareStatement("replace into users (guid, data) values (@guid, @data)"))
|
|
|
|
|
{
|
|
|
|
|
statement.TryBind("@guid", user.Id.ToGuidBlob());
|
|
|
|
|
statement.TryBind("@data", serialized);
|
|
|
|
|
statement.MoveNext();
|
|
|
|
|
}
|
|
|
|
|
}, TransactionMode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Retrieve all users from the database
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>IEnumerable{User}.</returns>
|
|
|
|
|
public IEnumerable<User> RetrieveAllUsers()
|
|
|
|
|
{
|
|
|
|
|
var list = new List<User>();
|
|
|
|
|
|
|
|
|
|
using (WriteLock.Read())
|
|
|
|
|
{
|
|
|
|
|
using (var connection = CreateConnection(true))
|
|
|
|
|
{
|
|
|
|
|
foreach (var row in connection.Query("select guid,data from users"))
|
|
|
|
|
{
|
|
|
|
|
var id = row[0].ReadGuidFromBlob();
|
|
|
|
|
|
|
|
|
|
using (var stream = _memoryStreamProvider.CreateNew(row[1].ToBlob()))
|
|
|
|
|
{
|
|
|
|
|
stream.Position = 0;
|
|
|
|
|
var user = _jsonSerializer.DeserializeFromStream<User>(stream);
|
|
|
|
|
user.Id = id;
|
|
|
|
|
list.Add(user);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Deletes the user.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="user">The user.</param>
|
|
|
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
|
|
|
/// <returns>Task.</returns>
|
|
|
|
|
/// <exception cref="System.ArgumentNullException">user</exception>
|
|
|
|
|
public void DeleteUser(User user, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
if (user == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("user");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
|
|
|
|
using (WriteLock.Write())
|
|
|
|
|
{
|
|
|
|
|
using (var connection = CreateConnection())
|
|
|
|
|
{
|
|
|
|
|
connection.RunInTransaction(db =>
|
|
|
|
|
{
|
|
|
|
|
using (var statement = db.PrepareStatement("delete from users where guid=@id"))
|
|
|
|
|
{
|
|
|
|
|
statement.TryBind("@id", user.Id.ToGuidBlob());
|
|
|
|
|
statement.MoveNext();
|
|
|
|
|
}
|
|
|
|
|
}, TransactionMode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|