added some user access settings

pull/702/head
Luke Pulverenti 11 years ago
parent 6992d31155
commit 56eea6a626

@ -3,6 +3,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Users;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using System;
@ -19,6 +20,11 @@ namespace MediaBrowser.Api
[Api(Description = "Gets a list of users")]
public class GetUsers : IReturn<List<UserDto>>
{
[ApiMember(Name = "IsHidden", Description="Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsHidden { get; set; }
[ApiMember(Name = "IsDisabled", Description = "Optional filter by IsDisabled=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsDisabled { get; set; }
}
/// <summary>
@ -56,7 +62,7 @@ namespace MediaBrowser.Api
/// </summary>
[Route("/Users/{Id}/Authenticate", "POST")]
[Api(Description = "Authenticates a user")]
public class AuthenticateUser : IReturnVoid
public class AuthenticateUser : IReturn<AuthenticationResult>
{
/// <summary>
/// Gets or sets the id.
@ -73,6 +79,28 @@ namespace MediaBrowser.Api
public string Password { get; set; }
}
/// <summary>
/// Class AuthenticateUser
/// </summary>
[Route("/Users/{Name}/AuthenticateByName", "POST")]
[Api(Description = "Authenticates a user")]
public class AuthenticateUserByName : IReturn<AuthenticationResult>
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the password.
/// </summary>
/// <value>The password.</value>
[ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
public string Password { get; set; }
}
/// <summary>
/// Class UpdateUserPassword
/// </summary>
@ -168,11 +196,21 @@ namespace MediaBrowser.Api
{
var dtoBuilder = new UserDtoBuilder(Logger);
var tasks = _userManager.Users.OrderBy(u => u.Name).Select(dtoBuilder.GetUserDto);
var users = _userManager.Users;
if (request.IsDisabled.HasValue)
{
users = users.Where(i => i.Configuration.IsDisabled == request.IsDisabled.Value);
}
if (request.IsHidden.HasValue)
{
users = users.Where(i => i.Configuration.IsHidden == request.IsHidden.Value);
}
var users = tasks.Select(i => i.Result).ToList();
var tasks = users.OrderBy(u => u.Name).Select(dtoBuilder.GetUserDto).Select(i => i.Result);
return ToOptimizedResult(users);
return ToOptimizedResult(tasks.ToList());
}
/// <summary>
@ -218,7 +256,21 @@ namespace MediaBrowser.Api
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
public void Post(AuthenticateUser request)
public object Post(AuthenticateUser request)
{
var result = AuthenticateUser(request).Result;
return ToOptimizedResult(result);
}
public object Post(AuthenticateUserByName request)
{
var user = _userManager.Users.FirstOrDefault(i => string.Equals(request.Name, i.Name, StringComparison.OrdinalIgnoreCase));
return AuthenticateUser(new AuthenticateUser { Id = user.Id, Password = request.Password }).Result;
}
private async Task<object> AuthenticateUser(AuthenticateUser request)
{
var user = _userManager.GetUserById(request.Id);
@ -227,13 +279,20 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("User not found");
}
var success = _userManager.AuthenticateUser(user, request.Password).Result;
var success = await _userManager.AuthenticateUser(user, request.Password).ConfigureAwait(false);
if (!success)
{
// Unauthorized
throw new UnauthorizedAccessException("Invalid user or password entered.");
}
var result = new AuthenticationResult
{
User = await new UserDtoBuilder(Logger).GetUserDto(user).ConfigureAwait(false)
};
return ToOptimizedResult(result);
}
/// <summary>
@ -294,6 +353,15 @@ namespace MediaBrowser.Api
}
}
// If removing admin access
if (dtoUser.Configuration.IsDisabled && !user.Configuration.IsDisabled)
{
if (_userManager.Users.Count(i => !i.Configuration.IsDisabled) == 1)
{
throw new ArgumentException("There must be at least one enabled user in the system.");
}
}
var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? _userManager.UpdateUser(user) : _userManager.RenameUser(user, dtoUser.Name);
Task.WaitAll(task);

@ -52,6 +52,9 @@
<Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs">
<Link>Configuration\BaseApplicationConfiguration.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\ManualLoginCategory.cs">
<Link>Configuration\ManualLoginCategory.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\ServerConfiguration.cs">
<Link>Configuration\ServerConfiguration.cs</Link>
</Compile>
@ -331,6 +334,9 @@
<Compile Include="..\MediaBrowser.Model\Updates\PackageVersionInfo.cs">
<Link>Updates\PackageVersionInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Users\AuthenticationResult.cs">
<Link>Users\AuthenticationResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Weather\WeatherUnits.cs">
<Link>Weather\WeatherUnits.cs</Link>
</Compile>

@ -0,0 +1,10 @@

namespace MediaBrowser.Model.Configuration
{
public enum ManualLoginCategory
{
Mobile,
MediaBrowserTheater,
Roku
}
}

@ -1,6 +1,6 @@
using MediaBrowser.Model.Entities;
using System;
using MediaBrowser.Model.Weather;
using System;
namespace MediaBrowser.Model.Configuration
{
@ -20,7 +20,7 @@ namespace MediaBrowser.Model.Configuration
/// </summary>
/// <value>The weather unit.</value>
public WeatherUnits WeatherUnit { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable HTTP level logging].
/// </summary>
@ -223,6 +223,8 @@ namespace MediaBrowser.Model.Configuration
/// <value>The dashboard source path.</value>
public string DashboardSourcePath { get; set; }
public ManualLoginCategory[] ManualLoginClients { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary>
@ -249,6 +251,8 @@ namespace MediaBrowser.Model.Configuration
EnableInternetProviders = true; //initial installs will need these
InternetProviderExcludeTypes = new string[] { };
ManualLoginClients = new ManualLoginCategory[] { };
MetadataRefreshDays = 30;
PreferredMetadataLanguage = "en";
MetadataCountryCode = "US";

@ -47,7 +47,15 @@ namespace MediaBrowser.Model.Configuration
/// </summary>
/// <value><c>true</c> if [use forced subtitles only]; otherwise, <c>false</c>.</value>
public bool UseForcedSubtitlesOnly { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is hidden.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool IsHidden { get; set; }
public bool IsDisabled { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
/// </summary>

@ -43,6 +43,7 @@
</Compile>
<Compile Include="ApiClient\IApiClient.cs" />
<Compile Include="Configuration\BaseApplicationConfiguration.cs" />
<Compile Include="Configuration\ManualLoginCategory.cs" />
<Compile Include="Configuration\ServerConfiguration.cs" />
<Compile Include="Dto\BaseItemPerson.cs" />
<Compile Include="Dto\ChapterInfoDto.cs" />
@ -141,6 +142,7 @@
<Compile Include="Tasks\TaskTriggerInfo.cs" />
<Compile Include="Updates\PackageInfo.cs" />
<Compile Include="Updates\PackageVersionInfo.cs" />
<Compile Include="Users\AuthenticationResult.cs" />
<Compile Include="Weather\WeatherUnits.cs" />
<Compile Include="Web\QueryStringDictionary.cs" />
<None Include="FodyWeavers.xml" />

@ -0,0 +1,9 @@
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Model.Users
{
public class AuthenticationResult
{
public UserDto User { get; set; }
}
}

@ -1,10 +1,7 @@
using System.IO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
@ -12,12 +9,12 @@ using MediaBrowser.Model.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Session;
namespace MediaBrowser.Server.Implementations.Library
{
@ -174,6 +171,11 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("user");
}
if (user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
}
var existingPasswordString = string.IsNullOrEmpty(user.Password) ? GetSha1String(string.Empty) : user.Password;
var success = string.Equals(existingPasswordString, password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);

@ -101,6 +101,11 @@ namespace MediaBrowser.Server.Implementations.Session
/// <exception cref="System.ArgumentNullException">user</exception>
public Task LogConnectionActivity(string clientType, string deviceId, string deviceName, User user)
{
if (user != null && user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
}
var activityDate = DateTime.UtcNow;
GetConnection(clientType, deviceId, deviceName, user).LastActivityDate = activityDate;

@ -5,7 +5,6 @@ using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
@ -221,7 +220,21 @@ namespace MediaBrowser.WebDashboard.Api
/// <returns>System.Object.</returns>
public object Get(GetDashboardConfigurationPages request)
{
var pages = ServerEntryPoint.Instance.PluginConfigurationPages;
const string unavilableMessage = "The server is still loading. Please try again momentarily.";
var instance = ServerEntryPoint.Instance;
if (instance == null)
{
throw new InvalidOperationException(unavilableMessage);
}
var pages = instance.PluginConfigurationPages;
if (pages == null)
{
throw new InvalidOperationException(unavilableMessage);
}
if (request.PageType.HasValue)
{
@ -428,6 +441,7 @@ namespace MediaBrowser.WebDashboard.Api
"librarybrowser.js",
"aboutpage.js",
"allusersettings.js",
"alphapicker.js",
"addpluginpage.js",
"advancedconfigurationpage.js",

@ -1432,9 +1432,9 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
/**
* Gets all users from the server
*/
self.getUsers = function () {
self.getUsers = function (options) {
var url = self.getUrl("users");
var url = self.getUrl("users", options || {});
return self.ajax({
type: "GET",
@ -1870,6 +1870,32 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
return files;
};
/**
* Authenticates a user
* @param {String} name
* @param {String} password
*/
self.authenticateUserByName = function (name, password) {
if (!name) {
throw new Error("null name");
}
var url = self.getUrl("Users/" + name + "/authenticatebyname");
var postData = {
password: MediaBrowser.SHA1(password || "")
};
return self.ajax({
type: "POST",
url: url,
data: JSON.stringify(postData),
dataType: "json",
contentType: "application/json"
});
};
/**
* Authenticates a user
* @param {String} userId
@ -1891,6 +1917,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
type: "POST",
url: url,
data: JSON.stringify(postData),
dataType: "json",
contentType: "application/json"
});
};

@ -81,6 +81,9 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ApiClient.js" />
<Content Include="dashboard-ui\allusersettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\boxsets.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -354,6 +357,9 @@
<Content Include="dashboard-ui\musicvideos.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\allusersettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\alphapicker.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.135" targetFramework="net45" />
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.138" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.54" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.54" targetFramework="net45" />
</packages>
Loading…
Cancel
Save