From 19f5d28eaa51bb758a5f8c44b404fb344d920a5f Mon Sep 17 00:00:00 2001 From: Uncled1023 Date: Sun, 15 May 2016 23:43:31 -0700 Subject: [PATCH] Moved user modification to helper class. Added cleaning of users to server maintainence program. Added cli args to server maint program. Modified last activity to also grab from email and git. --- ServerMaint/ArgumentOptions.cs | 60 ++++ ServerMaint/Program.cs | 149 +++++++-- ServerMaint/ServerMaint.csproj | 19 +- ServerMaint/packages.config | 9 +- .../Areas/User/Controllers/UserController.cs | 219 +------------- Teknik/Areas/User/Utility/UserHelper.cs | 286 ++++++++++++++++++ Teknik/Areas/User/Views/User/Index.cshtml | 2 +- Teknik/Configuration/GitConfig.cs | 3 + Teknik/Teknik.csproj | 1 + 9 files changed, 512 insertions(+), 236 deletions(-) create mode 100644 ServerMaint/ArgumentOptions.cs diff --git a/ServerMaint/ArgumentOptions.cs b/ServerMaint/ArgumentOptions.cs new file mode 100644 index 0000000..9d8aab5 --- /dev/null +++ b/ServerMaint/ArgumentOptions.cs @@ -0,0 +1,60 @@ +using CommandLine; +using CommandLine.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ServerMaint +{ + public class ArgumentOptions + { + [ParserState] + public IParserState LastParserState { get; set; } + + [Option('a', "all", DefaultValue = false, Required = false, HelpText = "Run All Processes")] + public bool RunAll { get; set; } + + [Option('u', "clean-users", DefaultValue = false, Required = false, HelpText = "Clean all inactive users")] + public bool CleanUsers { get; set; } + + [Option('s', "scan", DefaultValue = false, Required = false, HelpText = "Scan all uploads for viruses")] + public bool ScanUploads { get; set; } + + [Option('c', "config", Required = false, HelpText = "The path to the teknik config file")] + public string Config { get; set; } + + [Option('d', "days", DefaultValue = 90, Required = false, HelpText = "Days before the user is deleted")] + public int DaysBeforeDeletion { get; set; } + + [Option('e', "emails", DefaultValue = 2, Required = false, HelpText = "Number of emails to send before deletion")] + public int EmailsToSend { get; set; } + + // Omitting long name, default --verbose + [Option(HelpText = "Prints all messages to standard output.")] + public bool Verbose { get; set; } + + [HelpOption] + public string GetUsage() + { + var help = new HelpText(); + + // ... + if (this.LastParserState.Errors.Any()) + { + var errors = help.RenderParsingErrorsText(this, 2); // indent with two spaces + + if (!string.IsNullOrEmpty(errors)) + { + help.AddPreOptionsLine(string.Concat(Environment.NewLine, "ERROR(S):")); + help.AddPreOptionsLine(errors); + } + } + + // ... + return help; + } + + } +} diff --git a/ServerMaint/Program.cs b/ServerMaint/Program.cs index 0592a0a..e2dc3a3 100644 --- a/ServerMaint/Program.cs +++ b/ServerMaint/Program.cs @@ -4,9 +4,14 @@ using System.Collections.Generic; using System.Data.Entity; using System.IO; using System.Linq; +using System.Net; +using System.Net.Mail; using System.Reflection; using System.Text; +using Teknik.Areas.Transparency.Models; using Teknik.Areas.Upload.Models; +using Teknik.Areas.Users.Models; +using Teknik.Areas.Users.Utility; using Teknik.Configuration; using Teknik.Helpers; using Teknik.Models; @@ -16,26 +21,54 @@ namespace ServerMaint public class Program { private static string currentPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - private static string parentPath = Directory.GetParent(currentPath).FullName; private static string virusFile = Path.Combine(currentPath, "virusLogs.txt"); private static string errorFile = Path.Combine(currentPath, "errorLogs.txt"); - private static string configPath = Path.Combine(parentPath, "App_Data"); + private static string configPath = currentPath; + + private const string TAKEDOWN_REPORTER = "Teknik Automated System"; public static event Action OutputEvent; - public static void Main(string[] args) + public static int Main(string[] args) { - - // Let's clean some stuff!! try { - Config config = Config.Load(configPath); - TeknikEntities db = new TeknikEntities(); - - // Scan all the uploads for viruses, and remove the bad ones - if (config.UploadConfig.VirusScanEnable) + ArgumentOptions options = new ArgumentOptions(); + var parser = new CommandLine.Parser(config => config.HelpWriter = Console.Out); + if (parser.ParseArguments(args, options)) { - ScanUploads(config, db); + if (!string.IsNullOrEmpty(options.Config)) + configPath = options.Config; + + if (Directory.Exists(configPath)) + { + Config config = Config.Load(configPath); + TeknikEntities db = new TeknikEntities(); + + // Scan all the uploads for viruses, and remove the bad ones + if (options.ScanUploads && config.UploadConfig.VirusScanEnable) + { + ScanUploads(config, db); + } + + // Cleans all inactive users + if (options.CleanUsers) + { + CleanUsers(config, db, options.DaysBeforeDeletion, options.EmailsToSend); + } + Output(string.Format("[{0}] Finished Server Maintainence Process.", DateTime.Now)); + return 0; + } + else + { + string msg = string.Format("[{0}] Config File does not exist.", DateTime.Now); + File.AppendAllLines(errorFile, new List { msg }); + Output(msg); + } + } + else + { + Output(options.GetUsage()); } } catch (Exception ex) @@ -44,6 +77,7 @@ namespace ServerMaint File.AppendAllLines(errorFile, new List { msg }); Output(msg); } + return -1; } public static void ScanUploads(Config config, TeknikEntities db) @@ -87,15 +121,15 @@ namespace ServerMaint string msg = string.Format("[{0}] Virus Detected: {1} - {2} - {3}", DateTime.Now, upload.Url, upload.FileName, scanResult.InfectedFiles.First().VirusName); File.AppendAllLines(virusFile, new List { msg }); Output(msg); - //// Delete from the DB - //db.Uploads.Remove(upload); - //db.SaveChanges(); + // Delete from the DB + db.Uploads.Remove(upload); + db.SaveChanges(); - //// Delete the File - //if (File.Exists(filePath)) - //{ - // File.Delete(filePath); - //} + // Delete the File + if (File.Exists(filePath)) + { + File.Delete(filePath); + } break; case ClamScanResults.Error: string errorMsg = string.Format("[{0}] Scan Error: {1}", DateTime.Now, scanResult.RawResult); @@ -111,9 +145,86 @@ namespace ServerMaint } } + // Add to transparency report if any were found + Takedown report = db.Takedowns.Create(); + report.Requester = TAKEDOWN_REPORTER; + report.RequesterContact = config.SupportEmail; + report.DateRequested = DateTime.Now; + report.Reason = "Malware Found"; + report.ActionTaken = string.Format("{0} Uploads removed", totalViruses); + report.DateActionTaken = DateTime.Now; + db.Takedowns.Add(report); + db.SaveChanges(); + Output(string.Format("Scanning Complete. {0} Scanned | {1} Viruses Found | {2} Total Files", totalScans, totalViruses, totalCount)); } + public static void CleanUsers(Config config, TeknikEntities db, int maxDays, int numEmails) + { + int totalUsers = 0; + + List curUsers = db.Users.ToList(); + foreach (User user in curUsers) + { + DateTime lastActivity = UserHelper.GetLastActivity(db, config, user); + + TimeSpan inactiveTime = DateTime.Now.Subtract(lastActivity); + + // If older than max days, delete + if (inactiveTime >= new TimeSpan(maxDays, 0, 0, 0, 0)) + { + UserHelper.DeleteUser(db, config, user); + continue; + } + + // Otherwise, send an email if they are within +-1 day of email days + int daysForEmail = (int)Math.Floor((double)(maxDays / (numEmails + 1))); + for (int i = daysForEmail; i < maxDays; i = i + daysForEmail) + { + if (inactiveTime.Days == daysForEmail) + { + string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain); + // Let's send them an email + SmtpClient client = new SmtpClient(); + client.Host = config.ContactConfig.Host; + client.Port = config.ContactConfig.Port; + client.EnableSsl = config.ContactConfig.SSL; + client.DeliveryMethod = SmtpDeliveryMethod.Network; + client.UseDefaultCredentials = true; + client.Credentials = new NetworkCredential(config.ContactConfig.Username, config.ContactConfig.Password); + client.Timeout = 5000; + + MailMessage mail = new MailMessage(config.SupportEmail, email); + mail.Subject = "Inactive Account Notice"; + mail.Body = string.Format(@" +The account {0} has not had any activity for {1} days. After {2} days of inactivity, this account will be deleted permanently. + +In order to avoid this, login into your email, or teknik website. + +Thank you for your use of Teknik and I hope you decide to come back. + +- Teknik Administration", user.Username, inactiveTime.Days, maxDays); + mail.BodyEncoding = UTF8Encoding.UTF8; + mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never; + + client.Send(mail); + break; + } + } + } + + // Add to transparency report if any users were removed + Takedown report = db.Takedowns.Create(); + report.Requester = TAKEDOWN_REPORTER; + report.RequesterContact = config.SupportEmail; + report.DateRequested = DateTime.Now; + report.Reason = "User Inactive"; + report.ActionTaken = string.Format("{0} Users Removed", totalUsers); + report.DateActionTaken = DateTime.Now; + db.Takedowns.Add(report); + db.SaveChanges(); + } + public static void Output(string message) { Console.WriteLine(message); diff --git a/ServerMaint/ServerMaint.csproj b/ServerMaint/ServerMaint.csproj index 1847449..924b411 100644 --- a/ServerMaint/ServerMaint.csproj +++ b/ServerMaint/ServerMaint.csproj @@ -52,8 +52,12 @@ false - - ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll + + ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll + True + + + ..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll True @@ -77,11 +81,11 @@ True - ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll True - - ..\packages\Inferno.1.1.0\lib\net451\SecurityDriven.Inferno.dll + + ..\packages\Inferno.1.2.0\lib\net452\SecurityDriven.Inferno.dll True @@ -94,6 +98,7 @@ + @@ -120,12 +125,12 @@ - + 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}. - +