diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 5ff1b8949..c830b7efc 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -292,7 +292,8 @@ namespace MediaBrowser.Api { Id = user.Id, Name = user.Name, - HasImage = !string.IsNullOrEmpty(user.PrimaryImagePath) + HasImage = !string.IsNullOrEmpty(user.PrimaryImagePath), + HasPassword = !string.IsNullOrEmpty(user.Password) }; } } diff --git a/MediaBrowser.Api/HttpHandlers/UserAuthenticationHandler.cs b/MediaBrowser.Api/HttpHandlers/UserAuthenticationHandler.cs new file mode 100644 index 000000000..0905016c4 --- /dev/null +++ b/MediaBrowser.Api/HttpHandlers/UserAuthenticationHandler.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Controller; +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Api.HttpHandlers +{ + class UserAuthenticationHandler : BaseSerializationHandler + { + protected override async Task GetObjectToSerialize() + { + Guid userId = Guid.Parse(QueryString["userid"]); + User user = Kernel.Instance.Users.First(u => u.Id == userId); + + string password = await GetFormValue("password").ConfigureAwait(false); + + AuthenticationResult result = new AuthenticationResult() + { + Success = true + }; + + return result; + } + } +} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 8f387e065..7b17606a8 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -73,6 +73,7 @@ + diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs index e83f366df..f254adbb6 100644 --- a/MediaBrowser.Api/Plugin.cs +++ b/MediaBrowser.Api/Plugin.cs @@ -117,6 +117,10 @@ namespace MediaBrowser.Api { return new PluginAssemblyHandler(); } + else if (IsUrlMatch("/api/UserAuthentication", localPath)) + { + return new UserAuthenticationHandler(); + } return null; } diff --git a/MediaBrowser.ApiInteraction.Metro/DataSerializer.cs b/MediaBrowser.ApiInteraction.Metro/DataSerializer.cs index 452ca43f4..8af88014c 100644 --- a/MediaBrowser.ApiInteraction.Metro/DataSerializer.cs +++ b/MediaBrowser.ApiInteraction.Metro/DataSerializer.cs @@ -13,18 +13,22 @@ namespace MediaBrowser.ApiInteraction { return Serializer.Deserialize(stream); } - if (format == ApiInteraction.SerializationFormats.Jsv) + else if (format == ApiInteraction.SerializationFormats.Jsv) { throw new NotImplementedException(); } - - using (StreamReader streamReader = new StreamReader(stream)) + else if (format == ApiInteraction.SerializationFormats.Json) { - using (JsonReader jsonReader = new JsonTextReader(streamReader)) + using (StreamReader streamReader = new StreamReader(stream)) { - return JsonSerializer.Create(new JsonSerializerSettings()).Deserialize(jsonReader); + using (JsonReader jsonReader = new JsonTextReader(streamReader)) + { + return JsonSerializer.Create(new JsonSerializerSettings()).Deserialize(jsonReader); + } } } + + throw new NotImplementedException(); } public static object DeserializeFromStream(Stream stream, SerializationFormats format, Type type) @@ -33,18 +37,22 @@ namespace MediaBrowser.ApiInteraction { throw new NotImplementedException(); } - if (format == ApiInteraction.SerializationFormats.Jsv) + else if (format == ApiInteraction.SerializationFormats.Jsv) { throw new NotImplementedException(); } - - using (StreamReader streamReader = new StreamReader(stream)) + else if (format == ApiInteraction.SerializationFormats.Json) { - using (JsonReader jsonReader = new JsonTextReader(streamReader)) + using (StreamReader streamReader = new StreamReader(stream)) { - return JsonSerializer.Create(new JsonSerializerSettings()).Deserialize(jsonReader, type); + using (JsonReader jsonReader = new JsonTextReader(streamReader)) + { + return JsonSerializer.Create(new JsonSerializerSettings()).Deserialize(jsonReader, type); + } } } + + throw new NotImplementedException(); } public static void Configure() diff --git a/MediaBrowser.ApiInteraction/ApiClient.cs b/MediaBrowser.ApiInteraction/ApiClient.cs index 7145c1465..48f43e03b 100644 --- a/MediaBrowser.ApiInteraction/ApiClient.cs +++ b/MediaBrowser.ApiInteraction/ApiClient.cs @@ -7,6 +7,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Weather; +using System.Text; namespace MediaBrowser.ApiInteraction { @@ -648,6 +649,24 @@ namespace MediaBrowser.ApiInteraction } } + /// + /// Authenticates a user and returns the result + /// + public async Task AuthenticateUser(Guid userId, string password) + { + string url = ApiUrl + "/UserAuthentication?userId=" + userId; + url += "&dataformat=" + SerializationFormat.ToString(); + + HttpContent content = new StringContent("password=" + password, Encoding.UTF8, "application/x-www-form-urlencoded"); + + HttpResponseMessage msg = await HttpClient.PostAsync(url, content).ConfigureAwait(false); + + using (Stream stream = await msg.Content.ReadAsStreamAsync().ConfigureAwait(false)) + { + return DeserializeFromStream(stream); + } + } + /// /// This is a helper around getting a stream from the server that contains serialized data /// @@ -663,11 +682,11 @@ namespace MediaBrowser.ApiInteraction { if (url.IndexOf('?') == -1) { - url += "?dataformat=" + serializationFormat.ToString().ToLower(); + url += "?dataformat=" + serializationFormat.ToString(); } else { - url += "&dataformat=" + serializationFormat.ToString().ToLower(); + url += "&dataformat=" + serializationFormat.ToString(); } return GetStreamAsync(url); diff --git a/MediaBrowser.ApiInteraction/DataSerializer.cs b/MediaBrowser.ApiInteraction/DataSerializer.cs index 45fd60ecf..c455bd15e 100644 --- a/MediaBrowser.ApiInteraction/DataSerializer.cs +++ b/MediaBrowser.ApiInteraction/DataSerializer.cs @@ -13,12 +13,16 @@ namespace MediaBrowser.ApiInteraction { return Serializer.Deserialize(stream); } - if (format == ApiInteraction.SerializationFormats.Jsv) + else if (format == ApiInteraction.SerializationFormats.Jsv) { return TypeSerializer.DeserializeFromStream(stream); } + else if (format == ApiInteraction.SerializationFormats.Json) + { + return JsonSerializer.DeserializeFromStream(stream); + } - return JsonSerializer.DeserializeFromStream(stream); + throw new NotImplementedException(); } public static object DeserializeFromStream(Stream stream, SerializationFormats format, Type type) @@ -27,12 +31,16 @@ namespace MediaBrowser.ApiInteraction { throw new NotImplementedException(); } - if (format == ApiInteraction.SerializationFormats.Jsv) + else if (format == ApiInteraction.SerializationFormats.Jsv) { return TypeSerializer.DeserializeFromStream(type, stream); } + else if (format == ApiInteraction.SerializationFormats.Json) + { + return JsonSerializer.DeserializeFromStream(type, stream); + } - return JsonSerializer.DeserializeFromStream(type, stream); + throw new NotImplementedException(); } public static void Configure() diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 2697acf72..ba70362b5 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -65,6 +65,7 @@ + ..\packages\MahApps.Metro.0.9.0.0\lib\net40\System.Windows.Interactivity.dll diff --git a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs index 2462833ff..19674fadd 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs @@ -1,11 +1,14 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; +using System.Text; using System.Threading.Tasks; +using System.Web; using MediaBrowser.Common.Logging; namespace MediaBrowser.Common.Net.Handlers @@ -374,5 +377,65 @@ namespace MediaBrowser.Common.Net.Handlers return StatusCode == 200 || StatusCode == 206; } } + + private Hashtable _FormValues = null; + + /// + /// Gets a value from form POST data + /// + protected async Task GetFormValue(string name) + { + if (_FormValues == null) + { + _FormValues = await GetFormValues(HttpListenerContext.Request).ConfigureAwait(false); + } + + if (_FormValues.ContainsKey(name)) + { + return _FormValues[name].ToString(); + } + + return null; + } + + /// + /// Extracts form POST data from a request + /// + private async Task GetFormValues(HttpListenerRequest request) + { + Hashtable formVars = new Hashtable(); + + if (request.HasEntityBody) + { + if (request.ContentType.Equals("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) + { + using (Stream requestBody = request.InputStream) + { + using (StreamReader reader = new StreamReader(requestBody, request.ContentEncoding)) + { + string s = await reader.ReadToEndAsync().ConfigureAwait(false); + + string[] pairs = s.Split('&'); + + for (int x = 0; x < pairs.Length; x++) + { + string pair = pairs[x]; + + int index = pair.IndexOf('='); + + if (index != -1) + { + string name = pair.Substring(0, index); + string value = pair.Substring(index + 1); + formVars.Add(name, value); + } + } + } + } + } + } + + return formVars; + } } } \ No newline at end of file diff --git a/MediaBrowser.Model/DTO/AuthenticationResult.cs b/MediaBrowser.Model/DTO/AuthenticationResult.cs new file mode 100644 index 000000000..ce492b60e --- /dev/null +++ b/MediaBrowser.Model/DTO/AuthenticationResult.cs @@ -0,0 +1,12 @@ +using System; +using ProtoBuf; + +namespace MediaBrowser.Model.DTO +{ + [ProtoContract] + public class AuthenticationResult + { + [ProtoMember(1)] + public bool Success { get; set; } + } +} diff --git a/MediaBrowser.Model/DTO/DTOUser.cs b/MediaBrowser.Model/DTO/DTOUser.cs index 512985731..61ca0593f 100644 --- a/MediaBrowser.Model/DTO/DTOUser.cs +++ b/MediaBrowser.Model/DTO/DTOUser.cs @@ -14,5 +14,8 @@ namespace MediaBrowser.Model.DTO [ProtoMember(3)] public bool HasImage { get; set; } + + [ProtoMember(4)] + public bool HasPassword { get; set; } } } diff --git a/MediaBrowser.Model/Entities/User.cs b/MediaBrowser.Model/Entities/User.cs index 921727631..4c51880ac 100644 --- a/MediaBrowser.Model/Entities/User.cs +++ b/MediaBrowser.Model/Entities/User.cs @@ -3,6 +3,8 @@ namespace MediaBrowser.Model.Entities { public class User : BaseEntity { + public string Password { get; set; } + public string MaxParentalRating { get; set; } public int RecentItemDays { get; set; } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 98904a6b6..da6fac538 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -35,6 +35,7 @@ +