aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs10
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthService.cs5
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs291
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/SessionContext.cs12
-rw-r--r--Emby.Server.Implementations/HttpServer/WebSocketManager.cs2
-rw-r--r--Emby.Server.Implementations/Security/AuthenticationRepository.cs407
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs80
7 files changed, 42 insertions, 765 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 213890c67..a69c4d035 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -36,7 +36,6 @@ using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.Plugins;
using Emby.Server.Implementations.QuickConnect;
using Emby.Server.Implementations.ScheduledTasks;
-using Emby.Server.Implementations.Security;
using Emby.Server.Implementations.Serialization;
using Emby.Server.Implementations.Session;
using Emby.Server.Implementations.SyncPlay;
@@ -57,7 +56,6 @@ using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -73,7 +71,6 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.QuickConnect;
using MediaBrowser.Controller.Resolvers;
-using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
@@ -599,8 +596,6 @@ namespace Emby.Server.Implementations
ServiceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
- ServiceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
-
ServiceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
ServiceCollection.AddSingleton<EncodingHelper>();
@@ -657,8 +652,7 @@ namespace Emby.Server.Implementations
ServiceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
- ServiceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
- ServiceCollection.AddSingleton<ISessionContext, SessionContext>();
+ ServiceCollection.AddScoped<ISessionContext, SessionContext>();
ServiceCollection.AddSingleton<IAuthService, AuthService>();
ServiceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
@@ -687,8 +681,6 @@ namespace Emby.Server.Implementations
_mediaEncoder = Resolve<IMediaEncoder>();
_sessionManager = Resolve<ISessionManager>();
- ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
-
SetStaticProperties();
var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>();
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
index 9afabf527..e2ad07177 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -1,5 +1,6 @@
#pragma warning disable CS1591
+using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
@@ -17,9 +18,9 @@ namespace Emby.Server.Implementations.HttpServer.Security
_authorizationContext = authorizationContext;
}
- public AuthorizationInfo Authenticate(HttpRequest request)
+ public async Task<AuthorizationInfo> Authenticate(HttpRequest request)
{
- var auth = _authorizationContext.GetAuthorizationInfo(request);
+ var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false);
if (!auth.HasToken)
{
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
deleted file mode 100644
index 024404ceb..000000000
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ /dev/null
@@ -1,291 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Security;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Net.Http.Headers;
-
-namespace Emby.Server.Implementations.HttpServer.Security
-{
- public class AuthorizationContext : IAuthorizationContext
- {
- private readonly IAuthenticationRepository _authRepo;
- private readonly IUserManager _userManager;
-
- public AuthorizationContext(IAuthenticationRepository authRepo, IUserManager userManager)
- {
- _authRepo = authRepo;
- _userManager = userManager;
- }
-
- public AuthorizationInfo GetAuthorizationInfo(HttpContext requestContext)
- {
- if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached))
- {
- return (AuthorizationInfo)cached;
- }
-
- return GetAuthorization(requestContext);
- }
-
- public AuthorizationInfo GetAuthorizationInfo(HttpRequest requestContext)
- {
- var auth = GetAuthorizationDictionary(requestContext);
- var authInfo = GetAuthorizationInfoFromDictionary(auth, requestContext.Headers, requestContext.Query);
- return authInfo;
- }
-
- /// <summary>
- /// Gets the authorization.
- /// </summary>
- /// <param name="httpReq">The HTTP req.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private AuthorizationInfo GetAuthorization(HttpContext httpReq)
- {
- var auth = GetAuthorizationDictionary(httpReq);
- var authInfo = GetAuthorizationInfoFromDictionary(auth, httpReq.Request.Headers, httpReq.Request.Query);
-
- httpReq.Request.HttpContext.Items["AuthorizationInfo"] = authInfo;
- return authInfo;
- }
-
- private AuthorizationInfo GetAuthorizationInfoFromDictionary(
- in Dictionary<string, string> auth,
- in IHeaderDictionary headers,
- in IQueryCollection queryString)
- {
- string deviceId = null;
- string device = null;
- string client = null;
- string version = null;
- string token = null;
-
- if (auth != null)
- {
- auth.TryGetValue("DeviceId", out deviceId);
- auth.TryGetValue("Device", out device);
- auth.TryGetValue("Client", out client);
- auth.TryGetValue("Version", out version);
- auth.TryGetValue("Token", out token);
- }
-
- if (string.IsNullOrEmpty(token))
- {
- token = headers["X-Emby-Token"];
- }
-
- if (string.IsNullOrEmpty(token))
- {
- token = headers["X-MediaBrowser-Token"];
- }
-
- if (string.IsNullOrEmpty(token))
- {
- token = queryString["ApiKey"];
- }
-
- // TODO deprecate this query parameter.
- if (string.IsNullOrEmpty(token))
- {
- token = queryString["api_key"];
- }
-
- var authInfo = new AuthorizationInfo
- {
- Client = client,
- Device = device,
- DeviceId = deviceId,
- Version = version,
- Token = token,
- IsAuthenticated = false,
- HasToken = false
- };
-
- if (string.IsNullOrWhiteSpace(token))
- {
- // Request doesn't contain a token.
- return authInfo;
- }
-
- authInfo.HasToken = true;
- var result = _authRepo.Get(new AuthenticationInfoQuery
- {
- AccessToken = token
- });
-
- if (result.Items.Count > 0)
- {
- authInfo.IsAuthenticated = true;
- }
-
- var originalAuthenticationInfo = result.Items.Count > 0 ? result.Items[0] : null;
-
- if (originalAuthenticationInfo != null)
- {
- var updateToken = false;
-
- // TODO: Remove these checks for IsNullOrWhiteSpace
- if (string.IsNullOrWhiteSpace(authInfo.Client))
- {
- authInfo.Client = originalAuthenticationInfo.AppName;
- }
-
- if (string.IsNullOrWhiteSpace(authInfo.DeviceId))
- {
- authInfo.DeviceId = originalAuthenticationInfo.DeviceId;
- }
-
- // Temporary. TODO - allow clients to specify that the token has been shared with a casting device
- var allowTokenInfoUpdate = authInfo.Client == null || authInfo.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
-
- if (string.IsNullOrWhiteSpace(authInfo.Device))
- {
- authInfo.Device = originalAuthenticationInfo.DeviceName;
- }
- else if (!string.Equals(authInfo.Device, originalAuthenticationInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
- {
- if (allowTokenInfoUpdate)
- {
- updateToken = true;
- originalAuthenticationInfo.DeviceName = authInfo.Device;
- }
- }
-
- if (string.IsNullOrWhiteSpace(authInfo.Version))
- {
- authInfo.Version = originalAuthenticationInfo.AppVersion;
- }
- else if (!string.Equals(authInfo.Version, originalAuthenticationInfo.AppVersion, StringComparison.OrdinalIgnoreCase))
- {
- if (allowTokenInfoUpdate)
- {
- updateToken = true;
- originalAuthenticationInfo.AppVersion = authInfo.Version;
- }
- }
-
- if ((DateTime.UtcNow - originalAuthenticationInfo.DateLastActivity).TotalMinutes > 3)
- {
- originalAuthenticationInfo.DateLastActivity = DateTime.UtcNow;
- updateToken = true;
- }
-
- if (!originalAuthenticationInfo.UserId.Equals(Guid.Empty))
- {
- authInfo.User = _userManager.GetUserById(originalAuthenticationInfo.UserId);
-
- if (authInfo.User != null && !string.Equals(authInfo.User.Username, originalAuthenticationInfo.UserName, StringComparison.OrdinalIgnoreCase))
- {
- originalAuthenticationInfo.UserName = authInfo.User.Username;
- updateToken = true;
- }
-
- authInfo.IsApiKey = false;
- }
- else
- {
- authInfo.IsApiKey = true;
- }
-
- if (updateToken)
- {
- _authRepo.Update(originalAuthenticationInfo);
- }
- }
-
- return authInfo;
- }
-
- /// <summary>
- /// Gets the auth.
- /// </summary>
- /// <param name="httpReq">The HTTP req.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private Dictionary<string, string> GetAuthorizationDictionary(HttpContext httpReq)
- {
- var auth = httpReq.Request.Headers["X-Emby-Authorization"];
-
- if (string.IsNullOrEmpty(auth))
- {
- auth = httpReq.Request.Headers[HeaderNames.Authorization];
- }
-
- return GetAuthorization(auth);
- }
-
- /// <summary>
- /// Gets the auth.
- /// </summary>
- /// <param name="httpReq">The HTTP req.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private Dictionary<string, string> GetAuthorizationDictionary(HttpRequest httpReq)
- {
- var auth = httpReq.Headers["X-Emby-Authorization"];
-
- if (string.IsNullOrEmpty(auth))
- {
- auth = httpReq.Headers[HeaderNames.Authorization];
- }
-
- return GetAuthorization(auth);
- }
-
- /// <summary>
- /// Gets the authorization.
- /// </summary>
- /// <param name="authorizationHeader">The authorization header.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private Dictionary<string, string> GetAuthorization(string authorizationHeader)
- {
- if (authorizationHeader == null)
- {
- return null;
- }
-
- var parts = authorizationHeader.Split(' ', 2);
-
- // There should be at least to parts
- if (parts.Length != 2)
- {
- return null;
- }
-
- var acceptedNames = new[] { "MediaBrowser", "Emby" };
-
- // It has to be a digest request
- if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase))
- {
- return null;
- }
-
- // Remove uptil the first space
- authorizationHeader = parts[1];
- parts = authorizationHeader.Split(',');
-
- var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
- foreach (var item in parts)
- {
- var param = item.Trim().Split('=', 2);
-
- if (param.Length == 2)
- {
- var value = NormalizeValue(param[1].Trim('"'));
- result[param[0]] = value;
- }
- }
-
- return result;
- }
-
- private static string NormalizeValue(string value)
- {
- return string.IsNullOrEmpty(value) ? value : WebUtility.HtmlEncode(value);
- }
- }
-}
diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
index 414ba7ca0..cd1b9cba0 100644
--- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -24,12 +24,18 @@ namespace Emby.Server.Implementations.HttpServer.Security
_sessionManager = sessionManager;
}
- public Task<SessionInfo> GetSession(HttpContext requestContext)
+ public async Task<SessionInfo> GetSession(HttpContext requestContext)
{
- var authorization = _authContext.GetAuthorizationInfo(requestContext);
+ var authorization = await _authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false);
var user = authorization.User;
- return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp().ToString(), user);
+ return await _sessionManager.LogSessionActivity(
+ authorization.Client,
+ authorization.Version,
+ authorization.DeviceId,
+ authorization.Device,
+ requestContext.GetNormalizedRemoteIp().ToString(),
+ user).ConfigureAwait(false);
}
public Task<SessionInfo> GetSession(object requestContext)
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
index 1bee1ac31..b71ffdaee 100644
--- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
+++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
@@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.HttpServer
/// <inheritdoc />
public async Task WebSocketRequestHandler(HttpContext context)
{
- _ = _authService.Authenticate(context.Request);
+ _ = await _authService.Authenticate(context.Request).ConfigureAwait(false);
try
{
_logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress);
diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
deleted file mode 100644
index 0d0a2b1df..000000000
--- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs
+++ /dev/null
@@ -1,407 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using Emby.Server.Implementations.Data;
-using Jellyfin.Data.Entities.Security;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Security;
-using MediaBrowser.Model.Querying;
-using Microsoft.Extensions.Logging;
-using SQLitePCL.pretty;
-
-namespace Emby.Server.Implementations.Security
-{
- public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository
- {
- public AuthenticationRepository(ILogger<AuthenticationRepository> logger, IServerConfigurationManager config)
- : base(logger)
- {
- DbFilePath = Path.Combine(config.ApplicationPaths.DataPath, "authentication.db");
- }
-
- public void Initialize()
- {
- string[] queries =
- {
- "create table if not exists Tokens (Id INTEGER PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT NOT NULL, AppName TEXT NOT NULL, AppVersion TEXT NOT NULL, DeviceName TEXT NOT NULL, UserId TEXT, UserName TEXT, IsActive BIT NOT NULL, DateCreated DATETIME NOT NULL, DateLastActivity DATETIME NOT NULL)",
- "create table if not exists Devices (Id TEXT NOT NULL PRIMARY KEY, CustomName TEXT, Capabilities TEXT)",
- "drop index if exists idx_AccessTokens",
- "drop index if exists Tokens1",
- "drop index if exists Tokens2",
-
- "create index if not exists Tokens3 on Tokens (AccessToken, DateLastActivity)",
- "create index if not exists Tokens4 on Tokens (Id, DateLastActivity)",
- "create index if not exists Devices1 on Devices (Id)"
- };
-
- using (var connection = GetConnection())
- {
- var tableNewlyCreated = !TableExists(connection, "Tokens");
-
- connection.RunQueries(queries);
-
- TryMigrate(connection, tableNewlyCreated);
- }
- }
-
- private void TryMigrate(ManagedConnection connection, bool tableNewlyCreated)
- {
- try
- {
- if (tableNewlyCreated && TableExists(connection, "AccessTokens"))
- {
- connection.RunInTransaction(
- db =>
- {
- var existingColumnNames = GetColumnNames(db, "AccessTokens");
-
- AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames);
- AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames);
- AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames);
- }, TransactionMode);
-
- connection.RunQueries(new[]
- {
- "update accesstokens set DateLastActivity=DateCreated where DateLastActivity is null",
- "update accesstokens set DeviceName='Unknown' where DeviceName is null",
- "update accesstokens set AppName='Unknown' where AppName is null",
- "update accesstokens set AppVersion='1' where AppVersion is null",
- "INSERT INTO Tokens (AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity) SELECT AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity FROM AccessTokens where deviceid not null and devicename not null and appname not null and isactive=1"
- });
- }
- }
- catch (Exception ex)
- {
- Logger.LogError(ex, "Error migrating authentication database");
- }
- }
-
- public void Create(AuthenticationInfo info)
- {
- if (info == null)
- {
- throw new ArgumentNullException(nameof(info));
- }
-
- using (var connection = GetConnection())
- {
- connection.RunInTransaction(
- db =>
- {
- using (var statement = db.PrepareStatement("insert into Tokens (AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity) values (@AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @UserName, @IsActive, @DateCreated, @DateLastActivity)"))
- {
- statement.TryBind("@AccessToken", info.AccessToken);
-
- statement.TryBind("@DeviceId", info.DeviceId);
- statement.TryBind("@AppName", info.AppName);
- statement.TryBind("@AppVersion", info.AppVersion);
- statement.TryBind("@DeviceName", info.DeviceName);
- statement.TryBind("@UserId", info.UserId.Equals(Guid.Empty) ? null : info.UserId.ToString("N", CultureInfo.InvariantCulture));
- statement.TryBind("@UserName", info.UserName);
- statement.TryBind("@IsActive", true);
- statement.TryBind("@DateCreated", info.DateCreated.ToDateTimeParamValue());
- statement.TryBind("@DateLastActivity", info.DateLastActivity.ToDateTimeParamValue());
-
- statement.MoveNext();
- }
- }, TransactionMode);
- }
- }
-
- public void Update(AuthenticationInfo info)
- {
- if (info == null)
- {
- throw new ArgumentNullException(nameof(info));
- }
-
- using (var connection = GetConnection())
- {
- connection.RunInTransaction(
- db =>
- {
- using (var statement = db.PrepareStatement("Update Tokens set AccessToken=@AccessToken, DeviceId=@DeviceId, AppName=@AppName, AppVersion=@AppVersion, DeviceName=@DeviceName, UserId=@UserId, UserName=@UserName, DateCreated=@DateCreated, DateLastActivity=@DateLastActivity where Id=@Id"))
- {
- statement.TryBind("@Id", info.Id);
-
- statement.TryBind("@AccessToken", info.AccessToken);
-
- statement.TryBind("@DeviceId", info.DeviceId);
- statement.TryBind("@AppName", info.AppName);
- statement.TryBind("@AppVersion", info.AppVersion);
- statement.TryBind("@DeviceName", info.DeviceName);
- statement.TryBind("@UserId", info.UserId.Equals(Guid.Empty) ? null : info.UserId.ToString("N", CultureInfo.InvariantCulture));
- statement.TryBind("@UserName", info.UserName);
- statement.TryBind("@DateCreated", info.DateCreated.ToDateTimeParamValue());
- statement.TryBind("@DateLastActivity", info.DateLastActivity.ToDateTimeParamValue());
-
- statement.MoveNext();
- }
- }, TransactionMode);
- }
- }
-
- public void Delete(AuthenticationInfo info)
- {
- if (info == null)
- {
- throw new ArgumentNullException(nameof(info));
- }
-
- using (var connection = GetConnection())
- {
- connection.RunInTransaction(
- db =>
- {
- using (var statement = db.PrepareStatement("Delete from Tokens where Id=@Id"))
- {
- statement.TryBind("@Id", info.Id);
-
- statement.MoveNext();
- }
- }, TransactionMode);
- }
- }
-
- private const string BaseSelectText = "select Tokens.Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, DateCreated, DateLastActivity, Devices.CustomName from Tokens left join Devices on Tokens.DeviceId=Devices.Id";
-
- private static void BindAuthenticationQueryParams(AuthenticationInfoQuery query, IStatement statement)
- {
- if (!string.IsNullOrEmpty(query.AccessToken))
- {
- statement.TryBind("@AccessToken", query.AccessToken);
- }
-
- if (!query.UserId.Equals(Guid.Empty))
- {
- statement.TryBind("@UserId", query.UserId.ToString("N", CultureInfo.InvariantCulture));
- }
-
- if (!string.IsNullOrEmpty(query.DeviceId))
- {
- statement.TryBind("@DeviceId", query.DeviceId);
- }
- }
-
- public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
- {
- if (query == null)
- {
- throw new ArgumentNullException(nameof(query));
- }
-
- var commandText = BaseSelectText;
-
- var whereClauses = new List<string>();
-
- if (!string.IsNullOrEmpty(query.AccessToken))
- {
- whereClauses.Add("AccessToken=@AccessToken");
- }
-
- if (!string.IsNullOrEmpty(query.DeviceId))
- {
- whereClauses.Add("DeviceId=@DeviceId");
- }
-
- if (!query.UserId.Equals(Guid.Empty))
- {
- whereClauses.Add("UserId=@UserId");
- }
-
- if (query.HasUser.HasValue)
- {
- if (query.HasUser.Value)
- {
- whereClauses.Add("UserId not null");
- }
- else
- {
- whereClauses.Add("UserId is null");
- }
- }
-
- var whereTextWithoutPaging = whereClauses.Count == 0 ?
- string.Empty :
- " where " + string.Join(" AND ", whereClauses.ToArray());
-
- commandText += whereTextWithoutPaging;
-
- commandText += " ORDER BY DateLastActivity desc";
-
- if (query.Limit.HasValue || query.StartIndex.HasValue)
- {
- var offset = query.StartIndex ?? 0;
-
- if (query.Limit.HasValue || offset > 0)
- {
- commandText += " LIMIT " + (query.Limit ?? int.MaxValue).ToString(CultureInfo.InvariantCulture);
- }
-
- if (offset > 0)
- {
- commandText += " OFFSET " + offset.ToString(CultureInfo.InvariantCulture);
- }
- }
-
- var statementTexts = new[]
- {
- commandText,
- "select count (Id) from Tokens" + whereTextWithoutPaging
- };
-
- var list = new List<AuthenticationInfo>();
- var result = new QueryResult<AuthenticationInfo>();
- using (var connection = GetConnection(true))
- {
- connection.RunInTransaction(
- db =>
- {
- var statements = PrepareAll(db, statementTexts);
-
- using (var statement = statements[0])
- {
- BindAuthenticationQueryParams(query, statement);
-
- foreach (var row in statement.ExecuteQuery())
- {
- list.Add(Get(row));
- }
-
- using (var totalCountStatement = statements[1])
- {
- BindAuthenticationQueryParams(query, totalCountStatement);
-
- result.TotalRecordCount = totalCountStatement.ExecuteQuery()
- .SelectScalarInt()
- .First();
- }
- }
- },
- ReadTransactionMode);
- }
-
- result.Items = list;
- return result;
- }
-
- private static AuthenticationInfo Get(IReadOnlyList<IResultSetValue> reader)
- {
- var info = new AuthenticationInfo
- {
- Id = reader[0].ToInt64(),
- AccessToken = reader[1].ToString()
- };
-
- if (reader[2].SQLiteType != SQLiteType.Null)
- {
- info.DeviceId = reader[2].ToString();
- }
-
- if (reader[3].SQLiteType != SQLiteType.Null)
- {
- info.AppName = reader[3].ToString();
- }
-
- if (reader[4].SQLiteType != SQLiteType.Null)
- {
- info.AppVersion = reader[4].ToString();
- }
-
- if (reader[5].SQLiteType != SQLiteType.Null)
- {
- info.DeviceName = reader[5].ToString();
- }
-
- if (reader[6].SQLiteType != SQLiteType.Null)
- {
- info.UserId = new Guid(reader[6].ToString());
- }
-
- if (reader[7].SQLiteType != SQLiteType.Null)
- {
- info.UserName = reader[7].ToString();
- }
-
- info.DateCreated = reader[8].ReadDateTime();
-
- if (reader[9].SQLiteType != SQLiteType.Null)
- {
- info.DateLastActivity = reader[9].ReadDateTime();
- }
- else
- {
- info.DateLastActivity = info.DateCreated;
- }
-
- if (reader[10].SQLiteType != SQLiteType.Null)
- {
- info.DeviceName = reader[10].ToString();
- }
-
- return info;
- }
-
- public DeviceOptions GetDeviceOptions(string deviceId)
- {
- using (var connection = GetConnection(true))
- {
- return connection.RunInTransaction(
- db =>
- {
- using (var statement = base.PrepareStatement(db, "select CustomName from Devices where Id=@DeviceId"))
- {
- statement.TryBind("@DeviceId", deviceId);
-
- var result = new DeviceOptions(deviceId);
-
- foreach (var row in statement.ExecuteQuery())
- {
- if (row[0].SQLiteType != SQLiteType.Null)
- {
- result.CustomName = row[0].ToString();
- }
- }
-
- return result;
- }
- }, ReadTransactionMode);
- }
- }
-
- public void UpdateDeviceOptions(string deviceId, DeviceOptions options)
- {
- if (options == null)
- {
- throw new ArgumentNullException(nameof(options));
- }
-
- using (var connection = GetConnection())
- {
- connection.RunInTransaction(
- db =>
- {
- using (var statement = db.PrepareStatement("replace into devices (Id, CustomName, Capabilities) VALUES (@Id, @CustomName, (Select Capabilities from Devices where Id=@Id))"))
- {
- statement.TryBind("@Id", deviceId);
-
- if (string.IsNullOrWhiteSpace(options.CustomName))
- {
- statement.TryBindNull("@CustomName");
- }
- else
- {
- statement.TryBind("@CustomName", options.CustomName);
- }
-
- statement.MoveNext();
- }
- }, TransactionMode);
- }
- }
- }
-}
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 2fb5040f9..92ef65bf1 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -11,6 +11,7 @@ using Jellyfin.Data.Entities;
using Jellyfin.Data.Entities.Security;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
+using Jellyfin.Data.Queries;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
@@ -23,7 +24,6 @@ using MediaBrowser.Controller.Events;
using MediaBrowser.Controller.Events.Session;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -52,7 +52,6 @@ namespace Emby.Server.Implementations.Session
private readonly IImageProcessor _imageProcessor;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerApplicationHost _appHost;
- private readonly IAuthenticationRepository _authRepo;
private readonly IDeviceManager _deviceManager;
/// <summary>
@@ -75,7 +74,6 @@ namespace Emby.Server.Implementations.Session
IDtoService dtoService,
IImageProcessor imageProcessor,
IServerApplicationHost appHost,
- IAuthenticationRepository authRepo,
IDeviceManager deviceManager,
IMediaSourceManager mediaSourceManager)
{
@@ -88,7 +86,6 @@ namespace Emby.Server.Implementations.Session
_dtoService = dtoService;
_imageProcessor = imageProcessor;
_appHost = appHost;
- _authRepo = authRepo;
_deviceManager = deviceManager;
_mediaSourceManager = mediaSourceManager;
@@ -1486,7 +1483,7 @@ namespace Emby.Server.Implementations.Session
throw new SecurityException("User is at their maximum number of sessions.");
}
- var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
+ var token = await GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName).ConfigureAwait(false);
var session = await LogSessionActivity(
request.App,
@@ -1509,21 +1506,21 @@ namespace Emby.Server.Implementations.Session
return returnResult;
}
- private string GetAuthorizationToken(User user, string deviceId, string app, string appVersion, string deviceName)
+ private async Task<string> GetAuthorizationToken(User user, string deviceId, string app, string appVersion, string deviceName)
{
- var existing = _authRepo.Get(
- new AuthenticationInfoQuery
+ var existing = (await _deviceManager.GetDevices(
+ new DeviceQuery
{
DeviceId = deviceId,
UserId = user.Id,
Limit = 1
- }).Items.FirstOrDefault();
+ }).ConfigureAwait(false)).Items.FirstOrDefault();
- var allExistingForDevice = _authRepo.Get(
- new AuthenticationInfoQuery
+ var allExistingForDevice = (await _deviceManager.GetDevices(
+ new DeviceQuery
{
DeviceId = deviceId
- }).Items;
+ }).ConfigureAwait(false)).Items;
foreach (var auth in allExistingForDevice)
{
@@ -1531,7 +1528,7 @@ namespace Emby.Server.Implementations.Session
{
try
{
- Logout(auth);
+ await Logout(auth).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -1546,29 +1543,14 @@ namespace Emby.Server.Implementations.Session
return existing.AccessToken;
}
- var now = DateTime.UtcNow;
-
- var newToken = new AuthenticationInfo
- {
- AppName = app,
- AppVersion = appVersion,
- DateCreated = now,
- DateLastActivity = now,
- DeviceId = deviceId,
- DeviceName = deviceName,
- UserId = user.Id,
- AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
- UserName = user.Username
- };
-
_logger.LogInformation("Creating new access token for user {0}", user.Id);
- _authRepo.Create(newToken);
+ var device = await _deviceManager.CreateDevice(new Device(user.Id, app, appVersion, deviceName, deviceId)).ConfigureAwait(false);
- return newToken.AccessToken;
+ return device.AccessToken;
}
/// <inheritdoc />
- public void Logout(string accessToken)
+ public async Task Logout(string accessToken)
{
CheckDisposed();
@@ -1577,27 +1559,27 @@ namespace Emby.Server.Implementations.Session
throw new ArgumentNullException(nameof(accessToken));
}
- var existing = _authRepo.Get(
- new AuthenticationInfoQuery
+ var existing = (await _deviceManager.GetDevices(
+ new DeviceQuery
{
Limit = 1,
AccessToken = accessToken
- }).Items;
+ }).ConfigureAwait(false)).Items;
if (existing.Count > 0)
{
- Logout(existing[0]);
+ await Logout(existing[0]).ConfigureAwait(false);
}
}
/// <inheritdoc />
- public void Logout(AuthenticationInfo existing)
+ public async Task Logout(Device existing)
{
CheckDisposed();
_logger.LogInformation("Logging out access token {0}", existing.AccessToken);
- _authRepo.Delete(existing);
+ await _deviceManager.DeleteDevice(existing).ConfigureAwait(false);
var sessions = Sessions
.Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
@@ -1617,30 +1599,24 @@ namespace Emby.Server.Implementations.Session
}
/// <inheritdoc />
- public void RevokeUserTokens(Guid userId, string currentAccessToken)
+ public async Task RevokeUserTokens(Guid userId, string currentAccessToken)
{
CheckDisposed();
- var existing = _authRepo.Get(new AuthenticationInfoQuery
+ var existing = await _deviceManager.GetDevices(new DeviceQuery
{
UserId = userId
- });
+ }).ConfigureAwait(false);
foreach (var info in existing.Items)
{
if (!string.Equals(currentAccessToken, info.AccessToken, StringComparison.OrdinalIgnoreCase))
{
- Logout(info);
+ await Logout(info).ConfigureAwait(false);
}
}
}
- /// <inheritdoc />
- public void RevokeToken(string token)
- {
- Logout(token);
- }
-
/// <summary>
/// Reports the capabilities.
/// </summary>
@@ -1792,7 +1768,7 @@ namespace Emby.Server.Implementations.Session
}
/// <inheritdoc />
- public Task<SessionInfo> GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion)
+ public Task<SessionInfo> GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion)
{
if (info == null)
{
@@ -1825,20 +1801,20 @@ namespace Emby.Server.Implementations.Session
}
/// <inheritdoc />
- public Task<SessionInfo> GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint)
+ public async Task<SessionInfo> GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint)
{
- var items = _authRepo.Get(new AuthenticationInfoQuery
+ var items = (await _deviceManager.GetDevices(new DeviceQuery
{
AccessToken = token,
Limit = 1
- }).Items;
+ }).ConfigureAwait(false)).Items;
if (items.Count == 0)
{
return null;
}
- return GetSessionByAuthenticationToken(items[0], deviceId, remoteEndpoint, null);
+ return await GetSessionByAuthenticationToken(items[0], deviceId, remoteEndpoint, null).ConfigureAwait(false);
}
/// <inheritdoc />