Done most on #59

This commit is contained in:
tidusjar 2016-03-23 13:43:27 +00:00
commit c7ac8a7d99
32 changed files with 345 additions and 2283 deletions

View file

@ -47,6 +47,7 @@ using PlexRequests.Services;
using PlexRequests.Services.Interfaces;
using PlexRequests.Services.Notification;
using PlexRequests.Store;
using PlexRequests.Store.Models;
using PlexRequests.Store.Repository;
using PlexRequests.UI.Jobs;
using TaskFactory = FluentScheduler.TaskFactory;
@ -77,6 +78,7 @@ namespace PlexRequests.UI
// Repo's
container.Register<IRepository<RequestedModel>, GenericRepository<RequestedModel>>();
container.Register<IRepository<LogEntity>, GenericRepository<LogEntity>>();
container.Register<IRequestService, JsonRequestService>();
container.Register<ISettingsRepository, SettingsJsonRepository>();

File diff suppressed because one or more lines are too long

View file

@ -26,6 +26,7 @@
#endregion
using System.Dynamic;
using System.Linq;
using System.Web.UI.WebControls;
using MarkdownSharp;
@ -44,6 +45,8 @@ using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
using PlexRequests.Services.Notification;
using PlexRequests.Store.Models;
using PlexRequests.Store.Repository;
using PlexRequests.UI.Helpers;
using PlexRequests.UI.Models;
@ -63,6 +66,7 @@ namespace PlexRequests.UI.Modules
private ISonarrApi SonarrApi { get; }
private PushbulletApi PushbulletApi { get; }
private ICouchPotatoApi CpApi { get; }
private IRepository<LogEntity> LogsRepo { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public AdminModule(ISettingsService<PlexRequestSettings> rpService,
@ -76,7 +80,8 @@ namespace PlexRequests.UI.Modules
IPlexApi plexApi,
ISettingsService<PushbulletNotificationSettings> pbSettings,
PushbulletApi pbApi,
ICouchPotatoApi cpApi) : base("admin")
ICouchPotatoApi cpApi,
IRepository<LogEntity> logsRepo) : base("admin")
{
RpService = rpService;
CpService = cpService;
@ -90,6 +95,7 @@ namespace PlexRequests.UI.Modules
PushbulletApi = pbApi;
CpApi = cpApi;
SickRageService = sickrage;
LogsRepo = logsRepo;
#if !DEBUG
this.RequiresAuthentication();
@ -126,6 +132,10 @@ namespace PlexRequests.UI.Modules
Get["/pushbulletnotification"] = _ => PushbulletNotifications();
Post["/pushbulletnotification"] = _ => SavePushbulletNotifications();
Get["/logs"] = _ => Logs();
Get["/loglevel"] = _ => GetLogLevels();
Post["/loglevel"] = _ => UpdateLogLevels(Request.Form.level);
}
private Negotiator Authentication()
@ -246,8 +256,8 @@ namespace PlexRequests.UI.Modules
}
var result = CpService.SaveSettings(couchPotatoSettings);
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for CouchPotato!" }
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for CouchPotato!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
@ -422,5 +432,24 @@ namespace PlexRequests.UI.Modules
return Response.AsJson(profiles);
}
private Negotiator Logs()
{
var allLogs = LogsRepo.GetAll().OrderByDescending(x => x.Id).Take(20);
return View["Logs", allLogs];
}
private Response GetLogLevels()
{
var levels = LogManager.Configuration.LoggingRules.FirstOrDefault(x => x.NameMatches("database"));
return Response.AsJson(levels.Levels);
}
private Response UpdateLogLevels(int level)
{
var newLevel = LogLevel.FromOrdinal(level);
LoggingHelper.ReconfigureLogLevel(newLevel);
return Response.AsJson(new JsonResponseModel { Result = true, Message = $"The new log level is now {newLevel}"});
}
}
}

View file

