completed auth database

This commit is contained in:
Luke Pulverenti
2014-07-07 21:41:03 -04:00
parent 379fa00228
commit c02e917f56
41 changed files with 936 additions and 139 deletions

View File

@@ -1133,6 +1133,8 @@ namespace MediaBrowser.Server.Implementations.Channels
item.CommunityRating = info.CommunityRating;
item.OfficialRating = info.OfficialRating;
item.Overview = info.Overview;
item.IndexNumber = info.IndexNumber;
item.ParentIndexNumber = info.ParentIndexNumber;
item.People = info.People;
item.PremiereDate = info.PremiereDate;
item.ProductionYear = info.ProductionYear;
@@ -1159,7 +1161,6 @@ namespace MediaBrowser.Server.Implementations.Channels
if (channelMediaItem != null)
{
channelMediaItem.IsInfiniteStream = info.IsInfiniteStream;
channelMediaItem.ContentType = info.ContentType;
channelMediaItem.ChannelMediaSources = info.MediaSources;

View File

@@ -1,9 +1,11 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using MoreLinq;
using System;
using System.Collections.Generic;
@@ -19,12 +21,18 @@ namespace MediaBrowser.Server.Implementations.Collections
private readonly ILibraryManager _libraryManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _iLibraryMonitor;
private readonly ILogger _logger;
public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor)
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger)
{
_libraryManager = libraryManager;
_fileSystem = fileSystem;
_iLibraryMonitor = iLibraryMonitor;
_logger = logger;
}
public Folder GetCollectionsFolder(string userId)
@@ -74,9 +82,16 @@ namespace MediaBrowser.Server.Implementations.Collections
if (options.ItemIdList.Count > 0)
{
await AddToCollection(collection.Id, options.ItemIdList);
await AddToCollection(collection.Id, options.ItemIdList, false);
}
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
{
Collection = collection,
Options = options
}, _logger);
return collection;
}
finally
@@ -113,7 +128,12 @@ namespace MediaBrowser.Server.Implementations.Collections
return GetCollectionsFolder(string.Empty);
}
public async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
{
return AddToCollection(collectionId, ids, true);
}
private async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent)
{
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
@@ -123,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
var list = new List<LinkedChild>();
var itemList = new List<BaseItem>();
var currentLinkedChildren = collection.GetLinkedChildren().ToList();
foreach (var itemId in ids)
@@ -134,6 +155,8 @@ namespace MediaBrowser.Server.Implementations.Collections
throw new ArgumentException("No item exists with the supplied Id");
}
itemList.Add(item);
if (currentLinkedChildren.Any(i => i.Id == itemId))
{
throw new ArgumentException("Item already exists in collection");
@@ -165,6 +188,16 @@ namespace MediaBrowser.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
if (fireEvent)
{
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
{
Collection = collection,
ItemsChanged = itemList
}, _logger);
}
}
public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
@@ -177,6 +210,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
var list = new List<LinkedChild>();
var itemList = new List<BaseItem>();
foreach (var itemId in itemIds)
{
@@ -190,6 +224,12 @@ namespace MediaBrowser.Server.Implementations.Collections
list.Add(child);
var childItem = _libraryManager.GetItemById(itemId);
if (childItem != null)
{
itemList.Add(childItem);
}
var supportsGrouping = childItem as ISupportsBoxSetGrouping;
if (supportsGrouping != null)
@@ -221,7 +261,7 @@ namespace MediaBrowser.Server.Implementations.Collections
{
File.Delete(file);
}
foreach (var child in list)
{
collection.LinkedChildren.Remove(child);
@@ -238,6 +278,13 @@ namespace MediaBrowser.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
{
Collection = collection,
ItemsChanged = itemList
}, _logger);
}
public IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user)

View File

