Added the ability to get the apikey from the api if you provide a correct username and password.

Added more unit tests
Added the ability to change a users password using the api
refactored the Usermapper and made it unit testsable.

Also api documentation for the new endpoints too.

#222 #205
This commit is contained in:
tidusjar 2016-05-20 10:44:02 +01:00
parent 84dc4515fd
commit cbfe88cd6d
14 changed files with 424 additions and 44 deletions

View file

@ -709,17 +709,14 @@ namespace PlexRequests.UI.Modules
private Response CreateApiKey()
{
this.RequiresClaims (UserClaims.Admin);
var apiKey = Guid.NewGuid ().ToString ("N");
var settings = PrService.GetSettings ();
this.RequiresClaims(UserClaims.Admin);
var apiKey = Guid.NewGuid().ToString("N");
var settings = PrService.GetSettings();
settings.ApiKey = apiKey;
PrService.SaveSettings(settings);
PrService.SaveSettings (settings);
return Response.AsJson (apiKey);
return Response.AsJson(apiKey);
}
}
}

View file

@ -30,6 +30,7 @@ using Nancy.Metadata.Modules;
using Nancy.Swagger;
using PlexRequests.Store;
using PlexRequests.UI.Models;
namespace PlexRequests.UI.Modules
{
@ -83,11 +84,32 @@ namespace PlexRequests.UI.Modules
with.ResourcePath("/requests/{id}");
with.Summary("Deletes an existing request");
with.Model<ApiModel<bool>>();
with.PathParam<int>("id");
with.PathParam<int>("id", required:true);
with.QueryParam<string>("apikey", "The Api Key found in the settings", true);
with.Notes("Deletes an existing request. If the request doesn't exist we will return an error.");
});
Describe["GetApiKey"] = description => description.AsSwagger(with =>
{
with.ResourcePath("/apikey");
with.Summary("Gets the Api Key for Plex Requests");
with.Model<ApiModel<string>>();
with.QueryParam<string>("username", required:true );
with.QueryParam<string>("password", required: true );
with.Notes("Get's the current api key for the application");
});
Describe["PutCredentials"] = description => description.AsSwagger(with =>
{
with.ResourcePath("/credentials/{username}");
with.Summary("Sets a new password for the user");
with.Model<ApiModel<string>>();
with.PathParam<int>("username", required:true);
with.QueryParam<string>("apikey", "The Api Key found in the settings", true);
with.BodyParam<UserUpdateViewModel>("User update view model", true);
with.Notes("Sets a new password for the user");
});
}
}
}

View file

@ -26,7 +26,6 @@
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Nancy;
using Nancy.ModelBinding;
@ -34,12 +33,13 @@ using Nancy.ModelBinding;
using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
using PlexRequests.Store;
using PlexRequests.UI.Models;
namespace PlexRequests.UI.Modules
{
public class ApiModule : BaseApiModule
{
public ApiModule(IRequestService service, ISettingsService<PlexRequestSettings> pr) : base("api", pr)
public ApiModule(IRequestService service, ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m) : base("api", pr)
{
Get["GetRequests","/requests"] = x => GetRequests();
Get["GetRequest","/requests/{id}"] = x => GetSingleRequests(x);
@ -47,10 +47,18 @@ namespace PlexRequests.UI.Modules
Put["PutRequests", "/requests"] = x => UpdateRequest();
Delete["DeleteRequests", "/requests/{id}"] = x => DeleteRequest(x);
Get["GetApiKey", "/apikey"] = x => GetApiKey();
Put["PutCredentials", "/credentials/{username}"] = x => ChangePassword(x);
RequestService = service;
SettingsService = pr;
UserMapper = m;
}
private IRequestService RequestService { get; }
private ISettingsService<PlexRequestSettings> SettingsService { get; }
private ICustomUserMapper UserMapper { get; }
public Response GetRequests()
{
@ -156,6 +164,54 @@ namespace PlexRequests.UI.Modules
}
}
public Response GetApiKey()
{
var user = Request.Query["username"];
var password = Request.Query["password"];
var result = UserMapper.ValidateUser(user, password);
var model = new ApiModel<string>();
if (result == null)
{
model.Error = true;
model.ErrorMessage = "Incorrect username or password";
return ReturnReponse(model);
}
var settings = SettingsService.GetSettings();
model.Data = settings.ApiKey;
return ReturnReponse(model);
}
public Response ChangePassword(dynamic x)
{
var username = (string)x.username;
var userModel = this.BindAndValidate<UserUpdateViewModel>();
if (!ModelValidationResult.IsValid)
{
return ReturnValidationReponse(ModelValidationResult);
}
var valid = UserMapper.ValidateUser(username, userModel.CurrentPassword);
if (valid == null)
{
var errorModel = new ApiModel<string> { Error = true, ErrorMessage = "Incorrect username or password" };
return ReturnReponse(errorModel);
}
var result = UserMapper.UpdatePassword(username, userModel.CurrentPassword, userModel.NewPassword);
if (!result)
{
var errorModel = new ApiModel<string> { Error = true, ErrorMessage = "Could not update the password. " };
return ReturnReponse(errorModel);
}
var model = new ApiModel<string> { Data = "Successfully updated the password"};
return ReturnReponse(model);
}
}
}

View file

@ -86,6 +86,10 @@ namespace PlexRequests.UI.Modules
private Response CheckAuth()
{
if (Request.Path.Contains("api/apikey")) // We do not need the apikey for this call
{
return null;
}
var settings = Settings.GetSettings();
var apiModel = new ApiModel<List<RequestedModel>> { Data = new List<RequestedModel>() };
if (!Authenticated(settings))

View file

@ -41,8 +41,9 @@ namespace PlexRequests.UI.Modules
{
public class LoginModule : BaseModule
{
public LoginModule(ISettingsService<PlexRequestSettings> pr) : base(pr)
public LoginModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m) : base(pr)
{
UserMapper = m;
Get["/login"] = _ =>
{
{
@ -110,6 +111,7 @@ namespace PlexRequests.UI.Modules
Get["/changepassword"] = _ => ChangePassword();
Post["/changepassword"] = _ => ChangePasswordPost();
}
private ICustomUserMapper UserMapper { get; }
private Negotiator ChangePassword()
{

View file

@ -13,13 +13,15 @@ namespace PlexRequests.UI.Modules
{
public class UserManagementModule : BaseModule
{
public UserManagementModule(ISettingsService<PlexRequestSettings> pr) : base("usermanagement",pr)
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m) : base("usermanagement",pr)
{
this.RequiresClaims(UserClaims.Admin);
Get["/"] = x => Load();
Get["/users"] = x => LoadUsers();
UserMapper = m;
}
private ICustomUserMapper UserMapper { get; }
private Negotiator Load()
{