@ -169,18 +169,14 @@ namespace PlexRequests.UI.Modules
private Response RequestMovieAndUpdateStatus(RequestedModel request)
{
if (!Context.CurrentUser.IsAuthenticated())
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." });
}
var cpSettings = CpService.GetSettings();
var cp = new CouchPotatoApi();
Log.Info("Adding movie to CP : {0}", request.Title);
Log.Info("Adding movie to CouchPotato : {0}", request.Title);
if (!cpSettings.Enabled)
{
// Approve it
request.Approved = true;
Log.Warn("We approved movie: {0} but could not add it to CouchPotato because it has not been setup", request.Title);
// Update the record
var inserted = Service.UpdateRequest(request);
@ -226,6 +222,11 @@ namespace PlexRequests.UI.Modules
/// <returns></returns>
private Response ApproveAll()
{
if (!Context.CurrentUser.IsAuthenticated())
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." });
}
var requests = Service.GetAll().Where(x => x.Approved == false);
var requestedModels = requests as RequestedModel[] ?? requests.ToArray();
if (!requestedModels.Any())

View file

@ -51,7 +51,7 @@ namespace PlexRequests.UI.Modules
model.AdminExists = adminCreated;
return View["Login/Index", model];
}
};
Get["/logout"] = x => this.LogoutAndRedirect("~/");
@ -76,7 +76,8 @@ namespace PlexRequests.UI.Modules
return this.LoginAndRedirect(userId.Value, expiry);
};
Get["/register"] = x => {
Get["/register"] = x =>
{
{
dynamic model = new ExpandoObject();
model.Errored = Request.Query.error.HasValue;
@ -87,13 +88,13 @@ namespace PlexRequests.UI.Modules
Post["/register"] = x =>
{
var username = (string) Request.Form.Username;
var username = (string)Request.Form.Username;
var exists = UserMapper.DoUsersExist();
if (exists)
{
return Context.GetRedirect("~/register?error=true&username=" + username);
return Context.GetRedirect("~/register?error=true");
}
var userId = UserMapper.CreateUser(username, Request.Form.Password);
var userId = UserMapper.CreateUser(username, Request.Form.Password, new[] { "Admin" });
Session[SessionKeys.UsernameKey] = username;
return this.LoginAndRedirect((Guid)userId);
};
@ -116,7 +117,7 @@ namespace PlexRequests.UI.Modules
var newPasswordAgain = Request.Form.NewPasswordAgain;
if (!newPassword.Equals(newPasswordAgain))
{
}
var result = UserMapper.UpdateUser(username, oldPass, newPassword);

View file

@ -13,7 +13,7 @@
layout="${date} ${logger} ${level}: ${message}" />
<target name="Database" xsi:type="Database"
<!--<target name="Database" xsi:type="Database"
dbProvider="Mono.Data.Sqlite.SqliteConnection, Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" keepConnection="false"
connectionString="Data Source=PlexRequests.sqlite, version=3"
commandText="INSERT into Logs(Date, Level, Logger, Callsite, Message, Exception)
@ -24,11 +24,11 @@
<parameter name="@Callsite" layout="${callsite:filename=true}"/>
<parameter name="@Message" layout="${message}"/>
<parameter name="@Exception" layout="${exception:format=tostring}"/>
</target>
</target>-->
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="filelog" />
<logger name="*" minlevel="Trace" writeTo="Database" />
<!--<logger name="*" minlevel="Trace" writeTo="Database" />-->
</rules>
</nlog>

View file

@ -97,6 +97,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Assemblies\Mono.Data.Sqlite.dll</HintPath>
</Reference>
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Nancy, Version=1.4.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Nancy.1.4.3\lib\net40\Nancy.dll</HintPath>
<Private>True</Private>
@ -335,6 +339,9 @@
<Content Include="Views\Login\ChangePassword.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Views\Admin\Logs.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="Web.Debug.config">
<DependentUpon>web.config</DependentUpon>
</None>

View file

@ -30,6 +30,8 @@ using System.Data;
using Microsoft.Owin.Hosting;
using Mono.Data.Sqlite;
using Mono.Unix;
using Mono.Unix.Native;
using NLog;
using NLog.Config;
@ -55,7 +57,7 @@ namespace PlexRequests.UI
int portResult;
if (!int.TryParse(args[0], out portResult))
{
Console.WriteLine("Incorrect Port format. Press Any Key to shut down.");
Console.WriteLine("Incorrect Port format. Press any key.");
Console.ReadLine();
Environment.Exit(1);
}
@ -65,7 +67,8 @@ namespace PlexRequests.UI
WriteOutVersion();
var s = new Setup();
s.SetupDb();
var cn = s.SetupDb();
ConfigureTargets(cn);
if (port == -1)
port = GetStartupPort();
@ -76,18 +79,29 @@ namespace PlexRequests.UI
};
try
{
using (WebApp.Start<Startup>(options))
{
Console.WriteLine($"Request Plex is running on the following: http://+:{port}/");
using (WebApp.Start<Startup>(options))
{
Console.WriteLine($"Request Plex is running on the following port: {port}");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
if (Type.GetType("Mono.Runtime") != null)
{
Log.Info("We are on Mono!");
// on mono, processes will usually run as daemons - this allows you to listen
// for termination signals (ctrl+c, shutdown, etc) and finalize correctly
UnixSignal.WaitAny(
new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM), new UnixSignal(Signum.SIGQUIT), new UnixSignal(Signum.SIGHUP) });
}
else
{
Log.Info("This is not Mono");
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}
}
catch (Exception e)
{
var a = e.Message;
Log.Fatal(e);
throw;
}
}
@ -116,59 +130,7 @@ namespace PlexRequests.UI
private static void ConfigureTargets(string connectionString)
{
LogManager.ThrowExceptions = true;
// Step 1. Create configuration object
var config = new LoggingConfiguration();
// Step 2. Create targets and add them to the configuration
var databaseTarget = new DatabaseTarget
{
CommandType = CommandType.Text,
ConnectionString = connectionString,
DBProvider = "Mono.Data.Sqlite.SqliteConnection, Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756",
Name = "database"
};
var messageParam = new DatabaseParameterInfo { Name = "@Message", Layout = "${message}" };
var callsiteParam = new DatabaseParameterInfo { Name = "@Callsite", Layout = "${callsite}" };
var levelParam = new DatabaseParameterInfo { Name = "@Level", Layout = "${level}" };
var usernameParam = new DatabaseParameterInfo { Name = "@Username", Layout = "${identity}" };
var dateParam = new DatabaseParameterInfo { Name = "@Date", Layout = "${date}" };
var loggerParam = new DatabaseParameterInfo { Name = "@Logger", Layout = "${logger}" };
var exceptionParam = new DatabaseParameterInfo { Name = "@Exception", Layout = "${exception:tostring}" };
databaseTarget.Parameters.Add(messageParam);
databaseTarget.Parameters.Add(callsiteParam);
databaseTarget.Parameters.Add(levelParam);
databaseTarget.Parameters.Add(usernameParam);
databaseTarget.Parameters.Add(dateParam);
databaseTarget.Parameters.Add(loggerParam);
databaseTarget.Parameters.Add(exceptionParam);
databaseTarget.CommandText = "INSERT INTO Log (Username,Date,Level,Logger, Message, Callsite, Exception) VALUES(@Username,@Date,@Level,@Logger, @Message, @Callsite, @Exception);";
config.AddTarget("database", databaseTarget);
// Step 4. Define rules
var rule1 = new LoggingRule("*", LogLevel.Error, databaseTarget);
config.LoggingRules.Add(rule1);
try
{
// Step 5. Activate the configuration
LogManager.Configuration = config;
}
catch (Exception)
{
throw;
}
// Example usage
Logger logger = LogManager.GetLogger("Example");
logger.Error("error log message");
LoggingHelper.ConfigureLogging(connectionString);
}
}
}