@@ -1,4 +1,4 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
@@ -13,9 +13,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
{
public class AuthService : IAuthService
{
public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext)
private readonly IServerConfigurationManager _config;
public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config)
{
AuthorizationContext = authorizationContext;
_config = config;
SessionManager = sessionManager;
UserManager = userManager;
}
@@ -54,29 +57,31 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
//This code is executed before the service
var auth = AuthorizationContext.GetAuthorizationInfo(req);
if (string.IsNullOrWhiteSpace(auth.Token))
{
// Legacy
// TODO: Deprecate this in Oct 2014
User user = null;
if (!string.IsNullOrWhiteSpace(auth.UserId))
{
var userId = auth.UserId;
user = UserManager.GetUserById(new Guid(userId));
}
if (user == null || user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException("Unauthorized access.");
}
}
else
if (!string.IsNullOrWhiteSpace(auth.Token) || _config.Configuration.EnableTokenAuthentication)
{
SessionManager.ValidateSecurityToken(auth.Token);
}
var user = string.IsNullOrWhiteSpace(auth.UserId)
? null
: UserManager.GetUserById(new Guid(auth.UserId));
if (user != null && user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException("User account has been disabled.");
}
if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
!string.IsNullOrWhiteSpace(auth.Client) &&
!string.IsNullOrWhiteSpace(auth.Device))
{
SessionManager.LogSessionActivity(auth.Client,
auth.Version,
auth.DeviceId,
auth.Device,
req.RemoteIp,
user);
}
}
private void ExecuteBasic(IRequest req, IResponse res, object requestDto)
@@ -108,11 +113,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
}
}
private void LogRequest()
{
}
protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false)
{
var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect;

View File

@@ -216,6 +216,7 @@
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
<Compile Include="Security\AuthenticationRepository.cs" />
<Compile Include="Security\EncryptionManager.cs" />
<Compile Include="ServerApplicationPaths.cs" />
<Compile Include="ServerManager\ServerManager.cs" />

View File

@@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
public class SqliteFileOrganizationRepository : IFileOrganizationRepository
public class SqliteFileOrganizationRepository : IFileOrganizationRepository, IDisposable
{
private IDbConnection _connection;

View File

@@ -0,0 +1,338 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Server.Implementations.Persistence;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Security
{
public class AuthenticationRepository : IAuthenticationRepository
{
private IDbConnection _connection;
private readonly ILogger _logger;
private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
private readonly IServerApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private IDbCommand _saveInfoCommand;
public AuthenticationRepository(ILogger logger, IServerApplicationPaths appPaths)
{
_logger = logger;
_appPaths = appPaths;
}
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
string[] queries = {
"create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
"create index if not exists idx_AccessTokens on AccessTokens(Id)",
//pragmas
"pragma temp_store = memory",
"pragma shrink_memory"
};
_connection.RunQueries(queries, _logger);
PrepareStatements();
}
private void PrepareStatements()
{
_saveInfoCommand = _connection.CreateCommand();
_saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)";
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@Id");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AccessToken");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceId");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AppName");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceName");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@UserId");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@IsActive");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateCreated");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateRevoked");
}
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
{
info.Id = Guid.NewGuid().ToString("N");
return Update(info, cancellationToken);
}
public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
cancellationToken.ThrowIfCancellationRequested();
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
{
transaction = _connection.BeginTransaction();
var index = 0;
_saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id);
_saveInfoCommand.GetParameter(index++).Value = info.AccessToken;
_saveInfoCommand.GetParameter(index++).Value = info.DeviceId;
_saveInfoCommand.GetParameter(index++).Value = info.AppName;
_saveInfoCommand.GetParameter(index++).Value = info.DeviceName;
_saveInfoCommand.GetParameter(index++).Value = info.UserId;
_saveInfoCommand.GetParameter(index++).Value = info.IsActive;
_saveInfoCommand.GetParameter(index++).Value = info.DateCreated;
_saveInfoCommand.GetParameter(index++).Value = info.DateRevoked;
_saveInfoCommand.Transaction = transaction;
_saveInfoCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
_logger.ErrorException("Failed to save record:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
_writeLock.Release();
}
}
private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = BaseSelectText;
var whereClauses = new List<string>();
var startIndex = query.StartIndex ?? 0;
if (startIndex > 0)
{
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens ORDER BY DateCreated LIMIT {0})",
startIndex.ToString(_usCulture)));
}
if (!string.IsNullOrWhiteSpace(query.AccessToken))
{
whereClauses.Add("AccessToken=@AccessToken");
cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
}
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
if (!string.IsNullOrWhiteSpace(query.DeviceId))
{
whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
if (query.IsActive.HasValue)
{
whereClauses.Add("IsActive=@IsActive");
cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value;
}
if (whereClauses.Count > 0)
{
cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
}
cmd.CommandText += " ORDER BY DateCreated";
if (query.Limit.HasValue)
{
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from AccessTokens";
var list = new List<AuthenticationInfo>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
list.Add(Get(reader));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
return new QueryResult<AuthenticationInfo>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
public AuthenticationInfo Get(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException("id");
}
var guid = new Guid(id);
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = BaseSelectText + " where Id=@Id";
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
return Get(reader);
}
}
}
return null;
}
private AuthenticationInfo Get(IDataReader reader)
{
var s = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
var info = new AuthenticationInfo
{
Id = reader.GetGuid(0).ToString("N"),
AccessToken = reader.GetString(1)
};
if (!reader.IsDBNull(2))
{
info.DeviceId = reader.GetString(2);
}
if (!reader.IsDBNull(3))
{
info.AppName = reader.GetString(3);
}
if (!reader.IsDBNull(4))
{
info.DeviceName = reader.GetString(4);
}
if (!reader.IsDBNull(5))
{
info.UserId = reader.GetString(5);
}
info.IsActive = reader.GetBoolean(6);
info.DateCreated = reader.GetDateTime(7);
if (!reader.IsDBNull(8))
{
info.DateRevoked = reader.GetDateTime(8);
}
return info;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly object _disposeLock = new object();
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
try
{
lock (_disposeLock)
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing database", ex);
}
}
}
}
}

