From fa42486e1cff6ff39f40e83bfc652bf632c0a9c0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 4 Feb 2016 12:50:24 -0500 Subject: [PATCH] stub out pin login service --- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 + MediaBrowser.Api/PinLoginService.cs | 146 +++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 MediaBrowser.Api/PinLoginService.cs diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 7e55446ae..f711c69e6 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -80,6 +80,7 @@ + diff --git a/MediaBrowser.Api/PinLoginService.cs b/MediaBrowser.Api/PinLoginService.cs new file mode 100644 index 000000000..81d590395 --- /dev/null +++ b/MediaBrowser.Api/PinLoginService.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Concurrent; +using System.Globalization; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Connect; +using ServiceStack; + +namespace MediaBrowser.Api +{ + [Route("/Auth/Pin", "POST", Summary = "Creates a pin request")] + public class CreatePinRequest : IReturn + { + public string DeviceId { get; set; } + } + + [Route("/Auth/Pin", "GET", Summary = "Gets pin status")] + public class GetPinStatusRequest : IReturn + { + public string DeviceId { get; set; } + public string Pin { get; set; } + } + + [Route("/Auth/Pin/Exchange", "POST", Summary = "Exchanges a pin")] + public class ExchangePinRequest : IReturn + { + public string DeviceId { get; set; } + public string Pin { get; set; } + } + + [Route("/Auth/Pin/Validate", "POST", Summary = "Validates a pin")] + [Authenticated] + public class ValidatePinRequest : IReturnVoid + { + public string Pin { get; set; } + } + + public class PinLoginService : BaseApiService + { + private readonly ConcurrentDictionary _activeRequests = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + + public object Post(CreatePinRequest request) + { + var pin = GetNewPin(5); + var key = GetKey(request.DeviceId, pin); + + var value = new MyPinStatus + { + CreationTimeUtc = DateTime.UtcNow, + IsConfirmed = false, + IsExpired = false, + Pin = pin + }; + + _activeRequests.AddOrUpdate(key, value, (k, v) => value); + + return ToOptimizedResult(new PinCreationResult + { + DeviceId = request.DeviceId, + IsConfirmed = false, + IsExpired = false, + Pin = pin + }); + } + + public object Get(GetPinStatusRequest request) + { + MyPinStatus status; + + if (!_activeRequests.TryGetValue(GetKey(request.DeviceId, request.Pin), out status)) + { + throw new ResourceNotFoundException(); + } + + CheckExpired(status); + + if (status.IsExpired) + { + throw new ResourceNotFoundException(); + } + + return ToOptimizedResult(new PinStatusResult + { + Pin = status.Pin, + IsConfirmed = status.IsConfirmed, + IsExpired = status.IsExpired + }); + } + + public object Post(ExchangePinRequest request) + { + MyPinStatus status; + + if (!_activeRequests.TryGetValue(GetKey(request.DeviceId, request.Pin), out status)) + { + throw new ResourceNotFoundException(); + } + + CheckExpired(status); + + if (status.IsExpired) + { + throw new ResourceNotFoundException(); + } + + return ToOptimizedResult(new PinExchangeResult + { + }); + } + + public void Post(ValidatePinRequest request) + { + } + + private void CheckExpired(MyPinStatus status) + { + if ((DateTime.UtcNow - status.CreationTimeUtc).TotalMinutes > 10) + { + status.IsExpired = true; + } + } + + private string GetNewPin(int length) + { + var pin = string.Empty; + + while (pin.Length < length) + { + var digit = new Random().Next(0, 9); + pin += digit.ToString(CultureInfo.InvariantCulture); + } + + return pin; + } + + private string GetKey(string deviceId, string pin) + { + return deviceId + pin; + } + + public class MyPinStatus : PinStatusResult + { + public DateTime CreationTimeUtc { get; set; } + } + } +}