Add project files.

This commit is contained in:
2017-02-02 01:31:36 +02:00
parent f6b08f01f2
commit e403fd51c4
275 changed files with 30026 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<appSettings>
<add key="webApiUrl" value="http://localhost:5000" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.104.0" newVersion="1.0.104.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -0,0 +1,198 @@
using Hangfire;
using Hangfire.SQLite;
using LanBackupAgent.WebApi;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Timers;
using TinyMessenger;
using LanBackupAgent.Models;
using LanBackupAgent.Message;
namespace LanBackupAgent.Utils
{
public class BackgroundRefreshController : IDisposable
{
private ILogger logger;
private ITinyMessengerHub messenger;
private WebApiService webapi;
public const int WEBAPI_REFRESH_BACKUPS_TIME = 120000; //miliseconds for backups refresh from webapi
#region WebApi
private System.Timers.Timer timerRefreshFromWebApi = new System.Timers.Timer();
#endregion
#region Hangfire
private BackgroundJobServer hangfireServer;
#endregion
public BackgroundRefreshController(
ILogger mlogger,
ITinyMessengerHub mmessenger,
WebApiService mwebapi
)
{
this.logger = mlogger;
this.messenger = mmessenger;
this.webapi = mwebapi;
this.messenger.Subscribe<StopMessage>(Stop);
logger.Trace("BackgroundRefreshController instance initialized");
}
internal void Start()
{
ConfigureHangfire();
ConfigureRefresWebApiTimer();
}
private void ConfigureHangfire()
{
string file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "local_backups.db3");
string sqlconn = $"Data Source={file};Version=3;";
GlobalConfiguration.Configuration.UseSQLiteStorage(sqlconn);
var options = new BackgroundJobServerOptions
{
// This is the default value
SchedulePollingInterval = TimeSpan.FromSeconds(5),
WorkerCount = 1// FORCE ONE BACKUP at one time - so they will be performed serial one by one
};
hangfireServer = new BackgroundJobServer(options);
JobStorage.Current?.GetMonitoringApi()?.PurgeJobs();
TimerRefreshFromWebApi_Elapsed(null, null);
}
private void ConfigureRefresWebApiTimer()
{
//start retry timer for WebAPi refresh
timerRefreshFromWebApi = new System.Timers.Timer();
timerRefreshFromWebApi.Interval = WEBAPI_REFRESH_BACKUPS_TIME;
timerRefreshFromWebApi.Elapsed += TimerRefreshFromWebApi_Elapsed; ;
timerRefreshFromWebApi.Start();
logger.Trace("WebApi timer configured");
}
private async void TimerRefreshFromWebApi_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
logger.Trace(string.Format("WebApi refresh at {0}", DateTime.Now.ToString("o")));
List<string> activeJobs = new List<string>();
var result = await webapi.LoadBackupConfigurations();
if (result != null)
{
foreach (var item in result)
{
try
{
string jobId = $"{item.Id}";// _{Convert.ToBase64String(item.RowVersion)}";
if (item.IsActive.Value)
{
//RecurringJob.
var recJob = JobStorage.Current.GetMonitoringApi().JobDetails(jobId);
//RecurringJob.AddOrUpdate(jobId, () => LanCopyFileJob(item), item.Crontab);
if (recJob == null)
{
RecurringJob.AddOrUpdate(jobId, () => DoCopyJob(item), item.Crontab);
}
activeJobs.Add(jobId);
RecurringJob.Trigger(jobId);
}
else
{
//stopping inactive
var recJob = JobStorage.Current.GetMonitoringApi().JobDetails(jobId);
if (recJob != null)
{
RecurringJob.RemoveIfExists(jobId);
}
}
}
catch (Exception ex)
{
logger.Error($"Reccuring jobs refresh failed: {ex}");
//report error to webAPI
webapi.LogActivity(item.Id, $"Reccuring jobs refresh failed -({item.Id})- see Err", ex.Message, "ERR");
}
}
}
//TODO - purge ofphan jobs
//JobStorage.Current.GetMonitoringApi().PurgeOrfanJobsExceptList(activeJobs);
}
catch (Exception ex)
{
logger.Error($"ERR WebApi refresh: {ex}");
//report error to webAPI
webapi.LogActivity(string.Empty, "Reccuring jobs refresh final failed - see Err", ex.Message, "ERR");
}
}
//MUST BE STATIC so it can be called from Hangfire
public static string DoCopyJob(BackupConfiguration item)
{
string result = string.Empty;
try
{
result = DI.Container.GetInstance<LanCopyController>().StartLanCopyFileJob(item);
}
catch (Exception ex)
{
var logger = DI.Container.GetInstance<ILogger>();
logger.Error(ex, "DoCopyJoberror:");
}
return result;
}
public void Stop(StopMessage msg)
{
//cleanup disposable resources
if (timerRefreshFromWebApi != null)
{
timerRefreshFromWebApi.Stop();
timerRefreshFromWebApi.Dispose();
}
if (hangfireServer != null)
{
hangfireServer.SendStop();
hangfireServer.Dispose();
}
logger.Trace("LanCopyController Stopped");
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (timerRefreshFromWebApi != null)
{
timerRefreshFromWebApi.Dispose();
}
if (hangfireServer != null)
{
hangfireServer.Dispose();
}
}
}
}
}
@@ -0,0 +1,437 @@
using System;
using LanBackupAgent.Models;
using NLog;
using LanBackupAgent.WebApi;
using TinyMessenger;
using System.Collections.Concurrent;
using System.Threading;
using System.IO;
using System.Security.Principal;
using SimpleImpersonation;
using LanBackupAgent.Message;
using LanBackup.Models;
using System.Linq;
using LanBackupAgent.Controllers;
namespace LanBackupAgent.Utils
{
public class LanCopyController
{
private ILogger logger;
private ITinyMessengerHub messenger;
private WebApiService webapi;
private Exception externalError;
private Network networkUtil;
/// <summary>
/// used to signal a forced exception
/// </summary>
private bool forceExceptionalStop;
/// <summary>
/// used to queue and sync copy jobs between threads
/// </summary>
ConcurrentQueue<CopyOperation> myCollection;
/// <summary>
/// maximum items in the copy queue - must test to find the best value
/// </summary>
const int queueTHRESHOLD = 30;
/// <summary>
/// buffer size for copy operations - must test to find the best value
/// </summary>
const int bufferSize = 5*65536;
private long dirCount = 0; long fileCount = 0;
public LanCopyController(
ILogger mlogger,
ITinyMessengerHub mmessenger,
WebApiService mwebapi,
Network networkUtil
)
{
this.logger = mlogger;
this.messenger = mmessenger;
this.webapi = mwebapi;
this.networkUtil = networkUtil;
this.messenger.Subscribe<StopMessage>(Stop);
logger.Trace("LanCopyController instance initialized");
}
public string StartLanCopyFileJob(BackupConfiguration item)
{
string jobId = $"{item.Id}";// _{Convert.ToBase64String(item.RowVersion)}";
Exception localEx = null;
try
{
var msg = $"({item.Id}) - START";
logger.Debug(msg);
webapi.LogActivity(item.Id, msg, string.Empty, "OK");
ReportAgentStatus(StatusType.Starting, $"Starting copy operation - ({item.Id})", 0, item.Id);
if (item.SrcUser.IndexOf(@"@") < 0)
throw new ArgumentException("Source user must be in format john@computer");
if (item.DestUser.IndexOf(@"@") < 0)
throw new ArgumentException("Destination user must be in format john@computer");
string domainSrc = item.SrcUser.Substring(item.SrcUser.IndexOf(@"@") + 1);
string usernameSrc = item.SrcUser.Substring(0, item.SrcUser.IndexOf(@"@"));
string domainDest = item.DestUser.Substring(item.DestUser.IndexOf(@"@") + 1);
string usernameDest = item.DestUser.Substring(0, item.DestUser.IndexOf(@"@"));
Exception outEx;
if (!CopyFolderAndFilesWithImpersonation(item.Id, item.SrcFolder, domainSrc, usernameSrc, item.SrcPass,
item.DestLanFolder, domainDest, usernameDest, item.DestPass, out outEx))
{
if (outEx != null)
{
localEx = outEx;
logger.Error($"CopyFolderAndFilesWithImpersonation ERR : {outEx}");
ReportAgentStatus(StatusType.Error, "Error... " + outEx.Message, 100);
}
}
else
{
ReportAgentStatus(StatusType.Idle, $"Finished - ({item.Id})...", 100);
}
}
catch (Exception ex)
{
localEx = ex;
logger.Error($"Background job ERR : {ex}");
ReportAgentStatus(StatusType.Error, $"Error - ({item.Id}) - " + ex.Message, 0);
}
finally
{
var msg = $"({item.Id}) - END";
logger.Debug(msg);
webapi.LogActivity(item.Id, msg, localEx != null ? localEx.Message : string.Empty, localEx != null ? "ERR" : "OK");
}
return jobId;
}
private void ReportAgentStatus(StatusType type, string desc, int percent, string configId = "")
{
var obj = new StatusReport("", new StatusReportInfo()
{
IP = networkUtil.GetLocalIPAddress(),
ConfigurationId = configId,
StatusType = type,
StatusDateTime = DateTime.UtcNow,
StatusPercent = percent,
StatusDescription = desc
});
ThreadPool.QueueUserWorkItem((msg) => {
this.messenger.Publish(msg as StatusReport);
}, obj);
}
/// <summary>
/// Copy the source folder content into a destination folder
/// </summary>
/// <param name="srcPath">source folder</param>
/// <param name="destPath">destination folder</param>
/// <returns>true if success</returns>
private bool CopyFolderAndFilesWithImpersonation(string configID, string srcPath, string domainSrc, string userSrc, string passSrc,
string destPath, string domainDest, string userDest, string passDest, out Exception outEx)
{
outEx = null;
myCollection = new ConcurrentQueue<CopyOperation>();
byte[] buffer = new byte[bufferSize];
bool finished = false;
Exception srcError = null;
Exception destError = null;
Thread thSource = new Thread(() =>
{
try
{
//FileLogging.Log($"begin thSrc.", LogLevel.Info);
using (Impersonation.LogonUser(domainSrc, userSrc, passSrc, LogonType.Network))//LogonType.Interactive
{
WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
//FileLogging.Log($"impersonated thSrc. {wid_current.Name}", LogLevel.Info);
//scan all of the directories
var lstDirectories = Directory.GetDirectories(srcPath, "*", SearchOption.AllDirectories);
dirCount = lstDirectories.LongCount();
foreach (string dirPath in lstDirectories)
{
CopyOperation coFolder = new CopyOperation
{
Operation = OperationType.WriteFolder,
Argument = dirPath.Replace(srcPath, string.Empty)
};
FillQueue(myCollection, queueTHRESHOLD, destError, coFolder);
if (forceExceptionalStop)
return;
//FileLogging.Log($"q-d: {coFolder.Argument}", LogLevel.Info);
}
//scan all files
var lstFiles = Directory.GetFiles(srcPath, "*.*", SearchOption.AllDirectories);
fileCount = lstFiles.LongCount();
foreach (string newPath in lstFiles)
{
using (FileStream fs = File.Open(newPath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
{
int readB;
long offset = 0;
while ((readB = fs.Read(buffer, 0, bufferSize)) > 0)
{
CopyOperation coFile = new CopyOperation
{
Operation = OperationType.WriteFile,
Argument = newPath.Replace(srcPath, string.Empty),
Offset = offset,
Content = buffer.SubArray(0, readB)
};
FillQueue(myCollection, queueTHRESHOLD, destError, coFile);
if (forceExceptionalStop)
return;
//FileLogging.Log($"q-f: {coFile.Argument} - {coFile.Offset}", LogLevel.Info);
offset += readB;
}
}
}
//YEY!
finished = true;
//wic.Undo();
}
}
catch (Exception err)
{
srcError = err;
forceExceptionalStop = true;
finished = true;
}
});
Thread thDest = new Thread(() =>
{
try
{
//FileLogging.Log($"begin thDest.", LogLevel.Info);
Thread.Sleep(200);
long dirIndex = 0, fileIndex = 0;
string lastFile = string.Empty;
DateTime lastSent = DateTime.MinValue;
int copyPercent;
using (Impersonation.LogonUser(domainDest, userDest, passDest, LogonType.NewCredentials))//LogonType.NewCredentials
{
WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
//FileLogging.Log($"impersonated thDest. {wid_current.Name}", LogLevel.Info);
while (!finished || myCollection.Count > 0)
{
while (myCollection.Count == 0 && !forceExceptionalStop)
{
Thread.Sleep(100);
}
if (forceExceptionalStop)
return;
CopyOperation item = null;
if (myCollection.TryDequeue(out item))
{
switch (item.Operation)
{
case OperationType.WriteFolder:
string newFolder = UncCombine(destPath, item.Argument);
Directory.CreateDirectory(newFolder);
dirIndex++;
break;
case OperationType.WriteFile:
string destFile = UncCombine(destPath, item.Argument);
using (var fs = ((item.Offset == 0) && File.Exists(destFile)) ? File.Create(destFile) : File.OpenWrite(destFile))
{
fs.Seek(item.Offset, SeekOrigin.Begin);
fs.Write(item.Content, 0, item.Content.Length);
}
if (destFile != lastFile)
{
fileIndex++;
lastFile = destFile;
}
break;
default:
break;
}
//update report status
DateTime now = DateTime.UtcNow;
if ( now > lastSent)
{
copyPercent = Convert.ToInt32( 20 * (dirCount > 0 ? (double)dirIndex / dirCount : 1) + 80 * (fileCount > 0 ? (double)fileIndex / fileCount : 1) );
lastSent = now + TimeSpan.FromMilliseconds(SignalRController.SIGNALR_REFRESH_INTERVAL);
ReportAgentStatus(item.Operation == OperationType.WriteFolder ? StatusType.CopyFolders : StatusType.CopyFiles,
item.Operation == OperationType.WriteFolder ? $"Copy folders in progress {dirIndex}/{dirCount} ..." : $"Copy files in progress {fileIndex}/{fileCount} ..."
, copyPercent, configID);
}
}
else
{
throw new ArgumentException("Could not extract item from queue");
}
}
}
}
catch (Exception err)
{
destError = err;
forceExceptionalStop = true;
}
});
//clear exception
forceExceptionalStop = false;
thDest.Start();
thSource.Start();
//wait to complete or fail
thSource.Join();
thDest.Join();
myCollection = new ConcurrentQueue<CopyOperation>();
if (srcError != null)
{
outEx = srcError;
logger.Error($"srcErr: {srcError}");
return false;
}
if (destError != null)
{
outEx = destError;
logger.Error($"destErr: {destError}");
return false;
}
if (externalError != null)
{
outEx = externalError;
logger.Debug($"externalError: {destError}");
return false;
}
logger.Error($"LAN Copy completed!");
return true;
}
/// <summary>
/// helper function for adding items in the copy queue
/// </summary>
/// <param name="myCollection"></param>
/// <param name="queueTHRESHOLD"></param>
/// <param name="destError"></param>
/// <param name="coFolder"></param>
private void FillQueue(ConcurrentQueue<CopyOperation> myCollection, int queueTHRESHOLD, Exception destError, CopyOperation coFolder)
{
if (destError != null)
throw new ArgumentException("Thread Copy Destination has failed", destError);
while (myCollection.Count > queueTHRESHOLD)
{
if (forceExceptionalStop)
return;
Thread.Sleep(100);
}
myCollection.Enqueue(coFolder);
}
/// <summary>
/// Helper function to combine Unc paths
/// </summary>
/// <param name="startPath"></param>
/// <param name="endPath"></param>
/// <returns></returns>
private string UncCombine(string startPath, string endPath)
{
while (startPath.EndsWith(@"\"))
startPath = startPath.Substring(0, startPath.Length - 1);
while (endPath.StartsWith(@"\"))
endPath = endPath.Substring(1);
return startPath + @"\" + endPath;
}
private void Stop(StopMessage obj)
{
//signal stop
externalError = new ApplicationException("Stop processing invoked by the service");
forceExceptionalStop = true;
//cleanup disposable resources
}
}
/// <summary>
/// helper class used in quing and sync copy operation between threads
/// </summary>
internal class CopyOperation
{
/// <summary>
/// Operation type - can be either Write Folder or Write File
/// </summary>
public OperationType Operation { get; internal set; }
/// <summary>
/// partial folder or file path
/// </summary>
public string Argument { get; internal set; }
public byte[] Content { get; internal set; }
public long Offset { get; internal set; }
}
/// <summary>
/// helper enumeration for copy operation type
/// </summary>
internal enum OperationType
{
WriteFolder,
WriteFile
}
}
@@ -0,0 +1,293 @@
using LanBackup.Models;
using LanBackupAgent.Message;
using LanBackupAgent.Utils;
using Microsoft.AspNet.SignalR.Client;
using Newtonsoft.Json;
using NLog;
using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using TinyMessenger;
namespace LanBackupAgent.Controllers
{
public class SignalRController : IDisposable
{
//TODO - move these in config file
const string SIGNALR_HUBNAME = "backupslan";
public const int SIGNALR_REFRESH_INTERVAL = 1500;
public const int SIGNALR_REFRESH_INTERVAL_IDLE = 10000; //used for retry and ping (when idle)
private ILogger logger;
private ITinyMessengerHub messenger;
private string webapiUrlBase;
private Network networkUtil;
private bool isWorkInProgress;
#region SignalR Hub
HubConnection connSignalR;
private DateTime connSignalrClosedOn;
IHubProxy hubSignalr;
private System.Timers.Timer timerRetryPingSignalR = new System.Timers.Timer();
#endregion
public SignalRController(
string mwebapiUrlBase,
ILogger mlogger,
ITinyMessengerHub mmessenger,
Network networkUtil
)
{
this.webapiUrlBase = mwebapiUrlBase;
this.logger = mlogger;
this.messenger = mmessenger;
this.networkUtil = networkUtil;
this.messenger.Subscribe<StopMessage>(DoStop);
this.messenger.Subscribe<StatusReport>(DoStatus);
logger.Trace("SignalRController instance initialized");
}
public async Task<bool> Start()
{
logger.Trace("SignalRController Starting");
await ConfigureSignalR();
ConfigureTimers();
logger.Trace("SignalRController Started");
return true;
}
private async Task ConfigureSignalR()
{
string webApiUrl = ConfigurationManager.AppSettings["webApiUrl"];
string hubAddress = webApiUrl + "/signalr";
logger.Trace($"Starting SignalR Client on: {hubAddress}");
connSignalR = new HubConnection(hubAddress, useDefaultUrl: false);
connSignalR.Error += (err) =>
{
if (err is WebSocketException)
{
return;
}
logger.Error($"Err: {err}");
};
connSignalR.Closed += () =>
{
logger.Info($"Connection closed.");
connSignalrClosedOn = DateTime.Now;
};
connSignalR.ConnectionSlow += () =>
{
//TODO - log the issue
};
connSignalR.Reconnected += () =>
{
//TODO - check for overdue/due backups on the server
};
hubSignalr = connSignalR.CreateHubProxy(SIGNALR_HUBNAME);
hubSignalr.On<string>("controlAgent", data => //Waiting control signal from server signalr
{
logger.Trace($"controlAgent data: {data}");
//scheduler
ThreadPool.QueueUserWorkItem((par) =>
{
try
{
DateTime recDate = (DateTime)par;
//TODO - something to do by the server command
}
catch (Exception ex)
{
logger.Error($"ERR scheduler: {ex}");
}
}, DateTime.Now);
});
await TryStartSignalR();
}
#region Timer for retry
private void ConfigureTimers()
{
//start retry timer for SignalR
timerRetryPingSignalR.Interval = SIGNALR_REFRESH_INTERVAL_IDLE;
timerRetryPingSignalR.Elapsed += TimerRetryPingSignalR_Elapsed;
timerRetryPingSignalR.Start();
logger.Trace("Timers configured");
}
private async void TimerRetryPingSignalR_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
if (connSignalR != null)
{
//retry
if (connSignalR.State == ConnectionState.Disconnected)
{
if((DateTime.Now - connSignalrClosedOn).TotalSeconds > 5) //retry after 5 seconds
await TryStartSignalR();
}
else if (connSignalR.State == ConnectionState.Connected)
{
//send ping signal when IDLE
if(!isWorkInProgress)
{
// IDLE ping signalr - i'm online!
ReadyIdlePing();
}
}
}
}
catch (Exception ex)
{
logger.Error($"ERR TimerRetrySignalR: {ex}");
}
}
/// <summary>
/// signal thet agent is online
/// </summary>
private void ReadyIdlePing()
{
this.messenger.Publish(new StatusReport("", new StatusReportInfo()
{
IP = networkUtil.GetLocalIPAddress(),
ConfigurationId = string.Empty,
StatusType = StatusType.Idle,
StatusDateTime = DateTime.UtcNow,
StatusPercent = 0,
StatusDescription = $"Ready ..."
}));
}
public async Task TryStartSignalR()
{
try
{
logger.Info($"Trying ro connect ...");
await connSignalR.Start();
// hello to signalr - i'm online!
ReadyIdlePing();
}
catch (HttpRequestException hex)
{
if (hex.InnerException is WebException)
{
WebException wex = hex.InnerException as WebException;
if (wex.Status == WebExceptionStatus.ConnectFailure)
{
//ignore this err
}
else
{
logger.Error($"ERR WebException HResult: {wex.HResult}");
logger.Error($"ERR WebException Status: {wex.Status}");
logger.Error($"ERR WebException Message: {wex.Message}");
}
}
}
catch (Exception ex)
{
logger.Error($"ERR Start SignalR: {ex}");
}
}
#endregion Timer for retry
#region SignalR actions
private void DoStop(StopMessage obj)
{
//cleanup disposable resources
if (timerRetryPingSignalR != null)
{
timerRetryPingSignalR.Stop();
timerRetryPingSignalR.Dispose();
}
if (connSignalR != null)
{
connSignalR.Stop();
connSignalR.Dispose();
}
logger.Trace("SignalRController Stopped");
}
private void DoStatus(StatusReport obj)
{
try
{
this.isWorkInProgress = (obj.Info.StatusType != StatusType.Idle);
if (connSignalR != null)
{
logger.Warn($"DoStatus {JsonConvert.SerializeObject(obj)}");
if (connSignalR != null && connSignalR.State == ConnectionState.Connected)
{
hubSignalr.Invoke("StatusReport", obj.Info);
}
else
{
//connection not open
}
}else
{
logger.Warn($"Warn SignalR DoStatus: connection null");
}
}
catch (Exception ex)
{
logger.Error($"ERR SignalR DoStatus: {ex}");
}
}
#endregion SignalR actions
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (timerRetryPingSignalR != null)
{
timerRetryPingSignalR.Dispose();
}
if (connSignalR != null)
{
connSignalR.Dispose();
}
}
}
#endregion IDisposable
}
}
Binary file not shown.
+202
View File
@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{CB7EE867-93E8-43E3-9EEE-9068AED1DE6C}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LanBackupAgent</RootNamespace>
<AssemblyName>LanBackupAgent</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>app_icon.png.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="ColoredConsole, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\ColoredConsole.0.5.0\lib\net45\ColoredConsole.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Dapper, Version=1.40.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Dapper.1.42\lib\net45\Dapper.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Hangfire.Core, Version=1.6.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Hangfire.Core.1.6.8\lib\net45\Hangfire.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Hangfire.SQLite, Version=1.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Hangfire.SQLite.1.1.1.0\lib\net45\Hangfire.SQLite.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Client, Version=2.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.AspNet.SignalR.Client.2.2.1\lib\net45\Microsoft.AspNet.SignalR.Client.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.2.3.4\lib\net45\Microsoft.Rest.ClientRuntime.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\..\packages\NLog.4.4.1\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimpleImpersonation, Version=2.0.1.27158, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimpleImpersonation.2.0.1\lib\net40-Client\SimpleImpersonation.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SimpleInjector, Version=3.3.2.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimpleInjector.3.3.2\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.104.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Data.SQLite.Core.1.0.104.0\lib\net46\System.Data.SQLite.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Topshelf, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
<HintPath>..\..\packages\Topshelf.4.0.3\lib\net452\Topshelf.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Topshelf.NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b800c4cfcdeea87b, processorArchitecture=MSIL">
<HintPath>..\..\packages\Topshelf.NLog.4.0.3\lib\net452\Topshelf.NLog.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\LanBackup.WebApp\Models\DTO\StatusReportInfo.cs">
<Link>Models\StatusReportInfo.cs</Link>
</Compile>
<Compile Include="Controllers\SignalRController.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="LanBackupAgentService.cs" />
<Compile Include="LanBackups API\ILanBackupsAPI.cs" />
<Compile Include="LanBackups API\LanBackupsAPI.cs" />
<Compile Include="LanBackups API\LanBackupsAPIExtensions.cs" />
<Compile Include="LanBackups API\Models\BackupConfiguration.cs" />
<Compile Include="LanBackups API\Models\BackupLog.cs" />
<Compile Include="LanBackups API\Models\IdentityError.cs" />
<Compile Include="LanBackups API\Models\IdentityResult.cs" />
<Compile Include="LanBackups API\Models\PaginatedListBackupConfigurationString.cs" />
<Compile Include="LanBackups API\Models\PaginatedListBackupLogDateTime.cs" />
<Compile Include="LanBackups API\Models\User.cs" />
<Compile Include="Message\StatusReport.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Message\StopMessage.cs" />
<Compile Include="Utils\Extensions.cs" />
<Compile Include="Utils\HangfireExtensions.cs" />
<Compile Include="Utils\NativeMethods.cs" />
<Compile Include="Utils\TinyMessenger.cs" />
<Compile Include="Utils\DI.cs" />
<Compile Include="Controllers\BackgroundRefreshController.cs" />
<Compile Include="Controllers\LanCopyController.cs" />
<Compile Include="Utils\Network.cs" />
<Compile Include="WebApi\WebApiService.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<Content Include="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="nlog.Debug.config">
<DependentUpon>nlog.config</DependentUpon>
</None>
<None Include="nlog.Release.config">
<DependentUpon>nlog.config</DependentUpon>
</None>
<None Include="nlog.xsd">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="app_icon.png.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\packages\System.Data.SQLite.Core.1.0.104.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\..\packages\System.Data.SQLite.Core.1.0.104.0\build\net46\System.Data.SQLite.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\System.Data.SQLite.Core.1.0.104.0\build\net46\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\System.Data.SQLite.Core.1.0.104.0\build\net46\System.Data.SQLite.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild" Condition="Exists('nlog.$(Configuration).config')">
<!--Generate transformed config in the output directory-->
<TransformXml Source="nlog.config" Destination="$(OutputPath)nlog.config" Transform="nlog.$(Configuration).config" />
</Target>
</Project>
@@ -0,0 +1,51 @@
using LanBackupAgent.Controllers;
using LanBackupAgent.Message;
using LanBackupAgent.Utils;
using Microsoft.AspNet.SignalR.Client;
using NLog;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Timers;
using TinyMessenger;
namespace LanBackupAgent
{
public class LanBackupAgentService
{
private ILogger logger;
ITinyMessengerHub messenger;
public LanBackupAgentService(ILogger mlogger, ITinyMessengerHub mmessenger)
{
this.logger = mlogger;
this.messenger = mmessenger;
}
public async Task<bool> Start()
{
logger.Info("Started");
//START LOGIC
DI.Container.GetInstance<BackgroundRefreshController>().Start();
await DI.Container.GetInstance<SignalRController>().Start();
return true;
}
public bool Stop()
{
//STOP LOGIC
logger.Info("Stopping signal received ...");
messenger.Publish(new StopMessage("STOP"));
return true;
}
}
}
@@ -0,0 +1,243 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Microsoft.Rest;
using Models;
/// <summary>
/// ASP.NET Core Web API for LAN Backup service
/// </summary>
public partial interface ILanBackupsAPI : IDisposable
{
/// <summary>
/// The base URI of the service.
/// </summary>
Uri BaseUri { get; set; }
/// <summary>
/// Gets or sets json serialization settings.
/// </summary>
JsonSerializerSettings SerializationSettings { get; }
/// <summary>
/// Gets or sets json deserialization settings.
/// </summary>
JsonSerializerSettings DeserializationSettings { get; }
/// <summary>
/// Subscription credentials which uniquely identify client
/// subscription.
/// </summary>
ServiceClientCredentials Credentials { get; }
/// <summary>
/// retrieve all backup configurations
/// </summary>
/// <param name='idx'>
/// </param>
/// <param name='siz'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<PaginatedListBackupConfigurationString>> ApiBackupConfigGetWithHttpMessagesAsync(string idx = default(string), string siz = default(string), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// create backup configuration
/// </summary>
/// <param name='backup'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<BackupConfiguration>> ApiBackupConfigPostWithHttpMessagesAsync(BackupConfiguration backup = default(BackupConfiguration), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// retrieve backup configuration by ID
/// </summary>
/// <param name='id'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<BackupConfiguration>> ApiBackupConfigByIdGetWithHttpMessagesAsync(string id, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Update backup configuration
/// </summary>
/// <param name='id'>
/// </param>
/// <param name='backup'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<BackupConfiguration>> ApiBackupConfigByIdPutWithHttpMessagesAsync(string id, BackupConfiguration backup = default(BackupConfiguration), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// delete backup configuration by id
/// </summary>
/// <param name='id'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<object>> ApiBackupConfigByIdDeleteWithHttpMessagesAsync(string id, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// retrieve backup configuration by ID
/// </summary>
/// <param name='clientid'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<IList<BackupConfiguration>>> ApiBackupConfigClientByClientidGetWithHttpMessagesAsync(string clientid, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// retrieves paginated logs from DB
/// </summary>
/// <param name='idx'>
/// page index
/// </param>
/// <param name='siz'>
/// page size
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<PaginatedListBackupLogDateTime>> ApiLogsGetWithHttpMessagesAsync(string idx = default(string), string siz = default(string), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Create an entry in the logs
/// </summary>
/// <param name='log'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<object>> ApiLogsPostWithHttpMessagesAsync(BackupLog log = default(BackupLog), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// retrieves alog record by ID
/// </summary>
/// <param name='id'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<BackupLog>> ApiLogsByIdGetWithHttpMessagesAsync(int id, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// retrieve all logs of a clientIP
/// </summary>
/// <param name='clientid'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<IList<BackupLog>>> ApiLogsClientByClientidGetWithHttpMessagesAsync(string clientid, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// retrieves all logs of a specific configuration
/// </summary>
/// <param name='configurationid'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<IList<BackupLog>>> ApiLogsConfigByConfigurationidGetWithHttpMessagesAsync(string configurationid, Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <param name='dtouser'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse<IdentityResult>> ApiUsersRegisterPostWithHttpMessagesAsync(User dtouser = default(User), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <param name='dtouser'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse> ApiUsersLoginPostWithHttpMessagesAsync(User dtouser = default(User), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <param name='dtouser'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse> ApiUsersPwchangePostWithHttpMessagesAsync(User dtouser = default(User), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse> ApiUsersListGetWithHttpMessagesAsync(Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
/// <param name='user'>
/// </param>
/// <param name='customHeaders'>
/// The headers that will be added to request.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
Task<HttpOperationResponse> ApiUsersListPostWithHttpMessagesAsync(User user = default(User), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken));
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,503 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Rest;
using Models;
/// <summary>
/// Extension methods for LanBackupsAPI.
/// </summary>
public static partial class LanBackupsAPIExtensions
{
/// <summary>
/// retrieve all backup configurations
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='idx'>
/// </param>
/// <param name='siz'>
/// </param>
public static PaginatedListBackupConfigurationString ApiBackupConfigGet(this ILanBackupsAPI operations, string idx = default(string), string siz = default(string))
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiBackupConfigGetAsync(idx, siz), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieve all backup configurations
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='idx'>
/// </param>
/// <param name='siz'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<PaginatedListBackupConfigurationString> ApiBackupConfigGetAsync(this ILanBackupsAPI operations, string idx = default(string), string siz = default(string), CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiBackupConfigGetWithHttpMessagesAsync(idx, siz, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// create backup configuration
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='backup'>
/// </param>
public static BackupConfiguration ApiBackupConfigPost(this ILanBackupsAPI operations, BackupConfiguration backup = default(BackupConfiguration))
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiBackupConfigPostAsync(backup), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// create backup configuration
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='backup'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<BackupConfiguration> ApiBackupConfigPostAsync(this ILanBackupsAPI operations, BackupConfiguration backup = default(BackupConfiguration), CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiBackupConfigPostWithHttpMessagesAsync(backup, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// retrieve backup configuration by ID
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
public static BackupConfiguration ApiBackupConfigByIdGet(this ILanBackupsAPI operations, string id)
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiBackupConfigByIdGetAsync(id), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieve backup configuration by ID
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<BackupConfiguration> ApiBackupConfigByIdGetAsync(this ILanBackupsAPI operations, string id, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiBackupConfigByIdGetWithHttpMessagesAsync(id, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// Update backup configuration
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
/// <param name='backup'>
/// </param>
public static BackupConfiguration ApiBackupConfigByIdPut(this ILanBackupsAPI operations, string id, BackupConfiguration backup = default(BackupConfiguration))
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiBackupConfigByIdPutAsync(id, backup), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// Update backup configuration
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
/// <param name='backup'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<BackupConfiguration> ApiBackupConfigByIdPutAsync(this ILanBackupsAPI operations, string id, BackupConfiguration backup = default(BackupConfiguration), CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiBackupConfigByIdPutWithHttpMessagesAsync(id, backup, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// delete backup configuration by id
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
public static object ApiBackupConfigByIdDelete(this ILanBackupsAPI operations, string id)
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiBackupConfigByIdDeleteAsync(id), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// delete backup configuration by id
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<object> ApiBackupConfigByIdDeleteAsync(this ILanBackupsAPI operations, string id, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiBackupConfigByIdDeleteWithHttpMessagesAsync(id, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// retrieve backup configuration by ID
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='clientid'>
/// </param>
public static IList<BackupConfiguration> ApiBackupConfigClientByClientidGet(this ILanBackupsAPI operations, string clientid)
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiBackupConfigClientByClientidGetAsync(clientid), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieve backup configuration by ID
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='clientid'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<IList<BackupConfiguration>> ApiBackupConfigClientByClientidGetAsync(this ILanBackupsAPI operations, string clientid, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiBackupConfigClientByClientidGetWithHttpMessagesAsync(clientid, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// retrieves paginated logs from DB
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='idx'>
/// page index
/// </param>
/// <param name='siz'>
/// page size
/// </param>
public static PaginatedListBackupLogDateTime ApiLogsGet(this ILanBackupsAPI operations, string idx = default(string), string siz = default(string))
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiLogsGetAsync(idx, siz), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieves paginated logs from DB
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='idx'>
/// page index
/// </param>
/// <param name='siz'>
/// page size
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<PaginatedListBackupLogDateTime> ApiLogsGetAsync(this ILanBackupsAPI operations, string idx = default(string), string siz = default(string), CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiLogsGetWithHttpMessagesAsync(idx, siz, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// Create an entry in the logs
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='log'>
/// </param>
public static object ApiLogsPost(this ILanBackupsAPI operations, BackupLog log = default(BackupLog))
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiLogsPostAsync(log), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// Create an entry in the logs
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='log'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<object> ApiLogsPostAsync(this ILanBackupsAPI operations, BackupLog log = default(BackupLog), CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiLogsPostWithHttpMessagesAsync(log, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// retrieves alog record by ID
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
public static BackupLog ApiLogsByIdGet(this ILanBackupsAPI operations, int id)
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiLogsByIdGetAsync(id), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieves alog record by ID
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='id'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<BackupLog> ApiLogsByIdGetAsync(this ILanBackupsAPI operations, int id, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiLogsByIdGetWithHttpMessagesAsync(id, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// retrieve all logs of a clientIP
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='clientid'>
/// </param>
public static IList<BackupLog> ApiLogsClientByClientidGet(this ILanBackupsAPI operations, string clientid)
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiLogsClientByClientidGetAsync(clientid), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieve all logs of a clientIP
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='clientid'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<IList<BackupLog>> ApiLogsClientByClientidGetAsync(this ILanBackupsAPI operations, string clientid, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiLogsClientByClientidGetWithHttpMessagesAsync(clientid, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <summary>
/// retrieves all logs of a specific configuration
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='configurationid'>
/// </param>
public static IList<BackupLog> ApiLogsConfigByConfigurationidGet(this ILanBackupsAPI operations, string configurationid)
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiLogsConfigByConfigurationidGetAsync(configurationid), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <summary>
/// retrieves all logs of a specific configuration
/// </summary>
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='configurationid'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<IList<BackupLog>> ApiLogsConfigByConfigurationidGetAsync(this ILanBackupsAPI operations, string configurationid, CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiLogsConfigByConfigurationidGetWithHttpMessagesAsync(configurationid, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='dtouser'>
/// </param>
public static IdentityResult ApiUsersRegisterPost(this ILanBackupsAPI operations, User dtouser = default(User))
{
return Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiUsersRegisterPostAsync(dtouser), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='dtouser'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task<IdentityResult> ApiUsersRegisterPostAsync(this ILanBackupsAPI operations, User dtouser = default(User), CancellationToken cancellationToken = default(CancellationToken))
{
using (var _result = await operations.ApiUsersRegisterPostWithHttpMessagesAsync(dtouser, null, cancellationToken).ConfigureAwait(false))
{
return _result.Body;
}
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='dtouser'>
/// </param>
public static void ApiUsersLoginPost(this ILanBackupsAPI operations, User dtouser = default(User))
{
Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiUsersLoginPostAsync(dtouser), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='dtouser'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task ApiUsersLoginPostAsync(this ILanBackupsAPI operations, User dtouser = default(User), CancellationToken cancellationToken = default(CancellationToken))
{
await operations.ApiUsersLoginPostWithHttpMessagesAsync(dtouser, null, cancellationToken).ConfigureAwait(false);
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='dtouser'>
/// </param>
public static void ApiUsersPwchangePost(this ILanBackupsAPI operations, User dtouser = default(User))
{
Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiUsersPwchangePostAsync(dtouser), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='dtouser'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task ApiUsersPwchangePostAsync(this ILanBackupsAPI operations, User dtouser = default(User), CancellationToken cancellationToken = default(CancellationToken))
{
await operations.ApiUsersPwchangePostWithHttpMessagesAsync(dtouser, null, cancellationToken).ConfigureAwait(false);
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
public static void ApiUsersListGet(this ILanBackupsAPI operations)
{
Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiUsersListGetAsync(), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task ApiUsersListGetAsync(this ILanBackupsAPI operations, CancellationToken cancellationToken = default(CancellationToken))
{
await operations.ApiUsersListGetWithHttpMessagesAsync(null, cancellationToken).ConfigureAwait(false);
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='user'>
/// </param>
public static void ApiUsersListPost(this ILanBackupsAPI operations, User user = default(User))
{
Task.Factory.StartNew(s => ((ILanBackupsAPI)s).ApiUsersListPostAsync(user), operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
}
/// <param name='operations'>
/// The operations group for this extension method.
/// </param>
/// <param name='user'>
/// </param>
/// <param name='cancellationToken'>
/// The cancellation token.
/// </param>
public static async Task ApiUsersListPostAsync(this ILanBackupsAPI operations, User user = default(User), CancellationToken cancellationToken = default(CancellationToken))
{
await operations.ApiUsersListPostWithHttpMessagesAsync(user, null, cancellationToken).ConfigureAwait(false);
}
}
}
@@ -0,0 +1,112 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class BackupConfiguration
{
/// <summary>
/// Initializes a new instance of the BackupConfiguration class.
/// </summary>
public BackupConfiguration() { }
/// <summary>
/// Initializes a new instance of the BackupConfiguration class.
/// </summary>
public BackupConfiguration(string clientIP, string id = default(string), byte[] rowVersion = default(byte[]), string srcFolder = default(string), string srcUser = default(string), string srcPass = default(string), string destLanFolder = default(string), string destUser = default(string), string destPass = default(string), bool? isActive = default(bool?), string crontab = default(string))
{
Id = id;
RowVersion = rowVersion;
ClientIP = clientIP;
SrcFolder = srcFolder;
SrcUser = srcUser;
SrcPass = srcPass;
DestLanFolder = destLanFolder;
DestUser = destUser;
DestPass = destPass;
IsActive = isActive;
Crontab = crontab;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "rowVersion")]
public byte[] RowVersion { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "clientIP")]
public string ClientIP { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "srcFolder")]
public string SrcFolder { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "srcUser")]
public string SrcUser { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "srcPass")]
public string SrcPass { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "destLanFolder")]
public string DestLanFolder { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "destUser")]
public string DestUser { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "destPass")]
public string DestPass { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "isActive")]
public bool? IsActive { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "crontab")]
public string Crontab { get; set; }
/// <summary>
/// Validate the object. Throws ValidationException if validation fails.
/// </summary>
public virtual void Validate()
{
if (ClientIP == null)
{
throw new ValidationException(ValidationRules.CannotBeNull, "ClientIP");
}
if (this.ClientIP != null)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(this.ClientIP, "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"))
{
throw new ValidationException(ValidationRules.Pattern, "ClientIP", "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
}
}
}
}
}
@@ -0,0 +1,90 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class BackupLog
{
/// <summary>
/// Initializes a new instance of the BackupLog class.
/// </summary>
public BackupLog() { }
/// <summary>
/// Initializes a new instance of the BackupLog class.
/// </summary>
public BackupLog(int? id = default(int?), byte[] rowVersion = default(byte[]), string clientIP = default(string), string configurationID = default(string), string description = default(string), string logError = default(string), string status = default(string), DateTime? dateTime = default(DateTime?))
{
Id = id;
RowVersion = rowVersion;
ClientIP = clientIP;
ConfigurationID = configurationID;
Description = description;
LogError = logError;
Status = status;
DateTime = dateTime;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "id")]
public int? Id { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "rowVersion")]
public byte[] RowVersion { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "clientIP")]
public string ClientIP { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "configurationID")]
public string ConfigurationID { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "logError")]
public string LogError { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "status")]
public string Status { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "dateTime")]
public DateTime? DateTime { get; set; }
/// <summary>
/// Validate the object. Throws ValidationException if validation fails.
/// </summary>
public virtual void Validate()
{
if (this.ClientIP != null)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(this.ClientIP, "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"))
{
throw new ValidationException(ValidationRules.Pattern, "ClientIP", "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
}
}
}
}
}
@@ -0,0 +1,41 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class IdentityError
{
/// <summary>
/// Initializes a new instance of the IdentityError class.
/// </summary>
public IdentityError() { }
/// <summary>
/// Initializes a new instance of the IdentityError class.
/// </summary>
public IdentityError(string code = default(string), string description = default(string))
{
Code = code;
Description = description;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "code")]
public string Code { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
}
}
@@ -0,0 +1,41 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class IdentityResult
{
/// <summary>
/// Initializes a new instance of the IdentityResult class.
/// </summary>
public IdentityResult() { }
/// <summary>
/// Initializes a new instance of the IdentityResult class.
/// </summary>
public IdentityResult(bool? succeeded = default(bool?), IList<IdentityError> errors = default(IList<IdentityError>))
{
Succeeded = succeeded;
Errors = errors;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "succeeded")]
public bool? Succeeded { get; private set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "errors")]
public IList<IdentityError> Errors { get; private set; }
}
}
@@ -0,0 +1,61 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class PaginatedListBackupConfigurationString
{
/// <summary>
/// Initializes a new instance of the
/// PaginatedListBackupConfigurationString class.
/// </summary>
public PaginatedListBackupConfigurationString() { }
/// <summary>
/// Initializes a new instance of the
/// PaginatedListBackupConfigurationString class.
/// </summary>
public PaginatedListBackupConfigurationString(int? pi = default(int?), int? tp = default(int?), IList<BackupConfiguration> recs = default(IList<BackupConfiguration>), bool? hp = default(bool?), bool? hn = default(bool?))
{
Pi = pi;
Tp = tp;
Recs = recs;
Hp = hp;
Hn = hn;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "pi")]
public int? Pi { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "tp")]
public int? Tp { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "recs")]
public IList<BackupConfiguration> Recs { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "hp")]
public bool? Hp { get; private set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "hn")]
public bool? Hn { get; private set; }
}
}
@@ -0,0 +1,61 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class PaginatedListBackupLogDateTime
{
/// <summary>
/// Initializes a new instance of the PaginatedListBackupLogDateTime
/// class.
/// </summary>
public PaginatedListBackupLogDateTime() { }
/// <summary>
/// Initializes a new instance of the PaginatedListBackupLogDateTime
/// class.
/// </summary>
public PaginatedListBackupLogDateTime(int? pi = default(int?), int? tp = default(int?), IList<BackupLog> recs = default(IList<BackupLog>), bool? hp = default(bool?), bool? hn = default(bool?))
{
Pi = pi;
Tp = tp;
Recs = recs;
Hp = hp;
Hn = hn;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "pi")]
public int? Pi { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "tp")]
public int? Tp { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "recs")]
public IList<BackupLog> Recs { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "hp")]
public bool? Hp { get; private set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "hn")]
public bool? Hn { get; private set; }
}
}
@@ -0,0 +1,65 @@
// Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
namespace LanBackupAgent.Models
{
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Rest;
using Microsoft.Rest.Serialization;
public partial class User
{
/// <summary>
/// Initializes a new instance of the User class.
/// </summary>
public User() { }
/// <summary>
/// Initializes a new instance of the User class.
/// </summary>
public User(string email = default(string), string password = default(string), string newPassword = default(string), bool? isAdmin = default(bool?), bool? succeeded = default(bool?), bool? isLockedOut = default(bool?))
{
Email = email;
Password = password;
NewPassword = newPassword;
IsAdmin = isAdmin;
Succeeded = succeeded;
IsLockedOut = isLockedOut;
}
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "email")]
public string Email { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "password")]
public string Password { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "newPassword")]
public string NewPassword { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "isAdmin")]
public bool? IsAdmin { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "succeeded")]
public bool? Succeeded { get; set; }
/// <summary>
/// </summary>
[JsonProperty(PropertyName = "isLockedOut")]
public bool? IsLockedOut { get; set; }
}
}
@@ -0,0 +1,14 @@
using LanBackup.Models;
using TinyMessenger;
namespace LanBackupAgent.Message
{
public class StatusReport : TinyMessageBase
{
public StatusReportInfo Info { get; set; }
public StatusReport(string sender, StatusReportInfo msg) : base(sender)
{
this.Info = msg;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
using TinyMessenger;
namespace LanBackupAgent.Message
{
public class StopMessage : TinyMessageBase
{
public StopMessage(string msg) : base(msg)
{
}
}
}
File diff suppressed because it is too large Load Diff
+108
View File
@@ -0,0 +1,108 @@
using LanBackupAgent.Utils;
using LanBackupAgent.WebApi;
using LanBackupAgent.Controllers;
using NLog;
using SimpleInjector;
using System;
using System.Configuration;
using TinyMessenger;
using Topshelf;
namespace LanBackupAgent
{
class Program
{
static ILogger logger;
static TinyMessengerHub messenger;
static Network network;
public static void Main()
{
//conf logger
logger = LogManager.GetCurrentClassLogger();
messenger = new TinyMessengerHub();
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += CurrentDomain_UnhandledException;
//setup DI container
// Register individual components
DI.Container.Register<ILogger>(() => logger, Lifestyle.Singleton);
DI.Container.Register<ITinyMessengerHub>(() => messenger, Lifestyle.Singleton);
network = new Network(logger);
DI.Container.Register<Network>(() => network, Lifestyle.Singleton);
DI.Container.Register<BackgroundRefreshController>(Lifestyle.Transient);
string webApiUrl = ConfigurationManager.AppSettings["webApiUrl"];
WebApiService api = new WebApiService(webApiUrl, logger, messenger);
DI.Container.Register<WebApiService>(() => api, Lifestyle.Singleton);
SignalRController signarl = new SignalRController(webApiUrl, logger, messenger, network);
DI.Container.Register<SignalRController>(() => signarl, Lifestyle.Singleton);
DI.Container.Register<LanCopyController>(Lifestyle.Transient);
logger.Trace("DI initialized");
logger.Trace("Starting service");
HostFactory.Run(x =>
{
//use NLog logger
x.UseNLog();
x.Service<LanBackupAgentService>(s =>
{
s.ConstructUsing(name => new LanBackupAgentService(logger, messenger));
s.WhenStarted(async tc => await tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsNetworkService();
x.StartAutomatically(); // Start the service automatically
x.SetDescription("LanBackup Agent Service");
x.SetDisplayName("LanBackup Agent");
//recommended that service names not contains spaces or other whitespace characters.
x.SetServiceName("LanBackupAgent");
x.EnableServiceRecovery(r =>
{
//you can have up to three of these
//r.RestartComputer(5, "message");
r.RestartService(1);//minutes for restart
//the last one will act for all subsequent failures
//r.RunProgram(7, "ping google.com");
//should this be true for crashed or non-zero exits
r.OnCrashOnly();
//number of days until the error count resets
r.SetResetPeriod(1);
});
//x.BeforeInstall(() => { ... });
//x.AfterInstall(() => { ... });
//x.BeforeUninstall(() => { ... });
//x.AfterUninstall(() => { ... });
x.OnException(ex =>
{
// Do something with the exception
logger.Error(ex, "LanBackup Agent service Error: ");
});
});
logger.Trace("Program DONE!");
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var logger = DI.Container.GetInstance<ILogger>();
logger.Fatal($"Global exception: {e.ExceptionObject}");
}
}
}
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("LanBackupAgent")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LanBackupAgent")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("cb7ee867-93e8-43e3-9eee-9068aed1de6c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+10
View File
@@ -0,0 +1,10 @@
using SimpleInjector;
namespace LanBackupAgent
{
public static class DI
{
//the DI container
public static Container Container { get; set; } = new Container();
}
}
+27
View File
@@ -0,0 +1,27 @@
using System;
namespace LanBackupAgent
{
public static class Extensions
{
/// <summary>
/// extension function for substracting an array
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <param name="index"></param>
/// <param name="length"></param>
/// <returns></returns>
public static T[] SubArray<T>(this T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}
}
}
@@ -0,0 +1,56 @@
using Hangfire;
using Hangfire.Storage;
using Hangfire.Storage.Monitoring;
using System;
using System.Collections.Generic;
namespace LanBackupAgent.Utils
{
public static class HangfireExtensions
{
public static void PurgeJobs(this IMonitoringApi monitor)
{
var toDelete = new List<string>();
foreach (QueueWithTopEnqueuedJobsDto queue in monitor.Queues())
{
for (var i = 0; i < Math.Ceiling(queue.Length / 1000d); i++)
{
monitor.EnqueuedJobs(queue.Name, 1000 * i, 1000)
.ForEach(x => toDelete.Add(x.Key));
}
}
foreach (var jobId in toDelete)
{
BackgroundJob.Delete(jobId);
}
}
public static void PurgeOrfanJobsExceptList(this IMonitoringApi monitor, List<string> exceptions)
{
var toDelete = new List<string>();
foreach (QueueWithTopEnqueuedJobsDto queue in monitor.Queues())
{
for (var i = 0; i < Math.Ceiling(queue.Length / 1000d); i++)
{
monitor.EnqueuedJobs(queue.Name, 1000 * i, 1000)
.ForEach(x =>
{
if (!exceptions.Contains(x.Key))
toDelete.Add(x.Key);
else
Console.WriteLine("x.Key " + x.Key + " remains.");
}
);
}
}
foreach (var jobId in toDelete)
{
BackgroundJob.Delete(jobId);
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Runtime.InteropServices;
namespace LanBackupAgent.Utils
{
public class NativeMethods
{
[DllImport("advapi32.DLL", SetLastError = true, CharSet=CharSet.Unicode)]
private static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
}
}
+75
View File
@@ -0,0 +1,75 @@
using NLog;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace LanBackupAgent.Utils
{
public class Network
{
private string localIP = string.Empty;
ILogger logger;
public Network(ILogger mlogger) {
this.logger = mlogger;
logger.Trace("Network instance initialized");
}
public string GetLocalIPAddress()
{
if (string.IsNullOrEmpty(localIP))
{
UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != OperationalStatus.Up)
continue;
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
continue;
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
continue;
if (IPAddress.IsLoopback(address.Address))
continue;
if (!address.IsDnsEligible)
{
if (mostSuitableIp == null)
mostSuitableIp = address;
continue;
}
// The best IP is the IP got from DHCP server
if (address.PrefixOrigin != PrefixOrigin.Dhcp)
{
if (mostSuitableIp == null || !mostSuitableIp.IsDnsEligible)
mostSuitableIp = address;
continue;
}
localIP = address.Address.ToString();
}
}
if (string.IsNullOrEmpty(localIP))
{
localIP = mostSuitableIp != null
? mostSuitableIp.Address.ToString()
: string.Empty;
}
}
logger.Trace($"Network instance IP: {localIP}");
return localIP;
}
}
}
+793
View File
@@ -0,0 +1,793 @@
//===============================================================================
// TinyIoC - TinyMessenger
//
// A simple messenger/event aggregator.
//
// http://hg.grumpydev.com/tinyioc
//===============================================================================
// Copyright © Steven Robbins. All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TinyMessenger
{
#region Message Types / Interfaces
/// <summary>
/// A TinyMessage to be published/delivered by TinyMessenger
/// </summary>
public interface ITinyMessage
{
/// <summary>
/// The sender of the message, or null if not supported by the message implementation.
/// </summary>
object Sender { get; }
}
/// <summary>
/// Base class for messages that provides weak refrence storage of the sender
/// </summary>
public abstract class TinyMessageBase : ITinyMessage
{
/// <summary>
/// Store a WeakReference to the sender just in case anyone is daft enough to
/// keep the message around and prevent the sender from being collected.
/// </summary>
private WeakReference _Sender;
public object Sender
{
get
{
return (_Sender == null) ? null : _Sender.Target;
}
}
/// <summary>
/// Initializes a new instance of the MessageBase class.
/// </summary>
/// <param name="sender">Message sender (usually "this")</param>
public TinyMessageBase(object sender)
{
if (sender == null)
throw new ArgumentNullException("sender");
_Sender = new WeakReference(sender);
}
}
/// <summary>
/// Generic message with user specified content
/// </summary>
/// <typeparam name="TContent">Content type to store</typeparam>
public class GenericTinyMessage<TContent> : TinyMessageBase
{
/// <summary>
/// Contents of the message
/// </summary>
public TContent Content { get; protected set; }
/// <summary>
/// Create a new instance of the GenericTinyMessage class.
/// </summary>
/// <param name="sender">Message sender (usually "this")</param>
/// <param name="content">Contents of the message</param>
public GenericTinyMessage(object sender, TContent content)
: base(sender)
{
Content = content;
}
}
/// <summary>
/// Basic "cancellable" generic message
/// </summary>
/// <typeparam name="TContent">Content type to store</typeparam>
public class CancellableGenericTinyMessage<TContent> : TinyMessageBase
{
/// <summary>
/// Cancel action
/// </summary>
public Action Cancel { get; protected set; }
/// <summary>
/// Contents of the message
/// </summary>
public TContent Content { get; protected set; }
/// <summary>
/// Create a new instance of the CancellableGenericTinyMessage class.
/// </summary>
/// <param name="sender">Message sender (usually "this")</param>
/// <param name="content">Contents of the message</param>
/// <param name="cancelAction">Action to call for cancellation</param>
public CancellableGenericTinyMessage(object sender, TContent content, Action cancelAction)
: base(sender)
{
if (cancelAction == null)
throw new ArgumentNullException("cancelAction");
Content = content;
Cancel = cancelAction;
}
}
/// <summary>
/// Represents an active subscription to a message
/// </summary>
public sealed class TinyMessageSubscriptionToken : IDisposable
{
private WeakReference _Hub;
private Type _MessageType;
/// <summary>
/// Initializes a new instance of the TinyMessageSubscriptionToken class.
/// </summary>
public TinyMessageSubscriptionToken(ITinyMessengerHub hub, Type messageType)
{
if (hub == null)
throw new ArgumentNullException("hub");
if (!typeof(ITinyMessage).IsAssignableFrom(messageType))
throw new ArgumentOutOfRangeException("messageType");
_Hub = new WeakReference(hub);
_MessageType = messageType;
}
public void Dispose()
{
if (_Hub.IsAlive)
{
var hub = _Hub.Target as ITinyMessengerHub;
if (hub != null)
{
var unsubscribeMethod = typeof(ITinyMessengerHub).GetMethod("Unsubscribe", new Type[] {typeof(TinyMessageSubscriptionToken)});
unsubscribeMethod = unsubscribeMethod.MakeGenericMethod(_MessageType);
unsubscribeMethod.Invoke(hub, new object[] {this});
}
}
GC.SuppressFinalize(this);
}
}
/// <summary>
/// Represents a message subscription
/// </summary>
public interface ITinyMessageSubscription
{
/// <summary>
/// Token returned to the subscribed to reference this subscription
/// </summary>
TinyMessageSubscriptionToken SubscriptionToken { get; }
/// <summary>
/// Whether delivery should be attempted.
/// </summary>
/// <param name="message">Message that may potentially be delivered.</param>
/// <returns>True - ok to send, False - should not attempt to send</returns>
bool ShouldAttemptDelivery(ITinyMessage message);
/// <summary>
/// Deliver the message
/// </summary>
/// <param name="message">Message to deliver</param>
void Deliver(ITinyMessage message);
}
/// <summary>
/// Message proxy definition.
///
/// A message proxy can be used to intercept/alter messages and/or
/// marshall delivery actions onto a particular thread.
/// </summary>
public interface ITinyMessageProxy
{
void Deliver(ITinyMessage message, ITinyMessageSubscription subscription);
}
/// <summary>
/// Default "pass through" proxy.
///
/// Does nothing other than deliver the message.
/// </summary>
public sealed class DefaultTinyMessageProxy : ITinyMessageProxy
{
private static readonly DefaultTinyMessageProxy _Instance = new DefaultTinyMessageProxy();
static DefaultTinyMessageProxy()
{
}
/// <summary>
/// Singleton instance of the proxy.
/// </summary>
public static DefaultTinyMessageProxy Instance
{
get
{
return _Instance;
}
}
private DefaultTinyMessageProxy()
{
}
public void Deliver(ITinyMessage message, ITinyMessageSubscription subscription)
{
subscription.Deliver(message);
}
}
#endregion
#region Exceptions
/// <summary>
/// Thrown when an exceptions occurs while subscribing to a message type
/// </summary>
[Serializable]
public class TinyMessengerSubscriptionException : Exception
{
private const string ERROR_TEXT = "Unable to add subscription for {0} : {1}";
public TinyMessengerSubscriptionException(Type messageType, string reason)
: base(String.Format(ERROR_TEXT, messageType, reason))
{
}
public TinyMessengerSubscriptionException(Type messageType, string reason, Exception innerException)
: base(String.Format(ERROR_TEXT, messageType, reason), innerException)
{
}
}
#endregion
#region Hub Interface
/// <summary>
/// Messenger hub responsible for taking subscriptions/publications and delivering of messages.
/// </summary>
public interface ITinyMessengerHub
{
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
/// All references are held with WeakReferences
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
/// Messages will be delivered via the specified proxy.
/// All references (apart from the proxy) are held with WeakReferences
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, bool useStrongReferences) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
/// Messages will be delivered via the specified proxy.
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// All references are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// Messages will be delivered via the specified proxy.
/// All references (apart from the proxy) are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// All references are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, bool useStrongReferences) where TMessage : class, ITinyMessage;
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// Messages will be delivered via the specified proxy.
/// All references are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage;
/// <summary>
/// Unsubscribe from a particular message type.
///
/// Does not throw an exception if the subscription is not found.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="subscriptionToken">Subscription token received from Subscribe</param>
void Unsubscribe<TMessage>(TinyMessageSubscriptionToken subscriptionToken) where TMessage : class, ITinyMessage;
/// <summary>
/// Publish a message to any subscribers
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="message">Message to deliver</param>
void Publish<TMessage>(TMessage message) where TMessage : class, ITinyMessage;
/// <summary>
/// Publish a message to any subscribers asynchronously
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="message">Message to deliver</param>
void PublishAsync<TMessage>(TMessage message) where TMessage : class, ITinyMessage;
/// <summary>
/// Publish a message to any subscribers asynchronously
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="message">Message to deliver</param>
/// <param name="callback">AsyncCallback called on completion</param>
void PublishAsync<TMessage>(TMessage message, AsyncCallback callback) where TMessage : class, ITinyMessage;
}
#endregion
#region Hub Implementation
/// <summary>
/// Messenger hub responsible for taking subscriptions/publications and delivering of messages.
/// </summary>
public sealed class TinyMessengerHub : ITinyMessengerHub
{
#region Private Types and Interfaces
private class WeakTinyMessageSubscription<TMessage> : ITinyMessageSubscription
where TMessage : class, ITinyMessage
{
protected TinyMessageSubscriptionToken _SubscriptionToken;
protected WeakReference _DeliveryAction;
protected WeakReference _MessageFilter;
public TinyMessageSubscriptionToken SubscriptionToken
{
get { return _SubscriptionToken; }
}
public bool ShouldAttemptDelivery(ITinyMessage message)
{
if (!(message is TMessage))
return false;
if (!_DeliveryAction.IsAlive)
return false;
if (!_MessageFilter.IsAlive)
return false;
return ((Func<TMessage, bool>)_MessageFilter.Target).Invoke(message as TMessage);
}
public void Deliver(ITinyMessage message)
{
if (!(message is TMessage))
throw new ArgumentException("Message is not the correct type");
if (!_DeliveryAction.IsAlive)
return;
((Action<TMessage>)_DeliveryAction.Target).Invoke(message as TMessage);
}
/// <summary>
/// Initializes a new instance of the WeakTinyMessageSubscription class.
/// </summary>
/// <param name="destination">Destination object</param>
/// <param name="deliveryAction">Delivery action</param>
/// <param name="messageFilter">Filter function</param>
public WeakTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionToken, Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter)
{
if (subscriptionToken == null)
throw new ArgumentNullException("subscriptionToken");
if (deliveryAction == null)
throw new ArgumentNullException("deliveryAction");
if (messageFilter == null)
throw new ArgumentNullException("messageFilter");
_SubscriptionToken = subscriptionToken;
_DeliveryAction = new WeakReference(deliveryAction);
_MessageFilter = new WeakReference(messageFilter);
}
}
private class StrongTinyMessageSubscription<TMessage> : ITinyMessageSubscription
where TMessage : class, ITinyMessage
{
protected TinyMessageSubscriptionToken _SubscriptionToken;
protected Action<TMessage> _DeliveryAction;
protected Func<TMessage, bool> _MessageFilter;
public TinyMessageSubscriptionToken SubscriptionToken
{
get { return _SubscriptionToken; }
}
public bool ShouldAttemptDelivery(ITinyMessage message)
{
if (!(message is TMessage))
return false;
return _MessageFilter.Invoke(message as TMessage);
}
public void Deliver(ITinyMessage message)
{
if (!(message is TMessage))
throw new ArgumentException("Message is not the correct type");
_DeliveryAction.Invoke(message as TMessage);
}
/// <summary>
/// Initializes a new instance of the TinyMessageSubscription class.
/// </summary>
/// <param name="destination">Destination object</param>
/// <param name="deliveryAction">Delivery action</param>
/// <param name="messageFilter">Filter function</param>
public StrongTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionToken, Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter)
{
if (subscriptionToken == null)
throw new ArgumentNullException("subscriptionToken");
if (deliveryAction == null)
throw new ArgumentNullException("deliveryAction");
if (messageFilter == null)
throw new ArgumentNullException("messageFilter");
_SubscriptionToken = subscriptionToken;
_DeliveryAction = deliveryAction;
_MessageFilter = messageFilter;
}
}
#endregion
#region Subscription dictionary
private class SubscriptionItem
{
public ITinyMessageProxy Proxy { get; private set; }
public ITinyMessageSubscription Subscription { get; private set; }
public SubscriptionItem(ITinyMessageProxy proxy, ITinyMessageSubscription subscription)
{
Proxy = proxy;
Subscription = subscription;
}
}
private readonly object _SubscriptionsPadlock = new object();
private readonly Dictionary<Type, List<SubscriptionItem>> _Subscriptions = new Dictionary<Type, List<SubscriptionItem>>();
#endregion
#region Public API
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
/// All references are held with strong references
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, (m) => true, true, DefaultTinyMessageProxy.Instance);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
/// Messages will be delivered via the specified proxy.
/// All references (apart from the proxy) are held with strong references
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, (m) => true, true, proxy);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, bool useStrongReferences) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, (m) => true, useStrongReferences, DefaultTinyMessageProxy.Instance);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action.
/// Messages will be delivered via the specified proxy.
///
/// All messages of this type will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, (m) => true, useStrongReferences, proxy);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// All references are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, messageFilter, true, DefaultTinyMessageProxy.Instance);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// Messages will be delivered via the specified proxy.
/// All references (apart from the proxy) are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, messageFilter, true, proxy);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// All references are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, bool useStrongReferences) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, messageFilter, useStrongReferences, DefaultTinyMessageProxy.Instance);
}
/// <summary>
/// Subscribe to a message type with the given destination and delivery action with the given filter.
/// Messages will be delivered via the specified proxy.
/// All references are held with WeakReferences
///
/// Only messages that "pass" the filter will be delivered.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="deliveryAction">Action to invoke when message is delivered</param>
/// <param name="useStrongReferences">Use strong references to destination and deliveryAction </param>
/// <param name="proxy">Proxy to use when delivering the messages</param>
/// <returns>TinyMessageSubscription used to unsubscribing</returns>
public TinyMessageSubscriptionToken Subscribe<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage
{
return AddSubscriptionInternal<TMessage>(deliveryAction, messageFilter, useStrongReferences, proxy);
}
/// <summary>
/// Unsubscribe from a particular message type.
///
/// Does not throw an exception if the subscription is not found.
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="subscriptionToken">Subscription token received from Subscribe</param>
public void Unsubscribe<TMessage>(TinyMessageSubscriptionToken subscriptionToken) where TMessage : class, ITinyMessage
{
RemoveSubscriptionInternal<TMessage>(subscriptionToken);
}
/// <summary>
/// Publish a message to any subscribers
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="message">Message to deliver</param>
public void Publish<TMessage>(TMessage message) where TMessage : class, ITinyMessage
{
PublishInternal<TMessage>(message);
}
/// <summary>
/// Publish a message to any subscribers asynchronously
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="message">Message to deliver</param>
public void PublishAsync<TMessage>(TMessage message) where TMessage : class, ITinyMessage
{
PublishAsyncInternal<TMessage>(message, null);
}
/// <summary>
/// Publish a message to any subscribers asynchronously
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <param name="message">Message to deliver</param>
/// <param name="callback">AsyncCallback called on completion</param>
public void PublishAsync<TMessage>(TMessage message, AsyncCallback callback) where TMessage : class, ITinyMessage
{
PublishAsyncInternal<TMessage>(message, callback);
}
#endregion
#region Internal Methods
private TinyMessageSubscriptionToken AddSubscriptionInternal<TMessage>(Action<TMessage> deliveryAction, Func<TMessage, bool> messageFilter, bool strongReference, ITinyMessageProxy proxy)
where TMessage : class, ITinyMessage
{
if (deliveryAction == null)
throw new ArgumentNullException("deliveryAction");
if (messageFilter == null)
throw new ArgumentNullException("messageFilter");
if (proxy == null)
throw new ArgumentNullException("proxy");
lock (_SubscriptionsPadlock)
{
List<SubscriptionItem> currentSubscriptions;
if (!_Subscriptions.TryGetValue(typeof(TMessage), out currentSubscriptions))
{
currentSubscriptions = new List<SubscriptionItem>();
_Subscriptions[typeof(TMessage)] = currentSubscriptions;
}
var subscriptionToken = new TinyMessageSubscriptionToken(this, typeof(TMessage));
ITinyMessageSubscription subscription;
if (strongReference)
subscription = new StrongTinyMessageSubscription<TMessage>(subscriptionToken, deliveryAction, messageFilter);
else
subscription = new WeakTinyMessageSubscription<TMessage>(subscriptionToken, deliveryAction, messageFilter);
currentSubscriptions.Add(new SubscriptionItem(proxy, subscription));
return subscriptionToken;
}
}
private void RemoveSubscriptionInternal<TMessage>(TinyMessageSubscriptionToken subscriptionToken)
where TMessage : class, ITinyMessage
{
if (subscriptionToken == null)
throw new ArgumentNullException("subscriptionToken");
lock (_SubscriptionsPadlock)
{
List<SubscriptionItem> currentSubscriptions;
if (!_Subscriptions.TryGetValue(typeof(TMessage), out currentSubscriptions))
return;
var currentlySubscribed = (from sub in currentSubscriptions
where object.ReferenceEquals(sub.Subscription.SubscriptionToken, subscriptionToken)
select sub).ToList();
currentlySubscribed.ForEach(sub => currentSubscriptions.Remove(sub));
}
}
private void PublishInternal<TMessage>(TMessage message)
where TMessage : class, ITinyMessage
{
if (message == null)
throw new ArgumentNullException("message");
List<SubscriptionItem> currentlySubscribed;
lock (_SubscriptionsPadlock)
{
List<SubscriptionItem> currentSubscriptions;
if (!_Subscriptions.TryGetValue(typeof(TMessage), out currentSubscriptions))
return;
currentlySubscribed = (from sub in currentSubscriptions
where sub.Subscription.ShouldAttemptDelivery(message)
select sub).ToList();
}
currentlySubscribed.ForEach(sub =>
{
try
{
sub.Proxy.Deliver(message, sub.Subscription);
}
catch (Exception)
{
// Ignore any errors and carry on
// TODO - add to a list of erroring subs and remove them?
}
});
}
private void PublishAsyncInternal<TMessage>(TMessage message, AsyncCallback callback) where TMessage : class, ITinyMessage
{
Action publishAction = () => { PublishInternal<TMessage>(message); };
publishAction.BeginInvoke(callback, null);
}
#endregion
}
#endregion
}
+143
View File
@@ -0,0 +1,143 @@
using LanBackupAgent.Message;
using LanBackupAgent.Models;
using LanBackupAgent.Utils;
using Microsoft.Rest;
using NLog;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using TinyMessenger;
namespace LanBackupAgent.WebApi
{
public class WebApiService
{
private ILogger logger;
private ITinyMessengerHub messenger;
private string webapiUrlBase;
public WebApiService(string mwebapiUrlBase,
ILogger mlogger,
ITinyMessengerHub mmessenger
)
{
this.webapiUrlBase = mwebapiUrlBase;
this.logger = mlogger;
this.messenger = mmessenger;
this.messenger.Subscribe<StopMessage>(Stop);
logger.Trace("WebApiService instance initialized");
}
private void Stop(StopMessage obj)
{
//TODO - implement cancelation
}
public async Task<IList<BackupConfiguration>> LoadBackupConfigurations()
{
IList<BackupConfiguration> result = new List<BackupConfiguration>();
try
{
LanBackupsAPI api = getApi();
//retrieve own backup configurations
string localIp = DI.Container.GetInstance<Network>().GetLocalIPAddress();
result = await api.ApiBackupConfigClientByClientidGetAsync(localIp);
if (result != null)
{
logger.Info($"loadBackupConfigurations WebApi, response: {result.Count} configurations.");
}
else
{
logger.Info($"loadBackupConfigurations WebApi, response: NO configurations.");
}
}
catch (HttpRequestException hex)
{
if (hex.InnerException is WebException)
{
WebException wex = hex.InnerException as WebException;
if (wex.Status == WebExceptionStatus.ConnectFailure)
{
//ignore this err
}
else
{
logger.Error($"ERR WebException HResult: {wex.HResult}");
logger.Error($"ERR WebException Status: {wex.Status}");
logger.Error($"ERR WebException Message: {wex.Message}");
}
}
}
catch (Exception ex)
{
logger.Error($"loadBackupConfigurations ERROR: {ex}");
}
return result;
}
public async void LogActivity(string backupId, string message, string error, string status)
{
try
{
LanBackupsAPI api = getApi();
// submit activity status
var log = new BackupLog()
{
ClientIP = DI.Container.GetInstance<Network>().GetLocalIPAddress(),
Status = status,
Description = message,
LogError = error,
DateTime = DateTime.UtcNow
};
var result = await api.ApiLogsPostAsync(log);
logger.Info($"Log sent to WebApi, response ID: {result}");
}
catch (HttpRequestException hex)
{
if (hex.InnerException is WebException)
{
WebException wex = hex.InnerException as WebException;
if (wex.Status == WebExceptionStatus.ConnectFailure)
{
//ignore this err
}
else
{
logger.Error($"ERR WebException HResult: {wex.HResult}");
logger.Error($"ERR WebException Status: {wex.Status}");
logger.Error($"ERR WebException Message: {wex.Message}");
}
}
}
catch (Exception ex)
{
logger.Error($"WebApi ERROR: {ex}");
}
}
#region helper
private LanBackupsAPI getApi()
{
string webApiUrl = webapiUrlBase;
var credentials = new TokenCredentials("<bearer token>");
LanBackupsAPI api = new LanBackupsAPI(new Uri(
webApiUrl
), credentials);
return api;
}
#endregion helper
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0"?>
<!-- For more information on using app.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
>
<rules xdt:Transform="Replace">
<logger name="*" minlevel="Trace" writeTo="file" />
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</nlog>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0"?>
<!-- For more information on using app.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
>
<rules xdt:Transform="Replace">
<logger name="*" minlevel="Info" writeTo="file" />
<logger name="*" minlevel="Info" writeTo="console" />
</rules>
</nlog>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target xsi:type="File"
name="file"
filename="${basedir}/log_${shortdate}.log"
keepFileOpen ="true"
openFileCacheTimeout = "30"
></target>
<target name="console" xsi:type="ColoredConsole" detectConsoleAvailable="true" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="file" />
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</nlog>
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="4.3.0" targetFramework="net462" />
<package id="ColoredConsole" version="0.5.0" targetFramework="net462" />
<package id="Dapper" version="1.42" targetFramework="net462" />
<package id="Hangfire.Core" version="1.6.8" targetFramework="net462" />
<package id="Hangfire.SQLite" version="1.1.1.0" targetFramework="net462" />
<package id="Microsoft.AspNet.SignalR.Client" version="2.2.1" targetFramework="net462" />
<package id="Microsoft.Rest.ClientRuntime" version="2.3.4" targetFramework="net462" />
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net462" />
<package id="NLog" version="4.4.1" targetFramework="net462" />
<package id="NLog.Schema" version="4.4.1" targetFramework="net462" />
<package id="Owin" version="1.0" targetFramework="net462" />
<package id="SimpleImpersonation" version="2.0.1" targetFramework="net462" />
<package id="SimpleInjector" version="3.3.2" targetFramework="net462" />
<package id="System.Data.SQLite.Core" version="1.0.104.0" targetFramework="net462" />
<package id="TinyMessenger" version="1.0" targetFramework="net462" />
<package id="Topshelf" version="4.0.3" targetFramework="net462" />
<package id="Topshelf.NLog" version="4.0.3" targetFramework="net462" />
</packages>