View file

@ -0,0 +1,118 @@
@Html.Partial("_Sidebar")
<div class="col-sm-8 col-sm-push-1">
<fieldset>
<legend>Logs</legend>
<form method="post" id="mainForm" action="/admin/loglevel">
<div class="form-group">
<label for="logLevel" class="control-label">Log Level</label>
<div id="logLevel">
<select class="form-control" id="selected">
<option id="Trace" value="0">Trace</option>
<option id="Debug" value="1">Debug</option>
<option id="Info" value="2">Info</option>
<option id="Warn" value="3">Warn</option>
<option id="Error" value="4">Error</option>
<option id="Fatal" value="5">Fatal</option>
</select>
</div>
</div>
<div class="form-group">
<div>
<button id="save" type="submit" class="btn btn-primary-outline ">Submit</button>
</div>
</div>
</form>
<table class="table table-striped table-hover table-responsive">
<tr>
<th>Message</th>
<th>Logger</th>
<th>Exception</th>
<th>Callsite</th>
<th>Log Level</th>
<th>Date</th>
</tr>
@foreach (var m in Model)
{
<tr>
<td>
@m.Message
</td>
<td>
@m.Logger
</td>
<td>
@m.Exception
</td>
<td>
@m.Callsite
</td>
<td>
@m.Level
</td>
<td>
@m.Date
</td>
</tr>
}
</table>
</fieldset>
</div>
<script>
$(function () {
$.ajax({
type: "get",
url: "/admin/loglevel",
dataType: "json",
success: function (response) {
$("#select > option").each(function (level) {
if (response[0] == level.value) {
$('#' + level.target.id).prop("selected", "selected");
}
});
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
$('#save').click(function (e) {
e.preventDefault();
var logLevel = $("#logLevel option:selected").val();
var $form = $("#mainForm");
var data = "level=" + logLevel;
$.ajax({
type: $form.prop("method"),
data: data,
url: $form.prop("action"),
dataType: "json",
success: function (response) {
if (response.result === true) {
generateNotify(response.message, "success");
} else {
generateNotify(response.message, "warning");
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
});
</script>

View file

@ -70,7 +70,14 @@
{
<a class="list-group-item" href="/admin/pushbulletnotification">Pushbullet Notifications</a>
}
@if (Context.Request.Path == "/admin/logs")
{
<a class="list-group-item active" href="/admin/logs">Logs</a>
}
else
{
<a class="list-group-item" href="/admin/logs">Logs</a>
}
@if (Context.Request.Path == "/admin/status")
{
<a class="list-group-item active" href="/admin/status">Status</a>

View file

@ -57,26 +57,26 @@
{
<li><a href="/requests">Requests</a></li>
}
@if (Context.CurrentUser.IsAuthenticated())
{
if (Context.Request.Path == "/admin")
{
<li class="active"><a href="/admin">Admin</a></li>
}
else
{
<li><a href="/admin">Admin</a></li>
}
}
</ul>
<ul class="nav navbar-nav navbar-right">
@if (!Context.CurrentUser.IsAuthenticated())
{
<li><a href="/login">Admin</a></li>
}
else
{
<li><a href="/logout">Admin Logout</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Admin <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/admin">Settings</a></li>
<li><a href="#">User Management</a></li>
<li class="divider"></li>
<li><a href="#">Logout</a></li>
</ul>
</li>
}
@if (Context.Request.Session[SessionKeys.UsernameKey] != null)
{

View file

@ -6,5 +6,9 @@
{
"outputFile": "Content/pace.css",
"inputFile": "Content/pace.scss"
},
{
"outputFile": "Content/requests.es5.js",
"inputFile": "Content/requests.js"
}
]

View file

@ -10,6 +10,7 @@
<package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net452" />
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.0" targetFramework="net46" />
<package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net452" />
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net46" />
<package id="Nancy" version="1.4.3" targetFramework="net452" />
<package id="Nancy.Authentication.Basic" version="1.4.1" targetFramework="net452" />
<package id="Nancy.Authentication.Forms" version="1.4.1" targetFramework="net452" />