Refactored how we check if the user has a valid api key
Added POST request, PUT and DELTE

Also some work on the updater #29
pull/226/head
tidusjar 9 years ago
parent 030c013862
commit 7266f20927

@ -1,71 +1,137 @@
using System;
using PlexRequests.UI.Modules;
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: ApiModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using Nancy;
using Nancy.Extensions;
using Nancy.ModelBinding;
using Nancy.Responses.Negotiation;
using Nancy.Validation;
using PlexRequests.Core;
using System.Collections.Generic;
using PlexRequests.Store;
using PlexRequests.Core.SettingModels;
namespace PlexRequests.UI.Modules
{
public class ApiModule : BaseModule
{
public ApiModule (IRequestService service, ISettingsService<PlexRequestSettings> settings) : base("api")
{
Get ["/requests"] = x => GetRequests ();
RequestService = service;
Settings = settings;
}
private IRequestService RequestService{ get; }
private ISettingsService<PlexRequestSettings> Settings{get;}
public Response GetRequests()
{
var apiModel = new ApiModel<List<RequestedModel>>{Data = new List<RequestedModel>()};
if (!Authenticated ()) {
apiModel.Error = true;
apiModel.ErrorMessage = "ApiKey is invalid or not present, Please use 'apikey' in the querystring.";
return ReturnReponse (apiModel);
}
var requests = RequestService.GetAll ();
apiModel.Data.AddRange (requests);
return ReturnReponse (apiModel);
}
private Response ReturnReponse(object result)
{
var queryString = (DynamicDictionary)Context.Request.Query;
dynamic value;
if (queryString.TryGetValue("xml", out value)) {
if ((bool)value) {
return Response.AsXml (result);
}
}
return Response.AsJson (result);
}
private bool Authenticated(){
var query = (DynamicDictionary)Context.Request.Query;
dynamic key;
if (!query.TryGetValue ("apikey", out key)) {
return false;
}
var settings = Settings.GetSettings ();
if ((string)key == settings.ApiKey) {
return true;
}
return false;
}
}
}
public class ApiModule : BaseApiModule
{
public ApiModule(IRequestService service) : base("api/v1/")
{
Get["/requests"] = x => GetRequests();
Post["/requests"] = x => CreateRequest();
Put["/requests"] = x => UpdateRequest();
Delete["/requests"] = x => DeleteRequest();
RequestService = service;
}
private IRequestService RequestService { get; }
public Response GetRequests()
{
var apiModel = new ApiModel<List<RequestedModel>> { Data = new List<RequestedModel>() };
var requests = RequestService.GetAll();
apiModel.Data.AddRange(requests);
return ReturnReponse(apiModel);
}
public Response CreateRequest()
{
var request = this.Bind<RequestedModel>();
var valid = this.Validate(request);
if (!valid.IsValid)
{
return ReturnValidationReponse(valid);
}
var apiModel = new ApiModel<bool>();
var result = RequestService.AddRequest(request);
if (result == -1)
{
apiModel.Error = true;
apiModel.ErrorMessage = "Could not insert the new request into the database. Internal error.";
return ReturnReponse(apiModel);
}
apiModel.Data = true;
return ReturnReponse(apiModel);
}
public Response UpdateRequest()
{
var request = this.Bind<RequestedModel>();
var valid = this.Validate(request);
if (!valid.IsValid)
{
return ReturnValidationReponse(valid);
}
var apiModel = new ApiModel<bool>();
var result = RequestService.UpdateRequest(request);
if (!result)
{
apiModel.Error = true;
apiModel.ErrorMessage = "Could not update the request into the database. Internal error.";
return ReturnReponse(apiModel);
}
apiModel.Data = true;
return ReturnReponse(apiModel);
}
public Response DeleteRequest()
{
var request = this.Bind<RequestedModel>();
var valid = this.Validate(request);
if (!valid.IsValid)
{
return ReturnValidationReponse(valid);
}
var apiModel = new ApiModel<bool>();
try
{
RequestService.DeleteRequest(request);
apiModel.Data = true;
return ReturnReponse(apiModel);
}
catch (Exception)
{
apiModel.Error = true;
apiModel.ErrorMessage = "Could not delete the request from the database. Internal error.";
return ReturnReponse(apiModel);
}
}
}
}

