mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
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.
This commit is contained in:
parent
24e89c02aa
commit
19f5d28eaa
60
ServerMaint/ArgumentOptions.cs
Normal file
60
ServerMaint/ArgumentOptions.cs
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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,27 +21,55 @@ 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<string> OutputEvent;
|
||||
|
||||
public static void Main(string[] args)
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
|
||||
// Let's clean some stuff!!
|
||||
try
|
||||
{
|
||||
ArgumentOptions options = new ArgumentOptions();
|
||||
var parser = new CommandLine.Parser(config => config.HelpWriter = Console.Out);
|
||||
if (parser.ParseArguments(args, options))
|
||||
{
|
||||
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 (config.UploadConfig.VirusScanEnable)
|
||||
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<string> { msg });
|
||||
Output(msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Output(options.GetUsage());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -44,6 +77,7 @@ namespace ServerMaint
|
||||
File.AppendAllLines(errorFile, new List<string> { 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<string> { 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<User> 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);
|
||||
|
@ -52,8 +52,12 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
|
||||
<Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
|
||||
<HintPath>..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="CommandLine, Version=1.9.71.2, Culture=neutral, PublicKeyToken=de6f01bd326f8c32, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
@ -77,11 +81,11 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SecurityDriven.Inferno, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Inferno.1.1.0\lib\net451\SecurityDriven.Inferno.dll</HintPath>
|
||||
<Reference Include="SecurityDriven.Inferno, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Inferno.1.2.0\lib\net452\SecurityDriven.Inferno.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@ -94,6 +98,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArgumentOptions.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
@ -120,12 +125,12 @@
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\packages\GitVersionTask.3.4.1\build\dotnet\GitVersionTask.targets" Condition="Exists('..\packages\GitVersionTask.3.4.1\build\dotnet\GitVersionTask.targets')" />
|
||||
<Import Project="..\packages\GitVersionTask.3.5.3\build\dotnet\GitVersionTask.targets" Condition="Exists('..\packages\GitVersionTask.3.5.3\build\dotnet\GitVersionTask.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\GitVersionTask.3.4.1\build\dotnet\GitVersionTask.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GitVersionTask.3.4.1\build\dotnet\GitVersionTask.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\GitVersionTask.3.5.3\build\dotnet\GitVersionTask.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GitVersionTask.3.5.3\build\dotnet\GitVersionTask.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.
|
||||
|
@ -1,11 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="BouncyCastle" version="1.7.0" targetFramework="net452" />
|
||||
<package id="BouncyCastle" version="1.8.1" targetFramework="net452" />
|
||||
<package id="CommandLineParser" version="1.9.71" targetFramework="net452" />
|
||||
<package id="EntityFramework" version="6.1.3" targetFramework="net452" />
|
||||
<package id="GitVersionTask" version="3.4.1" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="Inferno" version="1.1.0" targetFramework="net452" />
|
||||
<package id="GitVersionTask" version="3.5.3" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="Inferno" version="1.2.0" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.1" targetFramework="net452" />
|
||||
<package id="nClam" version="2.0.6.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />
|
||||
</packages>
|
@ -18,6 +18,7 @@ using Teknik.Models;
|
||||
using Teknik.ViewModels;
|
||||
using System.Windows;
|
||||
using System.Net;
|
||||
using Teknik.Areas.Users.Utility;
|
||||
|
||||
namespace Teknik.Areas.Users.Controllers
|
||||
{
|
||||
@ -52,7 +53,7 @@ namespace Teknik.Areas.Users.Controllers
|
||||
model.Email = string.Format("{0}@{1}", user.Username, Config.EmailConfig.Domain);
|
||||
}
|
||||
model.JoinDate = user.JoinDate;
|
||||
model.LastSeen = user.LastSeen;
|
||||
model.LastSeen = UserHelper.GetLastActivity(db, Config, user);
|
||||
|
||||
model.UserSettings = user.UserSettings;
|
||||
model.BlogSettings = user.BlogSettings;
|
||||
@ -208,7 +209,7 @@ namespace Teknik.Areas.Users.Controllers
|
||||
{
|
||||
if (Config.UserConfig.RegistrationEnabled)
|
||||
{
|
||||
if (Utility.UserHelper.UserExists(db, model.Username))
|
||||
if (UserHelper.UserExists(db, model.Username))
|
||||
{
|
||||
return Json(new { error = "That username already exists." });
|
||||
}
|
||||
@ -216,51 +217,9 @@ namespace Teknik.Areas.Users.Controllers
|
||||
{
|
||||
return Json(new { error = "Passwords must match." });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string email = string.Format("{0}@{1}", model.Username, Config.EmailConfig.Domain);
|
||||
// If Email Server is enabled
|
||||
if (Config.EmailConfig.Enabled)
|
||||
{
|
||||
// Connect to hmailserver COM
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(Config.EmailConfig.Username, Config.EmailConfig.Password);
|
||||
|
||||
var domain = app.Domains.ItemByName[Config.EmailConfig.Domain];
|
||||
try
|
||||
{
|
||||
var account = domain.Accounts.ItemByAddress[email];
|
||||
return Json(new { error = "That email already exists." });
|
||||
}
|
||||
catch { }
|
||||
|
||||
// If we got an exception, then the email doesnt exist and we continue on!
|
||||
var newAccount = domain.Accounts.Add();
|
||||
newAccount.Address = email;
|
||||
newAccount.Password = model.Password;
|
||||
newAccount.Active = true;
|
||||
newAccount.MaxSize = Config.EmailConfig.MaxSize;
|
||||
|
||||
newAccount.Save();
|
||||
}
|
||||
|
||||
// If Git is enabled
|
||||
if (Config.GitConfig.Enabled)
|
||||
{
|
||||
// Add gogs user
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
var obj = new { source_id = Config.GitConfig.SourceId, username = model.Username, email = email, login_name = email, password = model.Password };
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/json";
|
||||
Uri baseUri = new Uri(Config.GitConfig.Host);
|
||||
Uri finalUri = new Uri(baseUri, "api/v1/admin/users?token=" + Config.GitConfig.AccessToken);
|
||||
string result = client.UploadString(finalUri, "POST", json);
|
||||
}
|
||||
}
|
||||
|
||||
// Add User
|
||||
User newUser = db.Users.Create();
|
||||
newUser.JoinDate = DateTime.Now;
|
||||
newUser.Username = model.Username;
|
||||
@ -268,18 +227,12 @@ namespace Teknik.Areas.Users.Controllers
|
||||
newUser.UserSettings = new UserSettings();
|
||||
newUser.BlogSettings = new BlogSettings();
|
||||
newUser.UploadSettings = new UploadSettings();
|
||||
db.Users.Add(newUser);
|
||||
db.SaveChanges();
|
||||
|
||||
// Generate blog for the user
|
||||
var newBlog = db.Blogs.Create();
|
||||
newBlog.UserId = newUser.UserId;
|
||||
db.Blogs.Add(newBlog);
|
||||
db.SaveChanges();
|
||||
UserHelper.AddUser(db, Config, newUser, model.Password);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Json(new { error = "Unable to create the user." });
|
||||
return Json(new { error = ex.Message });
|
||||
}
|
||||
return Login(new LoginViewModel { Username = model.Username, Password = model.Password, RememberMe = false, ReturnUrl = model.ReturnUrl });
|
||||
}
|
||||
@ -293,9 +246,10 @@ namespace Teknik.Areas.Users.Controllers
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
User user = Utility.UserHelper.GetUser(db, User.Identity.Name);
|
||||
User user = UserHelper.GetUser(db, User.Identity.Name);
|
||||
if (user != null)
|
||||
{
|
||||
bool changePass = false;
|
||||
string email = string.Format("{0}@{1}", User.Identity.Name, Config.EmailConfig.Domain);
|
||||
// Changing Password?
|
||||
if (!string.IsNullOrEmpty(curPass) && (!string.IsNullOrEmpty(newPass) || !string.IsNullOrEmpty(newPassConfirm)))
|
||||
@ -311,37 +265,7 @@ namespace Teknik.Areas.Users.Controllers
|
||||
return Json(new { error = "New Password Must Match." });
|
||||
}
|
||||
user.HashedPassword = SHA384.Hash(User.Identity.Name, newPass);
|
||||
|
||||
// Update Email Pass
|
||||
if (Config.EmailConfig.Enabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(Config.EmailConfig.Username, Config.EmailConfig.Password);
|
||||
var domain = app.Domains.ItemByName[Config.EmailConfig.Domain];
|
||||
var account = domain.Accounts.ItemByAddress[email];
|
||||
account.Password = newPass;
|
||||
account.Save();
|
||||
}
|
||||
catch (COMException)
|
||||
{ }
|
||||
}
|
||||
|
||||
// Update Git Pass
|
||||
if (Config.GitConfig.Enabled)
|
||||
{
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
var obj = new { source_id = Config.GitConfig.SourceId, email = email, password = newPass };
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/json";
|
||||
Uri baseUri = new Uri(Config.GitConfig.Host);
|
||||
Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + User.Identity.Name + "?token=" + Config.GitConfig.AccessToken);
|
||||
string result = client.UploadString(finalUri, "PATCH", json);
|
||||
}
|
||||
}
|
||||
changePass = true;
|
||||
}
|
||||
|
||||
// PGP Key valid?
|
||||
@ -360,9 +284,7 @@ namespace Teknik.Areas.Users.Controllers
|
||||
|
||||
user.UploadSettings.SaveKey = saveKey;
|
||||
user.UploadSettings.ServerSideEncrypt = serverSideEncrypt;
|
||||
|
||||
db.Entry(user).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
UserHelper.SaveUser(db, Config, user, changePass, newPass);
|
||||
return Json(new { result = true });
|
||||
}
|
||||
return Json(new { error = "User does not exist" });
|
||||
@ -375,130 +297,17 @@ namespace Teknik.Areas.Users.Controllers
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
if (Config.EmailConfig.Enabled)
|
||||
User user = UserHelper.GetUser(db, User.Identity.Name);
|
||||
if (user != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delete Email
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(Config.EmailConfig.Username, Config.EmailConfig.Password);
|
||||
var domain = app.Domains.ItemByName[Config.EmailConfig.Domain];
|
||||
var account = domain.Accounts.ItemByAddress[string.Format("{0}@{1}", User.Identity.Name, Config.EmailConfig.Domain)];
|
||||
if (account != null)
|
||||
{
|
||||
account.Delete();
|
||||
}
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Json(new { error = "Unable to delete email account." });
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Git
|
||||
if (Config.GitConfig.Enabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri baseUri = new Uri(Config.GitConfig.Host);
|
||||
Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + User.Identity.Name + "?token=" + Config.GitConfig.AccessToken);
|
||||
WebRequest request = WebRequest.Create(finalUri);
|
||||
request.Method = "DELETE";
|
||||
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (response.StatusCode != HttpStatusCode.NotFound && response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
return Json(new { error = "Unable to delete git account. Response Code: " + response.StatusCode });
|
||||
}
|
||||
}
|
||||
catch (HttpException htex)
|
||||
{
|
||||
if (htex.GetHttpCode() != 404)
|
||||
return Json(new { error = "Unable to delete git account. Http Exception: " + htex.Message });
|
||||
UserHelper.DeleteUser(db, Config, user);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// This error signifies the user doesn't exist, so we can continue deleting
|
||||
if (ex.Message != "The remote server returned an error: (404) Not Found.")
|
||||
{
|
||||
return Json(new { error = "Unable to delete git account. Exception: " + ex.Message });
|
||||
return Json(new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update uploads
|
||||
List<Upload.Models.Upload> uploads = db.Uploads.Include("User").Where(u => u.User.Username == User.Identity.Name).ToList();
|
||||
if (uploads != null)
|
||||
{
|
||||
foreach (Upload.Models.Upload upload in uploads)
|
||||
{
|
||||
upload.UserId = null;
|
||||
db.Entry(upload).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
// Update pastes
|
||||
List<Paste.Models.Paste> pastes = db.Pastes.Include("User").Where(u => u.User.Username == User.Identity.Name).ToList();
|
||||
if (pastes != null)
|
||||
{
|
||||
foreach (Paste.Models.Paste paste in pastes)
|
||||
{
|
||||
paste.UserId = null;
|
||||
db.Entry(paste).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
// Update shortened urls
|
||||
List<ShortenedUrl> shortUrls = db.ShortenedUrls.Include("User").Where(u => u.User.Username == User.Identity.Name).ToList();
|
||||
if (shortUrls != null)
|
||||
{
|
||||
foreach (ShortenedUrl shortUrl in shortUrls)
|
||||
{
|
||||
shortUrl.UserId = null;
|
||||
db.Entry(shortUrl).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Blogs
|
||||
Blog.Models.Blog blog = db.Blogs.Include("BlogPosts").Include("BlogPosts.Comments").Include("User").Where(u => u.User.Username == User.Identity.Name).FirstOrDefault();
|
||||
if (blog != null)
|
||||
{
|
||||
db.Blogs.Remove(blog);
|
||||
}
|
||||
|
||||
// Delete post comments
|
||||
List<BlogPostComment> postComments = db.BlogComments.Include("User").Where(u => u.User.Username == User.Identity.Name).ToList();
|
||||
if (postComments != null)
|
||||
{
|
||||
foreach (BlogPostComment postComment in postComments)
|
||||
{
|
||||
db.BlogComments.Remove(postComment);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete post comments
|
||||
List<Podcast.Models.PodcastComment> podComments = db.PodcastComments.Include("User").Where(u => u.User.Username == User.Identity.Name).ToList();
|
||||
if (podComments != null)
|
||||
{
|
||||
foreach (Podcast.Models.PodcastComment podComment in podComments)
|
||||
{
|
||||
db.PodcastComments.Remove(podComment);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete User
|
||||
User user = Utility.UserHelper.GetUser(db, User.Identity.Name);
|
||||
if (user != null)
|
||||
{
|
||||
user.UserSettings = db.UserSettings.Find(user.UserId);
|
||||
user.BlogSettings = db.BlogSettings.Find(user.UserId);
|
||||
user.UploadSettings = db.UploadSettings.Find(user.UserId);
|
||||
db.Users.Remove(user);
|
||||
db.SaveChanges();
|
||||
// Sign Out
|
||||
Logout();
|
||||
return Json(new { result = true });
|
||||
|
@ -1,12 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using Teknik.Areas.Blog.Models;
|
||||
using Teknik.Areas.Shortener.Models;
|
||||
using Teknik.Areas.Users.Models;
|
||||
using Teknik.Configuration;
|
||||
using Teknik.Helpers;
|
||||
using Teknik.Models;
|
||||
|
||||
namespace Teknik.Areas.Users.Utility
|
||||
@ -16,6 +22,12 @@ namespace Teknik.Areas.Users.Utility
|
||||
public static User GetUser(TeknikEntities db, string username)
|
||||
{
|
||||
User user = db.Users.Where(b => b.Username == username).FirstOrDefault();
|
||||
if (user != null)
|
||||
{
|
||||
user.UserSettings = db.UserSettings.Find(user.UserId);
|
||||
user.BlogSettings = db.BlogSettings.Find(user.UserId);
|
||||
user.UploadSettings = db.UploadSettings.Find(user.UserId);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
@ -31,6 +43,280 @@ namespace Teknik.Areas.Users.Utility
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void AddUser(TeknikEntities db, Config config, User user, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
|
||||
// If Email Server is enabled
|
||||
if (config.EmailConfig.Enabled)
|
||||
{
|
||||
// Connect to hmailserver COM
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
|
||||
|
||||
var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
|
||||
try
|
||||
{
|
||||
var account = domain.Accounts.ItemByAddress[email];
|
||||
throw new Exception("That email already exists.");
|
||||
}
|
||||
catch { }
|
||||
|
||||
// If we got an exception, then the email doesnt exist and we continue on!
|
||||
var newAccount = domain.Accounts.Add();
|
||||
newAccount.Address = email;
|
||||
newAccount.Password = password;
|
||||
newAccount.Active = true;
|
||||
newAccount.MaxSize = config.EmailConfig.MaxSize;
|
||||
|
||||
newAccount.Save();
|
||||
}
|
||||
|
||||
// If Git is enabled
|
||||
if (config.GitConfig.Enabled)
|
||||
{
|
||||
// Add gogs user
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
var obj = new { source_id = config.GitConfig.SourceId, username = user.Username, email = email, login_name = email, password = password };
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/json";
|
||||
Uri baseUri = new Uri(config.GitConfig.Host);
|
||||
Uri finalUri = new Uri(baseUri, "api/v1/admin/users?token=" + config.GitConfig.AccessToken);
|
||||
string result = client.UploadString(finalUri, "POST", json);
|
||||
}
|
||||
}
|
||||
|
||||
// Add User
|
||||
db.Users.Add(user);
|
||||
db.SaveChanges();
|
||||
|
||||
// Generate blog for the user
|
||||
var newBlog = db.Blogs.Create();
|
||||
newBlog.UserId = user.UserId;
|
||||
db.Blogs.Add(newBlog);
|
||||
db.SaveChanges();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to create user.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveUser(TeknikEntities db, Config config, User user, bool changePass, string newPass)
|
||||
{
|
||||
string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
|
||||
// Changing Password?
|
||||
if (changePass)
|
||||
{
|
||||
// Update Email Pass
|
||||
if (config.EmailConfig.Enabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
|
||||
var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
|
||||
var account = domain.Accounts.ItemByAddress[email];
|
||||
account.Password = newPass;
|
||||
account.Save();
|
||||
}
|
||||
catch (COMException)
|
||||
{ }
|
||||
}
|
||||
|
||||
// Update Git Pass
|
||||
if (config.GitConfig.Enabled)
|
||||
{
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
var obj = new { source_id = config.GitConfig.SourceId, email = email, password = newPass };
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/json";
|
||||
Uri baseUri = new Uri(config.GitConfig.Host);
|
||||
Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + user.Username + "?token=" + config.GitConfig.AccessToken);
|
||||
string result = client.UploadString(finalUri, "PATCH", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
db.Entry(user).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
public static void DeleteUser(TeknikEntities db, Config config, User user)
|
||||
{
|
||||
// Check to see if we need to delete their email.
|
||||
if (config.EmailConfig.Enabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delete Email
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
|
||||
var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
|
||||
var account = domain.Accounts.ItemByAddress[string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain)];
|
||||
if (account != null)
|
||||
{
|
||||
account.Delete();
|
||||
}
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to delete email account.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Git
|
||||
if (config.GitConfig.Enabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri baseUri = new Uri(config.GitConfig.Host);
|
||||
Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + user.Username + "?token=" + config.GitConfig.AccessToken);
|
||||
WebRequest request = WebRequest.Create(finalUri);
|
||||
request.Method = "DELETE";
|
||||
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (response.StatusCode != HttpStatusCode.NotFound && response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new Exception("Unable to delete git account. Response Code: " + response.StatusCode);
|
||||
}
|
||||
}
|
||||
catch (HttpException htex)
|
||||
{
|
||||
if (htex.GetHttpCode() != 404)
|
||||
throw new Exception("Unable to delete git account. Http Exception: " + htex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// This error signifies the user doesn't exist, so we can continue deleting
|
||||
if (ex.Message != "The remote server returned an error: (404) Not Found.")
|
||||
{
|
||||
throw new Exception("Unable to delete git account. Exception: " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update uploads
|
||||
List<Upload.Models.Upload> uploads = db.Uploads.Include("User").Where(u => u.User.Username == user.Username).ToList();
|
||||
if (uploads != null)
|
||||
{
|
||||
foreach (Upload.Models.Upload upload in uploads)
|
||||
{
|
||||
upload.UserId = null;
|
||||
db.Entry(upload).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
// Update pastes
|
||||
List<Paste.Models.Paste> pastes = db.Pastes.Include("User").Where(u => u.User.Username == user.Username).ToList();
|
||||
if (pastes != null)
|
||||
{
|
||||
foreach (Paste.Models.Paste paste in pastes)
|
||||
{
|
||||
paste.UserId = null;
|
||||
db.Entry(paste).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
// Update shortened urls
|
||||
List<ShortenedUrl> shortUrls = db.ShortenedUrls.Include("User").Where(u => u.User.Username == user.Username).ToList();
|
||||
if (shortUrls != null)
|
||||
{
|
||||
foreach (ShortenedUrl shortUrl in shortUrls)
|
||||
{
|
||||
shortUrl.UserId = null;
|
||||
db.Entry(shortUrl).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Blogs
|
||||
Blog.Models.Blog blog = db.Blogs.Include("BlogPosts").Include("BlogPosts.Comments").Include("User").Where(u => u.User.Username == user.Username).FirstOrDefault();
|
||||
if (blog != null)
|
||||
{
|
||||
db.Blogs.Remove(blog);
|
||||
}
|
||||
|
||||
// Delete post comments
|
||||
List<BlogPostComment> postComments = db.BlogComments.Include("User").Where(u => u.User.Username == user.Username).ToList();
|
||||
if (postComments != null)
|
||||
{
|
||||
foreach (BlogPostComment postComment in postComments)
|
||||
{
|
||||
db.BlogComments.Remove(postComment);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete post comments
|
||||
List<Podcast.Models.PodcastComment> podComments = db.PodcastComments.Include("User").Where(u => u.User.Username == user.Username).ToList();
|
||||
if (podComments != null)
|
||||
{
|
||||
foreach (Podcast.Models.PodcastComment podComment in podComments)
|
||||
{
|
||||
db.PodcastComments.Remove(podComment);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete User
|
||||
db.Users.Remove(user);
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
public static DateTime GetLastActivity(TeknikEntities db, Config config, User user)
|
||||
{
|
||||
DateTime lastActive = new DateTime(1900, 1, 1);
|
||||
string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
|
||||
|
||||
if (config.EmailConfig.Enabled)
|
||||
{
|
||||
// Connect to hmailserver COM
|
||||
var app = new hMailServer.Application();
|
||||
app.Connect();
|
||||
app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
|
||||
|
||||
try
|
||||
{
|
||||
var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
|
||||
var account = domain.Accounts.ItemByAddress[email];
|
||||
DateTime lastEmail = (DateTime)account.LastLogonTime;
|
||||
if (lastActive < lastEmail)
|
||||
lastActive = lastEmail;
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
}
|
||||
|
||||
if (config.GitConfig.Enabled)
|
||||
{
|
||||
// We need to check the actual git database
|
||||
MysqlDatabase mySQL = new MysqlDatabase(config.GitConfig.Database);
|
||||
string sql = @"SELECT MAX(gogs.repository.updated) AS LastUpdate
|
||||
FROM gogs.repository
|
||||
INNER JOIN gogs.user
|
||||
WHERE gogs.user.login_name = {0} AND gogs.user.id = gogs.repository.owner_id";
|
||||
object result = mySQL.ScalarQuery(sql, new object[] { email });
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
DateTime tmpLast = lastActive;
|
||||
DateTime.TryParse(result.ToString(), out tmpLast);
|
||||
if (lastActive < tmpLast)
|
||||
lastActive = tmpLast;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastActive < user.LastSeen)
|
||||
lastActive = user.LastSeen;
|
||||
|
||||
return lastActive;
|
||||
}
|
||||
|
||||
public static HttpCookie CreateAuthCookie(string username, bool remember, string domain, bool local)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
|
@ -73,7 +73,7 @@
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Joined</strong></span> <time datetime="@Model.LastSeen.ToString("o")">@Model.JoinDate.ToString("MMMM dd, yyyy")</time></li>
|
||||
@if (OwnProfile && User.Identity.IsAuthenticated)
|
||||
{
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Last Seen</strong></span> <time datetime="@Model.LastSeen.ToString("o")">@Model.LastSeen.ToString("MMMM dd, yyyy")</time></li>
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Last Seen</strong></span> <time datetime="@Model.LastSeen.ToString("o")">@Model.LastSeen.ToString("MMMM dd, yyyy hh:mm:ss")</time></li>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(pgpFingerprint))
|
||||
{
|
||||
|
@ -16,12 +16,15 @@ namespace Teknik.Configuration
|
||||
|
||||
public int SourceId { get; set; }
|
||||
|
||||
public DatabaseConfig Database { get; set; }
|
||||
|
||||
public GitConfig()
|
||||
{
|
||||
Enabled = true;
|
||||
Host = string.Empty;
|
||||
AccessToken = string.Empty;
|
||||
SourceId = 1;
|
||||
Database = new DatabaseConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -612,6 +612,7 @@
|
||||
<Folder Include="Areas\TOS\Views\TOS\" />
|
||||
<Folder Include="Areas\Transparency\Views\Shared\" />
|
||||
<Folder Include="Areas\Upload\Views\Shared\" />
|
||||
<Folder Include="Areas\User\Repositories\" />
|
||||
<Folder Include="Areas\User\Views\Shared\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user