View File

@@ -1,6 +1,4 @@
using System.Security.Cryptography;
using System.Text;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -13,12 +11,14 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -27,7 +27,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Server.Implementations.Session
{
@@ -62,6 +61,8 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationHost _appHost;
private readonly IAuthenticationRepository _authRepo;
/// <summary>
/// Gets or sets the configuration manager.
/// </summary>
@@ -104,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient)
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@@ -119,6 +120,7 @@ namespace MediaBrowser.Server.Implementations.Session
_jsonSerializer = jsonSerializer;
_appHost = appHost;
_httpClient = httpClient;
_authRepo = authRepo;
}
/// <summary>
@@ -204,7 +206,12 @@ namespace MediaBrowser.Server.Implementations.Session
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
/// <exception cref="System.UnauthorizedAccessException"></exception>
public async Task<SessionInfo> LogSessionActivity(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user)
public async Task<SessionInfo> LogSessionActivity(string clientType,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
User user)
{
if (string.IsNullOrEmpty(clientType))
{
@@ -1157,7 +1164,37 @@ namespace MediaBrowser.Server.Implementations.Session
public void ValidateSecurityToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
throw new UnauthorizedAccessException();
}
var result = _authRepo.Get(new AuthenticationInfoQuery
{
AccessToken = token
});
var info = result.Items.FirstOrDefault();
if (info == null)
{
throw new UnauthorizedAccessException();
}
if (!info.IsActive)
{
throw new UnauthorizedAccessException("Access token has expired.");
}
if (!string.IsNullOrWhiteSpace(info.UserId))
{
var user = _userManager.GetUserById(new Guid(info.UserId));
if (user == null || user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException("User account has been disabled.");
}
}
}
/// <summary>
@@ -1175,7 +1212,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <exception cref="UnauthorizedAccessException"></exception>
public async Task<AuthenticationResult> AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint)
{
var result = await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
var result = IsLocalhost(remoteEndPoint) || await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
if (!result)
{
@@ -1185,6 +1222,8 @@ namespace MediaBrowser.Server.Implementations.Session
var user = _userManager.Users
.First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
var token = await GetAuthorizationToken(user.Id.ToString("N"), deviceId, clientType, deviceName).ConfigureAwait(false);
var session = await LogSessionActivity(clientType,
appVersion,
deviceId,
@@ -1197,11 +1236,108 @@ namespace MediaBrowser.Server.Implementations.Session
{
User = _dtoService.GetUserDto(user),
SessionInfo = GetSessionInfoDto(session),
AuthenticationToken = Guid.NewGuid().ToString("N")
AccessToken = token
};
}
private bool IsLocal(string remoteEndpoint)
private async Task<string> GetAuthorizationToken(string userId, string deviceId, string app, string deviceName)
{
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
DeviceId = deviceId,
IsActive = true,
UserId = userId,
Limit = 1
});
if (existing.Items.Length > 0)
{
_logger.Debug("Reissuing access token");
return existing.Items[0].AccessToken;
}
var newToken = new AuthenticationInfo
{
AppName = app,
DateCreated = DateTime.UtcNow,
DeviceId = deviceId,
DeviceName = deviceName,
UserId = userId,
IsActive = true,
AccessToken = Guid.NewGuid().ToString("N")
};
_logger.Debug("Creating new access token for user {0}", userId);
await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false);
return newToken.AccessToken;
}
public async Task Logout(string accessToken)
{
if (string.IsNullOrWhiteSpace(accessToken))
{
throw new ArgumentNullException("accessToken");
}
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
Limit = 1,
AccessToken = accessToken
}).Items.FirstOrDefault();
if (existing != null)
{
existing.IsActive = false;
await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false);
var sessions = Sessions
.Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
.ToList();
foreach (var session in sessions)
{
try
{
ReportSessionEnded(session.Id);
}
catch (Exception ex)
{
_logger.ErrorException("Error reporting session ended", ex);
}
}
}
}
public async Task RevokeUserTokens(string userId)
{
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
IsActive = true,
UserId = userId
});
foreach (var info in existing.Items)
{
await Logout(info.AccessToken).ConfigureAwait(false);
}
}
private bool IsLocalhost(string remoteEndpoint)
{
if (string.IsNullOrWhiteSpace(remoteEndpoint))
{
throw new ArgumentNullException("remoteEndpoint");
}
return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
}
public bool IsLocal(string remoteEndpoint)
{
if (string.IsNullOrWhiteSpace(remoteEndpoint))
{
@@ -1211,12 +1347,11 @@ namespace MediaBrowser.Server.Implementations.Session
// Private address space:
// http://en.wikipedia.org/wiki/Private_network
return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
return IsLocalhost(remoteEndpoint) ||
remoteEndpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
remoteEndpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
}
/// <summary>