@ -0,0 +1,112 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: BaseApiModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System.Collections.Generic;
using System.Linq;
using Nancy;
using Nancy.Validation;
using PlexRequests.Core.SettingModels;
using PlexRequests.Store;
namespace PlexRequests.UI.Modules
{
public abstract class BaseApiModule : BaseModule
{
protected BaseApiModule()
{
Before += (ctx) => CheckAuth();
}
protected BaseApiModule(string modulePath) : base(modulePath)
{
Before += (ctx) => CheckAuth();
}
protected Response ReturnReponse(object result)
{
var queryString = (DynamicDictionary)Context.Request.Query;
dynamic value;
if (queryString.TryGetValue("xml", out value))
{
if ((bool)value)
{
return Response.AsXml(result);
}
}
return Response.AsJson(result);
}
protected Response ReturnValidationReponse(ModelValidationResult result)
{
var errors = result.Errors;
var model = new ApiModel<List<string>>
{
Error = true,
ErrorMessage = "Please view the error messages inside the data node",
Data = new List<string>()
};
foreach (var error in errors)
{
model.Data.AddRange(error.Value.Select(x => x.ErrorMessage));
}
return ReturnReponse(model);
}
private Response CheckAuth()
{
var settings = Settings.GetSettings();
var apiModel = new ApiModel<List<RequestedModel>> { Data = new List<RequestedModel>() };
if (!Authenticated(settings))
{
apiModel.Error = true;
apiModel.ErrorMessage = "ApiKey is invalid or not present, Please use 'apikey' in the querystring.";
return ReturnReponse(apiModel);
}
return null;
}
private bool Authenticated(PlexRequestSettings settings)
{
var query = (DynamicDictionary)Context.Request.Query;
dynamic key;
if (!query.TryGetValue("apikey", out key))
{
return false;
}
if ((string)key == settings.ApiKey)
{
return true;
}
return false;
}
}
}

@ -33,15 +33,13 @@ using Nancy.Extensions;
using PlexRequests.UI.Models;
using System;
using Nancy.Security;
using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
namespace PlexRequests.UI.Modules
{
public class BaseAuthModule : BaseModule
public abstract class BaseAuthModule : BaseModule
{
private string _username;
private int _dateTimeOffset = -1;
@ -77,12 +75,12 @@ namespace PlexRequests.UI.Modules
}
}
public BaseAuthModule()
protected BaseAuthModule()
{
Before += (ctx) => CheckAuth();
}
public BaseAuthModule(string modulePath) : base(modulePath)
protected BaseAuthModule(string modulePath) : base(modulePath)
{
Before += (ctx) => CheckAuth();
}
@ -99,8 +97,5 @@ namespace PlexRequests.UI.Modules
? Context.GetRedirect(redirectPath)
: null;
}
}
}

@ -32,13 +32,15 @@ using PlexRequests.UI.Helpers;
namespace PlexRequests.UI.Modules
{
public class BaseModule : NancyModule
public abstract class BaseModule : NancyModule
{
protected ServiceLocator Locator => ServiceLocator.Instance;
protected ISettingsService<PlexRequestSettings> Settings => Locator.Resolve<ISettingsService<PlexRequestSettings>>();
protected string BaseUrl { get; set; }
public BaseModule()
protected BaseModule()
{
var settings = Locator.Resolve<ISettingsService<PlexRequestSettings>>().GetSettings();
var settings = Settings.GetSettings();
var baseUrl = settings.BaseUrl;
BaseUrl = baseUrl;
@ -47,9 +49,9 @@ namespace PlexRequests.UI.Modules
ModulePath = modulePath;
}
public BaseModule(string modulePath)
protected BaseModule(string modulePath)
{
var settings = Locator.Resolve<ISettingsService<PlexRequestSettings>>().GetSettings();
var settings = Settings.GetSettings();
var baseUrl = settings.BaseUrl;
BaseUrl = baseUrl;

@ -158,9 +158,11 @@
<Compile Include="Models\SearchViewModel.cs" />
<Compile Include="Models\SearchMusicViewModel.cs" />
<Compile Include="Models\SearchMovieViewModel.cs" />
<Compile Include="Modules\BaseApiModule.cs" />
<Compile Include="Modules\BaseModule.cs" />
<Compile Include="Modules\UpdateCheckerModule.cs" />
<Compile Include="Start\StartupOptions.cs" />
<Compile Include="Start\UpdateValue.cs" />
<Compile Include="Validators\HeadphonesValidator.cs" />
<Compile Include="Validators\PushoverSettingsValidator.cs" />
<Compile Include="Validators\PushbulletSettingsValidator.cs" />

@ -61,7 +61,7 @@ namespace PlexRequests.UI
x => x.Port,
e => -1);
var updated = result.MapResult(x => x.Updated, e => false);
var updated = result.MapResult(x => x.Updated, e => UpdateValue.None);
//TODO
PrintToConsole("Starting Up! Please wait, this can usually take a few seconds.", ConsoleColor.Yellow);
@ -158,5 +158,17 @@ namespace PlexRequests.UI
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray;
}
private static void CheckUpdate(UpdateValue val)
{
if (val == UpdateValue.Failed)
{
}
if (val == UpdateValue.Updated)
{
// TODO Change the name of PlexRequests.Updater.exe_Updated and delete the old version
}
}
}
}

@ -57,7 +57,7 @@ namespace PlexRequests.UI.Start
/// <c>true</c> if updated; otherwise, <c>false</c>.
/// </value>
[Option('u', "updated", Required = false, HelpText = "This should only be used by the internal application")]
public bool Updated { get; set; }
public UpdateValue Updated { get; set; }
}
}

@ -0,0 +1,35 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: UpdateValue.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
namespace PlexRequests.UI.Start
{
public enum UpdateValue
{
None,
Updated,
Failed
}
}

@ -56,6 +56,8 @@
<li><a href="@url/admin"><i class="fa fa-cog"></i> Settings</a></li>
<li><a href="@url/changepassword"><i class="fa fa-key"></i> Change password</a></li>
<li class="divider"></li>
<li><a href="@url/logout"><i class="fa fa-heart"></i> Donate!</a></li>
<li class="divider"></li>
<li><a href="@url/logout"><i class="fa fa-sign-out"></i> Logout</a></li>
</ul>
</li>
@ -70,14 +72,14 @@
<div id="updateAvailable" hidden="hidden"></div>
</nav>
<div class="container">
@RenderBody()
</div>
<div class="scroll-top-wrapper ">
<span class="scroll-top-inner">
<div class="container">
@RenderBody()
</div>
<div class="scroll-top-wrapper ">
<span class="scroll-top-inner">
<i class="fa fa-2x fa-arrow-circle-up"></i>
</span>
</div>
</div>
</body>
</html>
<script>
@ -93,7 +95,7 @@
success: function (response) {
if (response.updateAvailable) {
var status = createBaseUrl(urlBase, '/admin/status');
$('#updateAvailable').html("<i class='fa fa-cloud-download' aria-hidden='true'></i> There is a new update available! Click <a style='color: white' href='"+status+"'>Here!</a>");
$('#updateAvailable').html("<i class='fa fa-cloud-download' aria-hidden='true'></i> There is a new update available! Click <a style='color: white' href='" + status + "'>Here!</a>");
$('#updateAvailable').removeAttr("hidden");
}
},

@ -192,7 +192,7 @@ namespace PlexRequests.Updater
private void FinishUpdate()
{
var startInfo = new ProcessStartInfo("PlexRequests.exe") { Arguments = Error ? "-u false" : "-u true" };
var startInfo = new ProcessStartInfo("PlexRequests.exe") { Arguments = Error ? "-u 2" : "-u 1" };
Process.Start(startInfo);
Environment.Exit(0);

Loading…
Cancel
Save