1
0
mirror of https://git.teknik.io/Teknikode/Teknik.git synced 2023-08-02 14:16:22 +02:00

Added email and customer info to admin view

This commit is contained in:
Uncled1023 2022-08-14 17:32:48 -07:00
parent c4840e696d
commit 270615be90
20 changed files with 436 additions and 173 deletions

35
BillingService/Logger.cs Normal file
View File

@ -0,0 +1,35 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.BillingService
{
internal class Logger : ILogger
{
private readonly TextWriter _textWriter;
public Logger(TextWriter textWriter)
{
_textWriter = textWriter;
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
_textWriter.WriteLine($"[{logLevel}] {formatter(state, exception)}");
}
}
}

View File

@ -6,6 +6,7 @@ using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommandLine; using CommandLine;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Teknik.Areas.Billing; using Teknik.Areas.Billing;
using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Models;
using Teknik.Areas.Users.Utility; using Teknik.Areas.Users.Utility;
@ -13,6 +14,7 @@ using Teknik.BillingCore;
using Teknik.BillingCore.Models; using Teknik.BillingCore.Models;
using Teknik.Configuration; using Teknik.Configuration;
using Teknik.Data; using Teknik.Data;
using Teknik.MailService;
using Teknik.Utilities; using Teknik.Utilities;
namespace Teknik.BillingService namespace Teknik.BillingService
@ -25,6 +27,7 @@ namespace Teknik.BillingService
private static readonly object dbLock = new object(); private static readonly object dbLock = new object();
private static readonly object scanStatsLock = new object(); private static readonly object scanStatsLock = new object();
private static readonly ILogger logger = new Logger(Console.Out);
public static event Action<string> OutputEvent; public static event Action<string> OutputEvent;
@ -78,6 +81,9 @@ namespace Teknik.BillingService
// Get Biling Service // Get Biling Service
var billingService = BillingFactory.GetBillingService(config.BillingConfig); var billingService = BillingFactory.GetBillingService(config.BillingConfig);
// Get Mail Service
var mailService = UserHelper.CreateMailService(config, logger);
// Get all customers // Get all customers
var customers = billingService.GetCustomers(); var customers = billingService.GetCustomers();
if (customers != null) if (customers != null)
@ -114,7 +120,7 @@ namespace Teknik.BillingService
var emailPrice = subscriptions.SelectMany(s => s.Prices).FirstOrDefault(p => p.ProductId == config.BillingConfig.EmailProductId); var emailPrice = subscriptions.SelectMany(s => s.Prices).FirstOrDefault(p => p.ProductId == config.BillingConfig.EmailProductId);
if (emailPrice != null) if (emailPrice != null)
{ {
BillingHelper.SetEmailLimits(config, user, emailPrice.Storage, true); BillingHelper.SetEmailLimits(config, mailService, user, emailPrice.Storage, true);
} }
else else
{ {
@ -122,9 +128,9 @@ namespace Teknik.BillingService
var userInfo = await IdentityHelper.GetIdentityUserInfo(config, user.Username); var userInfo = await IdentityHelper.GetIdentityUserInfo(config, user.Username);
if (userInfo != null && if (userInfo != null &&
userInfo.AccountType == AccountType.Premium) userInfo.AccountType == AccountType.Premium)
BillingHelper.SetEmailLimits(config, user, config.EmailConfig.MaxSize, true); BillingHelper.SetEmailLimits(config, mailService, user, config.EmailConfig.MaxSize, true);
else else
BillingHelper.SetEmailLimits(config, user, config.EmailConfig.MaxSize, false); BillingHelper.SetEmailLimits(config, mailService, user, config.EmailConfig.MaxSize, false);
} }
} }
} }
@ -132,7 +138,7 @@ namespace Teknik.BillingService
public static void Output(string message) public static void Output(string message)
{ {
Console.WriteLine(message); logger.Log(LogLevel.Information, message);
if (OutputEvent != null) if (OutputEvent != null)
{ {
OutputEvent(message); OutputEvent(message);

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Teknik.MailService
{
public class EmptyMailService : IMailService
{
public bool AccountExists(string username)
{
throw new NotImplementedException();
}
public bool CreateAccount(string username, string password, long size)
{
throw new NotImplementedException();
}
public bool DeleteAccount(string username)
{
throw new NotImplementedException();
}
public bool DisableAccount(string username)
{
throw new NotImplementedException();
}
public bool EditMaxEmailsPerDay(string username, int maxPerDay)
{
throw new NotImplementedException();
}
public bool EditMaxSize(string username, long size)
{
throw new NotImplementedException();
}
public bool EditPassword(string username, string password)
{
throw new NotImplementedException();
}
public bool EnableAccount(string username)
{
throw new NotImplementedException();
}
public long GetMaxSize(string username)
{
throw new NotImplementedException();
}
public bool IsEnabled(string username)
{
throw new NotImplementedException();
}
public DateTime LastActive(string username)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,4 +1,5 @@
using System; using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@ -7,6 +8,7 @@ namespace Teknik.MailService
public class HMailService : IMailService public class HMailService : IMailService
{ {
private readonly hMailServer.Application _App; private readonly hMailServer.Application _App;
private readonly ILogger _logger;
private string _Host { get; set; } private string _Host { get; set; }
private string _Username { get; set; } private string _Username { get; set; }
@ -19,7 +21,16 @@ namespace Teknik.MailService
private string _CounterPassword { get; set; } private string _CounterPassword { get; set; }
private int _CounterPort { get; set; } private int _CounterPort { get; set; }
public HMailService(string host, string username, string password, string domain, string counterServer, string counterDatabase, string counterUsername, string counterPassword, int counterPort) public HMailService(string host,
string username,
string password,
string domain,
string counterServer,
string counterDatabase,
string counterUsername,
string counterPassword,
int counterPort,
ILogger logger)
{ {
_Host = host; _Host = host;
_Username = username; _Username = username;
@ -32,10 +43,11 @@ namespace Teknik.MailService
_CounterPassword = counterPassword; _CounterPassword = counterPassword;
_CounterPort = counterPort; _CounterPort = counterPort;
_logger = logger;
_App = InitApp(); _App = InitApp();
} }
public void CreateAccount(string username, string password, long size) public bool CreateAccount(string username, string password, long size)
{ {
var domain = _App.Domains.ItemByName[_Domain]; var domain = _App.Domains.ItemByName[_Domain];
var newAccount = domain.Accounts.Add(); var newAccount = domain.Accounts.Add();
@ -45,73 +57,92 @@ namespace Teknik.MailService
newAccount.MaxSize = (int)(size / 1000000); newAccount.MaxSize = (int)(size / 1000000);
newAccount.Save(); newAccount.Save();
return true;
} }
public bool AccountExists(string username) public bool AccountExists(string username)
{ {
try var account = GetAccount(username);
{ return account != null;
GetAccount(username);
// We didn't error out, so the email exists
return true;
}
catch { }
return false;
} }
public void DeleteAccount(string username) public bool DeleteAccount(string username)
{ {
var account = GetAccount(username); var account = GetAccount(username);
if (account != null) if (account != null)
{ {
account.Delete(); account.Delete();
return true;
} }
return false;
} }
public void EnableAccount(string username) public bool EnableAccount(string username)
{ {
EditActivity(username, true); return EditActivity(username, true);
} }
public void DisableAccount(string username) public bool DisableAccount(string username)
{ {
EditActivity(username, false); return EditActivity(username, false);
} }
public void EditActivity(string username, bool active) public bool EditActivity(string username, bool active)
{ {
var account = GetAccount(username); var account = GetAccount(username);
account.Active = active; if (account != null)
account.Save(); {
account.Active = active;
account.Save();
return true;
}
return false;
} }
public void EditMaxEmailsPerDay(string username, int maxPerDay) public bool EditMaxEmailsPerDay(string username, int maxPerDay)
{ {
//We need to check the actual git database //We need to check the actual git database
MysqlDatabase mySQL = new MysqlDatabase(_CounterServer, _CounterDatabase, _CounterUsername, _CounterPassword, _CounterPort); MysqlDatabase mySQL = new MysqlDatabase(_CounterServer, _CounterDatabase, _CounterUsername, _CounterPassword, _CounterPort);
string sql = @"INSERT INTO mailcounter.counts (qname, lastdate, qlimit, count) VALUES ({1}, NOW(), {0}, 0) string sql = @"INSERT INTO mailcounter.counts (qname, lastdate, qlimit, count) VALUES ({1}, NOW(), {0}, 0)
ON DUPLICATE KEY UPDATE qlimit = {0}"; ON DUPLICATE KEY UPDATE qlimit = {0}";
mySQL.Execute(sql, new object[] { maxPerDay, username }); mySQL.Execute(sql, new object[] { maxPerDay, username });
return true;
} }
public void EditMaxSize(string username, long size) public long GetMaxSize(string username)
{ {
var account = GetAccount(username); var account = GetAccount(username);
account.MaxSize = (int)(size / 1000000); return account?.MaxSize ?? 0;
account.Save();
} }
public void EditPassword(string username, string password) public bool EditMaxSize(string username, long size)
{ {
var account = GetAccount(username); var account = GetAccount(username);
account.Password = password; if (account != null)
account.Save(); {
account.MaxSize = (int)(size / 1000000);
account.Save();
return true;
}
return false;
}
public bool EditPassword(string username, string password)
{
var account = GetAccount(username);
if (account != null)
{
account.Password = password;
account.Save();
return true;
}
return false;
} }
public DateTime LastActive(string username) public DateTime LastActive(string username)
{ {
var account = GetAccount(username); var account = GetAccount(username);
return (DateTime)account.LastLogonTime; return (DateTime)(account?.LastLogonTime ?? DateTime.MinValue);
} }
private hMailServer.Application InitApp() private hMailServer.Application InitApp()
@ -125,14 +156,22 @@ namespace Teknik.MailService
private hMailServer.Account GetAccount(string username) private hMailServer.Account GetAccount(string username)
{ {
var domain = _App.Domains.ItemByName[_Domain]; try
return domain.Accounts.ItemByAddress[username]; {
var domain = _App.Domains.ItemByName[_Domain];
return domain.Accounts.ItemByAddress[username];
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred getting Email Account");
}
return null;
} }
public bool Enabled(string username) public bool IsEnabled(string username)
{ {
var account = GetAccount(username); var account = GetAccount(username);
return account.Active; return account?.Active ?? false;
} }
} }
} }

View File

@ -8,20 +8,22 @@ namespace Teknik.MailService
DateTime LastActive(string username); DateTime LastActive(string username);
bool Enabled(string username); bool IsEnabled(string username);
void CreateAccount(string username, string password, long size); bool CreateAccount(string username, string password, long size);
void EditPassword(string username, string password); bool EditPassword(string username, string password);
void EditMaxSize(string username, long size); long GetMaxSize(string username);
void EditMaxEmailsPerDay(string username, int maxPerDay); bool EditMaxSize(string username, long size);
void EnableAccount(string username); bool EditMaxEmailsPerDay(string username, int maxPerDay);
void DisableAccount(string username); bool EnableAccount(string username);
void DeleteAccount(string username); bool DisableAccount(string username);
bool DeleteAccount(string username);
} }
} }

View File

@ -8,6 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
<PackageReference Include="MySql.Data" Version="8.0.29" /> <PackageReference Include="MySql.Data" Version="8.0.29" />
</ItemGroup> </ItemGroup>

View File

@ -2,6 +2,7 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using nClam; using nClam;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -159,8 +160,8 @@ namespace Teknik.ServiceWorker
// If the IV is set, and Key is set, then scan it // If the IV is set, and Key is set, then scan it
if (!string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV)) if (!string.IsNullOrEmpty(upload.Key) && !string.IsNullOrEmpty(upload.IV))
{ {
byte[] keyBytes = Encoding.UTF8.GetBytes(upload.Key); var keyArray = new PooledArray(Encoding.UTF8.GetBytes(upload.Key));
byte[] ivBytes = Encoding.UTF8.GetBytes(upload.IV); var ivArray = new PooledArray(Encoding.UTF8.GetBytes(upload.IV));
long maxUploadSize = config.UploadConfig.MaxUploadFileSize; long maxUploadSize = config.UploadConfig.MaxUploadFileSize;
@ -171,7 +172,7 @@ namespace Teknik.ServiceWorker
maxUploadSize = upload.User.UploadSettings.MaxUploadFileSize.Value; maxUploadSize = upload.User.UploadSettings.MaxUploadFileSize.Value;
} }
using (AesCounterStream aesStream = new AesCounterStream(fileStream, false, keyBytes, ivBytes)) using (AesCounterStream aesStream = new AesCounterStream(fileStream, false, keyArray, ivArray))
{ {
ClamClient clam = new ClamClient(config.UploadConfig.ClamConfig.Server, config.UploadConfig.ClamConfig.Port); ClamClient clam = new ClamClient(config.UploadConfig.ClamConfig.Server, config.UploadConfig.ClamConfig.Port);
clam.MaxStreamSize = maxUploadSize; clam.MaxStreamSize = maxUploadSize;

View File

@ -14,6 +14,7 @@ using Teknik.BillingCore.Models;
using Teknik.Configuration; using Teknik.Configuration;
using Teknik.Data; using Teknik.Data;
using Teknik.Logging; using Teknik.Logging;
using Teknik.MailService;
namespace Teknik.Areas.API.V1.Controllers namespace Teknik.Areas.API.V1.Controllers
{ {
@ -21,7 +22,7 @@ namespace Teknik.Areas.API.V1.Controllers
{ {
public BillingAPIv1Controller(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } public BillingAPIv1Controller(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
public async Task<IActionResult> HandleCheckoutCompleteEvent() public async Task<IActionResult> HandleCheckoutCompleteEvent([FromServices] IMailService mailService)
{ {
if (!_config.BillingConfig.Enabled) if (!_config.BillingConfig.Enabled)
return Forbid(); return Forbid();
@ -38,13 +39,13 @@ namespace Teknik.Areas.API.V1.Controllers
{ {
var subscription = billingService.GetSubscription(session.SubscriptionId); var subscription = billingService.GetSubscription(session.SubscriptionId);
BillingHelper.ProcessSubscription(_config, _dbContext, session.CustomerId, subscription); BillingHelper.ProcessSubscription(_config, _dbContext, mailService, session.CustomerId, subscription);
} }
return Ok(); return Ok();
} }
public async Task<IActionResult> HandleSubscriptionChange() public async Task<IActionResult> HandleSubscriptionChange([FromServices] IMailService mailService)
{ {
if (!_config.BillingConfig.Enabled) if (!_config.BillingConfig.Enabled)
return Forbid(); return Forbid();
@ -60,7 +61,7 @@ namespace Teknik.Areas.API.V1.Controllers
if (subscriptionEvent == null) if (subscriptionEvent == null)
return BadRequest(); return BadRequest();
BillingHelper.ProcessSubscription(_config, _dbContext, subscriptionEvent.CustomerId, subscriptionEvent); BillingHelper.ProcessSubscription(_config, _dbContext, mailService, subscriptionEvent.CustomerId, subscriptionEvent);
return Ok(); return Ok();
} }

View File

@ -18,6 +18,7 @@ using Teknik.ViewModels;
using Teknik.Logging; using Teknik.Logging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Teknik.MailService;
namespace Teknik.Areas.Admin.Controllers namespace Teknik.Areas.Admin.Controllers
{ {
@ -45,7 +46,7 @@ namespace Teknik.Areas.Admin.Controllers
[HttpGet] [HttpGet]
[TrackPageView] [TrackPageView]
public async Task<IActionResult> UserInfo(string username) public async Task<IActionResult> UserInfo(string username, [FromServices] IMailService mailService)
{ {
if (UserHelper.UserExists(_dbContext, username)) if (UserHelper.UserExists(_dbContext, username))
{ {
@ -59,6 +60,13 @@ namespace Teknik.Areas.Admin.Controllers
model.AccountType = info.AccountType.Value; model.AccountType = info.AccountType.Value;
if (info.AccountStatus.HasValue) if (info.AccountStatus.HasValue)
model.AccountStatus = info.AccountStatus.Value; model.AccountStatus = info.AccountStatus.Value;
var email = UserHelper.GetUserEmailAddress(_config, username);
if (UserHelper.UserEmailExists(mailService, _config, email))
model.Email = email;
model.EmailEnabled = UserHelper.UserEmailEnabled(mailService, _config, email);
model.MaxEmailStorage = UserHelper.GetUserEmailMaxSize(mailService, _config, email);
return View(model); return View(model);
} }
return new StatusCodeResult(StatusCodes.Status404NotFound); return new StatusCodeResult(StatusCodes.Status404NotFound);
@ -89,11 +97,12 @@ namespace Teknik.Areas.Admin.Controllers
} }
[HttpPost] [HttpPost]
public async Task<IActionResult> GetUserSearchResults(string query, [FromServices] ICompositeViewEngine viewEngine) public async Task<IActionResult> GetUserSearchResults(string query, [FromServices] ICompositeViewEngine viewEngine, [FromServices] IMailService mailService)
{ {
List<UserResultViewModel> models = new List<UserResultViewModel>(); List<UserResultViewModel> models = new List<UserResultViewModel>();
var results = _dbContext.Users.Where(u => u.Username.Contains(query)).ToList(); var results = _dbContext.Users.Where(u => u.Username.Contains(query) ||
(u.BillingCustomer != null && u.BillingCustomer.CustomerId == query)).ToList();
if (results != null) if (results != null)
{ {
foreach (User user in results) foreach (User user in results)
@ -110,7 +119,7 @@ namespace Teknik.Areas.Admin.Controllers
if (info.CreationDate.HasValue) if (info.CreationDate.HasValue)
model.JoinDate = info.CreationDate.Value; model.JoinDate = info.CreationDate.Value;
model.LastSeen = await UserHelper.GetLastAccountActivity(_dbContext, _config, user.Username); model.LastSeen = await UserHelper.GetLastAccountActivity(_dbContext, _config, mailService, user.Username);
models.Add(model); models.Add(model);
} }
catch (Exception) catch (Exception)
@ -192,12 +201,12 @@ namespace Teknik.Areas.Admin.Controllers
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> EditUserAccountType(string username, AccountType accountType) public async Task<IActionResult> EditUserAccountType(string username, AccountType accountType, [FromServices] IMailService mailService)
{ {
if (UserHelper.UserExists(_dbContext, username)) if (UserHelper.UserExists(_dbContext, username))
{ {
// Edit the user's account type // Edit the user's account type
await UserHelper.EditAccountType(_dbContext, _config, username, accountType); await UserHelper.EditAccountType(_dbContext, _config, mailService, username, accountType);
return Json(new { result = new { success = true } }); return Json(new { result = new { success = true } });
} }
return new StatusCodeResult(StatusCodes.Status404NotFound); return new StatusCodeResult(StatusCodes.Status404NotFound);
@ -205,12 +214,28 @@ namespace Teknik.Areas.Admin.Controllers
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> EditUserAccountStatus(string username, AccountStatus accountStatus) public async Task<IActionResult> EditUserAccountStatus(string username, AccountStatus accountStatus, [FromServices] IMailService mailService)
{ {
if (UserHelper.UserExists(_dbContext, username)) if (UserHelper.UserExists(_dbContext, username))
{ {
// Edit the user's account type // Edit the user's account type
await UserHelper.EditAccountStatus(_dbContext, _config, username, accountStatus); await UserHelper.EditAccountStatus(_dbContext, _config, mailService, username, accountStatus);
return Json(new { result = new { success = true } });
}
return new StatusCodeResult(StatusCodes.Status404NotFound);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult EditEmailActive(string username, string active, [FromServices] IMailService mailService)
{
if (UserHelper.UserExists(_dbContext, username))
{
var email = UserHelper.GetUserEmailAddress(_config, username);
if (active == "Enabled")
UserHelper.EnableUserEmail(mailService, _config, email);
else
UserHelper.DisableUserEmail(mailService, _config, email);
return Json(new { result = new { success = true } }); return Json(new { result = new { success = true } });
} }
return new StatusCodeResult(StatusCodes.Status404NotFound); return new StatusCodeResult(StatusCodes.Status404NotFound);
@ -241,14 +266,14 @@ namespace Teknik.Areas.Admin.Controllers
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteAccount(string username) public async Task<IActionResult> DeleteAccount(string username, [FromServices] IMailService mailService)
{ {
try try
{ {
User user = UserHelper.GetUser(_dbContext, username); User user = UserHelper.GetUser(_dbContext, username);
if (user != null) if (user != null)
{ {
await UserHelper.DeleteAccount(_dbContext, _config, user); await UserHelper.DeleteAccount(_dbContext, _config, mailService, user);
return Json(new { result = true }); return Json(new { result = true });
} }
} }

View File

@ -12,5 +12,8 @@ namespace Teknik.Areas.Admin.ViewModels
public string Username { get; set; } public string Username { get; set; }
public AccountType AccountType { get; set; } public AccountType AccountType { get; set; }
public AccountStatus AccountStatus { get; set; } public AccountStatus AccountStatus { get; set; }
public string Email { get; set; }
public bool EmailEnabled { get; set; }
public long MaxEmailStorage { get; set; }
} }
} }

View File

@ -6,6 +6,7 @@
var deleteUserURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "DeleteAccount" })'; var deleteUserURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "DeleteAccount" })';
var editAccountType = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountType" })'; var editAccountType = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountType" })';
var editAccountStatus = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountStatus" })'; var editAccountStatus = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountStatus" })';
var editEmailActive = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditEmailActive" })';
var createInviteCode = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "CreateInviteCode" })'; var createInviteCode = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "CreateInviteCode" })';
var username = '@Model.Username'; var username = '@Model.Username';
</script> </script>
@ -52,6 +53,36 @@
</div> </div>
</div> </div>
<br /> <br />
<div class="row">
<div class="col-sm-2 col-sm-offset-1">
Email:
</div>
<div class="col-sm-8">
@Model.Email
</div>
</div>
<br />
<div class="row">
<div class="col-sm-2 col-sm-offset-1">
Email Active:
</div>
<div class="col-sm-8">
<select class="userEmailActive">
<!option @(Model.EmailEnabled ? "selected" : string.Empty)>Enabled</!option>
<!option @(!Model.EmailEnabled ? "selected" : string.Empty)>Disabled</!option>
</select>
</div>
</div>
<br />
<div class="row">
<div class="col-sm-2 col-sm-offset-1">
Email Max Size:
</div>
<div class="col-sm-8">
<input class="emailMaxSize" value="@Model.MaxEmailStorage" />
</div>
</div>
<br />
<div class="row"> <div class="row">
<div class="col-sm-2 col-sm-offset-1"> <div class="col-sm-2 col-sm-offset-1">
<button type="button" class="btn btn-info" id="createInviteCode">Create Invite Code</button> <button type="button" class="btn btn-info" id="createInviteCode">Create Invite Code</button>

View File

@ -10,7 +10,7 @@
<div class="col-sm-6 col-sm-offset-3"> <div class="col-sm-6 col-sm-offset-3">
<!form> <!form>
<div class="form-group center-block"> <div class="form-group center-block">
<input type="text" class="form-control" id="query" name="query" placeholder="Username" /> <input type="text" class="form-control" id="query" name="query" placeholder="Username/Customer ID" />
</div> </div>
</!form> </!form>
</div> </div>

View File

@ -6,6 +6,7 @@ using Teknik.BillingCore;
using Teknik.BillingCore.Models; using Teknik.BillingCore.Models;
using Teknik.Configuration; using Teknik.Configuration;
using Teknik.Data; using Teknik.Data;
using Teknik.MailService;
namespace Teknik.Areas.Billing namespace Teknik.Areas.Billing
{ {
@ -41,7 +42,7 @@ namespace Teknik.Areas.Billing
} }
} }
public static void ProcessSubscription(Config config, TeknikEntities db, string customerId, Subscription subscription) public static void ProcessSubscription(Config config, TeknikEntities db, IMailService mailService, string customerId, Subscription subscription)
{ {
// They have paid, so let's get their subscription and update their user settings // They have paid, so let's get their subscription and update their user settings
var user = db.Users.FirstOrDefault(u => u.BillingCustomer != null && var user = db.Users.FirstOrDefault(u => u.BillingCustomer != null &&
@ -51,12 +52,12 @@ namespace Teknik.Areas.Billing
var isActive = subscription.Status == SubscriptionStatus.Active; var isActive = subscription.Status == SubscriptionStatus.Active;
foreach (var price in subscription.Prices) foreach (var price in subscription.Prices)
{ {
ProcessPrice(config, db, user, price, isActive); ProcessPrice(config, db, mailService, user, price, isActive);
} }
} }
} }
public static void ProcessPrice(Config config, TeknikEntities db, User user, Price price, bool active) public static void ProcessPrice(Config config, TeknikEntities db, IMailService mailService, User user, Price price, bool active)
{ {
// What type of subscription is this // What type of subscription is this
if (config.BillingConfig.UploadProductId == price.ProductId) if (config.BillingConfig.UploadProductId == price.ProductId)
@ -68,7 +69,7 @@ namespace Teknik.Areas.Billing
} }
else if (config.BillingConfig.EmailProductId == price.ProductId) else if (config.BillingConfig.EmailProductId == price.ProductId)
{ {
SetEmailLimits(config, user, price.Storage, active); SetEmailLimits(config, mailService, user, price.Storage, active);
} }
} }
@ -81,18 +82,18 @@ namespace Teknik.Areas.Billing
db.SaveChanges(); db.SaveChanges();
} }
public static void SetEmailLimits(Config config, User user, long storage, bool active) public static void SetEmailLimits(Config config, IMailService mailService, User user, long storage, bool active)
{ {
// Process an email subscription // Process an email subscription
string email = UserHelper.GetUserEmailAddress(config, user.Username); string email = UserHelper.GetUserEmailAddress(config, user.Username);
if (active) if (active)
{ {
UserHelper.EnableUserEmail(config, email); UserHelper.EnableUserEmail(mailService, config, email);
UserHelper.EditUserEmailMaxSize(config, email, storage); UserHelper.EditUserEmailMaxSize(mailService, config, email, storage);
} }
else else
{ {
UserHelper.DisableUserEmail(config, email); UserHelper.DisableUserEmail(mailService, config, email);
} }
} }
} }

View File

@ -10,6 +10,8 @@ using Teknik.Data;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Teknik.Logging; using Teknik.Logging;
using Teknik.Areas.Users.Utility;
using Teknik.MailService;
namespace Teknik.Areas.Contact.Controllers namespace Teknik.Areas.Contact.Controllers
{ {
@ -21,12 +23,23 @@ namespace Teknik.Areas.Contact.Controllers
[AllowAnonymous] [AllowAnonymous]
[TrackPageView] [TrackPageView]
public IActionResult Index() public IActionResult Index([FromServices] IMailService mailService)
{ {
ViewBag.Title = "Contact Us"; ViewBag.Title = "Contact Us";
ViewBag.Description = "Contact Teknik Support"; ViewBag.Description = "Contact Teknik Support";
var model = new ContactViewModel();
return View(new ContactViewModel()); if (User.Identity.IsAuthenticated)
{
model.Name = User.Identity.Name;
var email = UserHelper.GetUserEmailAddress(_config, User.Identity.Name);
if (UserHelper.UserEmailEnabled(mailService, _config, email))
{
model.Email = email;
}
}
return View(model);
} }
[HttpPost] [HttpPost]

View File

@ -1,22 +1,5 @@
@model Teknik.Areas.Contact.ViewModels.ContactViewModel @model Teknik.Areas.Contact.ViewModels.ContactViewModel
@using Teknik.Areas.Users.Utility
@{
string username = string.Empty;
string email = string.Empty;
if (User.Identity.IsAuthenticated)
{
username = User.Identity.Name;
if (UserHelper.UserEmailEnabled(Config, UserHelper.GetUserEmailAddress(Config, username)))
{
email = UserHelper.GetUserEmailAddress(Config, username);
}
}
}
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-sm-12 col-lg-12"> <div class="col-sm-12 col-lg-12">
@ -39,7 +22,7 @@
<label for="Name"> <label for="Name">
Name Name
</label> </label>
<input type="text" class="form-control" id="Name" name="Name" placeholder="Enter name" required="required" value="@username" /> <input type="text" class="form-control" id="Name" name="Name" placeholder="Enter name" required="required" value="@Model.Name" />
</div> </div>
<div class="form-group"> <div class="form-group">
@Html.ValidationMessageFor(u => u.Email) @Html.ValidationMessageFor(u => u.Email)
@ -50,7 +33,7 @@
<span class="input-group-addon"> <span class="input-group-addon">
<span class="fa fa-envelope"></span> <span class="fa fa-envelope"></span>
</span> </span>
<input type="email" class="form-control" id="Email" name="Email" placeholder="Enter email" required="required" value="@email" /> <input type="email" class="form-control" id="Email" name="Email" placeholder="Enter email" required="required" value="@Model.Email" />
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -25,6 +25,7 @@ using Microsoft.AspNetCore.Http;
using IdentityServer4.Models; using IdentityServer4.Models;
using Teknik.Utilities.Routing; using Teknik.Utilities.Routing;
using Teknik.BillingCore; using Teknik.BillingCore;
using Teknik.MailService;
namespace Teknik.Areas.Users.Controllers namespace Teknik.Areas.Users.Controllers
{ {
@ -51,11 +52,11 @@ namespace Teknik.Areas.Users.Controllers
} }
[HttpGet] [HttpGet]
public IActionResult Login(string returnUrl) public IActionResult Login(string returnUrl, [FromServices] IMailService mailService)
{ {
// Let's double check their email and git accounts to make sure they exist // Let's double check their email and git accounts to make sure they exist
string email = UserHelper.GetUserEmailAddress(_config, User.Identity.Name); string email = UserHelper.GetUserEmailAddress(_config, User.Identity.Name);
if (_config.EmailConfig.Enabled && !UserHelper.UserEmailExists(_config, email)) if (_config.EmailConfig.Enabled && !UserHelper.UserEmailExists(mailService, _config, email))
{ {
//UserHelper.AddUserEmail(_config, email, model.Password); //UserHelper.AddUserEmail(_config, email, model.Password);
} }
@ -102,7 +103,7 @@ namespace Teknik.Areas.Users.Controllers
[HttpOptions] [HttpOptions]
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
public async Task<IActionResult> Register([Bind(Prefix = "Register")]RegisterViewModel model) public async Task<IActionResult> Register([Bind(Prefix = "Register")]RegisterViewModel model, [FromServices] IMailService mailService)
{ {
model.Error = false; model.Error = false;
model.ErrorMessage = string.Empty; model.ErrorMessage = string.Empty;
@ -115,7 +116,7 @@ namespace Teknik.Areas.Users.Controllers
model.Error = true; model.Error = true;
model.ErrorMessage = "That username is not valid"; model.ErrorMessage = "That username is not valid";
} }
if (!model.Error && !(await UserHelper.UsernameAvailable(_dbContext, _config, model.Username))) if (!model.Error && !(await UserHelper.UsernameAvailable(_dbContext, _config, mailService, model.Username)))
{ {
model.Error = true; model.Error = true;
model.ErrorMessage = "That username is not available"; model.ErrorMessage = "That username is not available";
@ -152,7 +153,7 @@ namespace Teknik.Areas.Users.Controllers
{ {
try try
{ {
await UserHelper.CreateAccount(_dbContext, _config, Url, model.Username, model.Password, model.RecoveryEmail, model.InviteCode); await UserHelper.CreateAccount(_dbContext, _config, mailService, Url, model.Username, model.Password, model.RecoveryEmail, model.InviteCode);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -184,7 +185,7 @@ namespace Teknik.Areas.Users.Controllers
// GET: Profile/Profile // GET: Profile/Profile
[AllowAnonymous] [AllowAnonymous]
[TrackPageView] [TrackPageView]
public async Task<IActionResult> ViewProfile(string username) public async Task<IActionResult> ViewProfile(string username, [FromServices] IMailService mailService)
{ {
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))
{ {
@ -208,13 +209,15 @@ namespace Teknik.Areas.Users.Controllers
model.Username = user.Username; model.Username = user.Username;
if (_config.EmailConfig.Enabled) if (_config.EmailConfig.Enabled)
{ {
model.Email = string.Format("{0}@{1}", user.Username, _config.EmailConfig.Domain); var email = UserHelper.GetUserEmailAddress(_config, user.Username);
if (UserHelper.UserEmailEnabled(mailService, _config, email))
model.Email = email;
} }
// Get the user claims for this user // Get the user claims for this user
model.IdentityUserInfo = await IdentityHelper.GetIdentityUserInfo(_config, user.Username); model.IdentityUserInfo = await IdentityHelper.GetIdentityUserInfo(_config, user.Username);
model.LastSeen = UserHelper.GetLastAccountActivity(_dbContext, _config, user.Username, model.IdentityUserInfo); model.LastSeen = UserHelper.GetLastAccountActivity(_dbContext, _config, mailService, user.Username, model.IdentityUserInfo);
model.UserSettings = user.UserSettings; model.UserSettings = user.UserSettings;
model.BlogSettings = user.BlogSettings; model.BlogSettings = user.BlogSettings;
@ -745,7 +748,7 @@ namespace Teknik.Areas.Users.Controllers
return Json(new { error = "Invalid Parameters" }); return Json(new { error = "Invalid Parameters" });
} }
public async Task<IActionResult> ChangePassword(AccountSettingsViewModel settings) public async Task<IActionResult> ChangePassword(AccountSettingsViewModel settings, [FromServices] IMailService mailService)
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
@ -775,7 +778,7 @@ namespace Teknik.Areas.Users.Controllers
return Json(new { error = "Password resets are disabled" }); return Json(new { error = "Password resets are disabled" });
// Change their password // Change their password
await UserHelper.ChangeAccountPassword(_dbContext, _config, user.Username, settings.CurrentPassword, settings.NewPassword); await UserHelper.ChangeAccountPassword(_dbContext, _config, mailService, user.Username, settings.CurrentPassword, settings.NewPassword);
return Json(new { result = true }); return Json(new { result = true });
} }
@ -791,7 +794,7 @@ namespace Teknik.Areas.Users.Controllers
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> Delete() public async Task<IActionResult> Delete([FromServices] IMailService mailService)
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
@ -800,7 +803,7 @@ namespace Teknik.Areas.Users.Controllers
User user = UserHelper.GetUser(_dbContext, User.Identity.Name); User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
if (user != null) if (user != null)
{ {
await UserHelper.DeleteAccount(_dbContext, _config, user); await UserHelper.DeleteAccount(_dbContext, _config, mailService, user);
// Sign Out // Sign Out
await HttpContext.SignOutAsync("Cookies"); await HttpContext.SignOutAsync("Cookies");
@ -945,7 +948,7 @@ namespace Teknik.Areas.Users.Controllers
[HttpPost] [HttpPost]
[AllowAnonymous] [AllowAnonymous]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> SetUserPassword(SetPasswordViewModel passwordViewModel) public async Task<IActionResult> SetUserPassword(SetPasswordViewModel passwordViewModel, [FromServices] IMailService mailService)
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
@ -973,7 +976,7 @@ namespace Teknik.Areas.Users.Controllers
try try
{ {
await UserHelper.ResetAccountPassword(_dbContext, _config, username, code, passwordViewModel.Password); await UserHelper.ResetAccountPassword(_dbContext, _config, mailService, username, code, passwordViewModel.Password);
_session.Remove(_AuthSessionKey); _session.Remove(_AuthSessionKey);
_session.Remove("AuthCode"); _session.Remove("AuthCode");

View File

@ -33,6 +33,7 @@ using Newtonsoft.Json.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Teknik.Utilities.Routing; using Teknik.Utilities.Routing;
using Microsoft.Extensions.Logging;
namespace Teknik.Areas.Users.Utility namespace Teknik.Areas.Users.Utility
{ {
@ -81,7 +82,7 @@ namespace Teknik.Areas.Users.Utility
return isValid; return isValid;
} }
public static async Task<bool> UsernameAvailable(TeknikEntities db, Config config, string username) public static async Task<bool> UsernameAvailable(TeknikEntities db, Config config, IMailService mailService, string username)
{ {
bool isAvailable = true; bool isAvailable = true;
@ -89,27 +90,27 @@ namespace Teknik.Areas.Users.Utility
isAvailable &= !UsernameReserved(config, username); isAvailable &= !UsernameReserved(config, username);
isAvailable &= !await IdentityHelper.UserExists(config, username); isAvailable &= !await IdentityHelper.UserExists(config, username);
isAvailable &= !UserExists(db, username); isAvailable &= !UserExists(db, username);
isAvailable &= !UserEmailExists(config, GetUserEmailAddress(config, username)); isAvailable &= !UserEmailExists(mailService, config, GetUserEmailAddress(config, username));
isAvailable &= !UserGitExists(config, username); isAvailable &= !UserGitExists(config, username);
return isAvailable; return isAvailable;
} }
public static async Task<DateTime> GetLastAccountActivity(TeknikEntities db, Config config, string username) public static async Task<DateTime> GetLastAccountActivity(TeknikEntities db, Config config, IMailService mailService, string username)
{ {
var userInfo = await IdentityHelper.GetIdentityUserInfo(config, username); var userInfo = await IdentityHelper.GetIdentityUserInfo(config, username);
return GetLastAccountActivity(db, config, username, userInfo); return GetLastAccountActivity(db, config, mailService, username, userInfo);
} }
public static DateTime GetLastAccountActivity(TeknikEntities db, Config config, string username, IdentityUserInfo userInfo) public static DateTime GetLastAccountActivity(TeknikEntities db, Config config, IMailService mailService, string username, IdentityUserInfo userInfo)
{ {
try try
{ {
DateTime lastActive = new DateTime(1900, 1, 1); DateTime lastActive = new DateTime(1900, 1, 1);
if (UserEmailExists(config, GetUserEmailAddress(config, username))) if (UserEmailExists(mailService, config, GetUserEmailAddress(config, username)))
{ {
DateTime emailLastActive = UserEmailLastActive(config, GetUserEmailAddress(config, username)); DateTime emailLastActive = UserEmailLastActive(mailService, config, GetUserEmailAddress(config, username));
if (lastActive < emailLastActive) if (lastActive < emailLastActive)
lastActive = emailLastActive; lastActive = emailLastActive;
} }
@ -136,7 +137,7 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static async Task CreateAccount(TeknikEntities db, Config config, IUrlHelper url, string username, string password, string recoveryEmail, string inviteCode) public static async Task CreateAccount(TeknikEntities db, Config config, IMailService mailService, IUrlHelper url, string username, string password, string recoveryEmail, string inviteCode)
{ {
try try
{ {
@ -147,10 +148,10 @@ namespace Teknik.Areas.Users.Utility
string userId = (string)result.Data; string userId = (string)result.Data;
// Create an Email Account // Create an Email Account
CreateUserEmail(config, GetUserEmailAddress(config, username), password); CreateUserEmail(mailService, config, GetUserEmailAddress(config, username), password);
// Disable the email account // Disable the email account
DisableUserEmail(config, GetUserEmailAddress(config, username)); DisableUserEmail(mailService, config, GetUserEmailAddress(config, username));
// Create a Git Account // Create a Git Account
CreateUserGit(config, username, password, userId); CreateUserGit(config, username, password, userId);
@ -189,12 +190,12 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static async Task ChangeAccountPassword(TeknikEntities db, Config config, string username, string currentPassword, string newPassword) public static async Task ChangeAccountPassword(TeknikEntities db, Config config, IMailService mailService, string username, string currentPassword, string newPassword)
{ {
IdentityResult result = await IdentityHelper.UpdatePassword(config, username, currentPassword, newPassword); IdentityResult result = await IdentityHelper.UpdatePassword(config, username, currentPassword, newPassword);
if (result.Success) if (result.Success)
{ {
ChangeServicePasswords(db, config, username, newPassword); ChangeServicePasswords(db, config, mailService, username, newPassword);
} }
else else
{ {
@ -202,12 +203,12 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static async Task ResetAccountPassword(TeknikEntities db, Config config, string username, string token, string newPassword) public static async Task ResetAccountPassword(TeknikEntities db, Config config, IMailService mailService, string username, string token, string newPassword)
{ {
IdentityResult result = await IdentityHelper.ResetPassword(config, username, token, newPassword); IdentityResult result = await IdentityHelper.ResetPassword(config, username, token, newPassword);
if (result.Success) if (result.Success)
{ {
ChangeServicePasswords(db, config, username, newPassword); ChangeServicePasswords(db, config, mailService, username, newPassword);
} }
else else
{ {
@ -215,16 +216,16 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static void ChangeServicePasswords(TeknikEntities db, Config config, string username, string newPassword) public static void ChangeServicePasswords(TeknikEntities db, Config config, IMailService mailService, string username, string newPassword)
{ {
try try
{ {
// Make sure they have a git and email account before resetting their password // Make sure they have a git and email account before resetting their password
string email = GetUserEmailAddress(config, username); string email = GetUserEmailAddress(config, username);
if (config.EmailConfig.Enabled && UserEmailExists(config, email)) if (config.EmailConfig.Enabled && UserEmailExists(mailService, config, email))
{ {
// Change email password // Change email password
EditUserEmailPassword(config, GetUserEmailAddress(config, username), newPassword); EditUserEmailPassword(mailService, config, GetUserEmailAddress(config, username), newPassword);
} }
if (config.GitConfig.Enabled && UserGitExists(config, username)) if (config.GitConfig.Enabled && UserGitExists(config, username))
@ -239,7 +240,7 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static async Task EditAccountType(TeknikEntities db, Config config, string username, AccountType type) public static async Task EditAccountType(TeknikEntities db, Config config, IMailService mailService, string username, AccountType type)
{ {
try try
{ {
@ -257,11 +258,11 @@ namespace Teknik.Areas.Users.Utility
{ {
case AccountType.Basic: case AccountType.Basic:
// Disable their email // Disable their email
DisableUserEmail(config, email); DisableUserEmail(mailService, config, email);
break; break;
case AccountType.Premium: case AccountType.Premium:
// Enable their email account // Enable their email account
EnableUserEmail(config, email); EnableUserEmail(mailService, config, email);
break; break;
} }
} }
@ -276,7 +277,7 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static async Task EditAccountStatus(TeknikEntities db, Config config, string username, AccountStatus status) public static async Task EditAccountStatus(TeknikEntities db, Config config, IMailService mailService, string username, AccountStatus status)
{ {
try try
{ {
@ -294,13 +295,13 @@ namespace Teknik.Areas.Users.Utility
{ {
case AccountStatus.Active: case AccountStatus.Active:
// Enable Email // Enable Email
EnableUserEmail(config, email); EnableUserEmail(mailService, config, email);
// Enable Git // Enable Git
EnableUserGit(config, username); EnableUserGit(config, username);
break; break;
case AccountStatus.Banned: case AccountStatus.Banned:
// Disable Email // Disable Email
DisableUserEmail(config, email); DisableUserEmail(mailService, config, email);
// Disable Git // Disable Git
DisableUserGit(config, username); DisableUserGit(config, username);
break; break;
@ -317,7 +318,7 @@ namespace Teknik.Areas.Users.Utility
} }
} }
public static async Task DeleteAccount(TeknikEntities db, Config config, User user) public static async Task DeleteAccount(TeknikEntities db, Config config, IMailService mailService, User user)
{ {
try try
{ {
@ -332,8 +333,8 @@ namespace Teknik.Areas.Users.Utility
DeleteUser(db, config, user); DeleteUser(db, config, user);
// Delete Email Account // Delete Email Account
if (UserEmailExists(config, GetUserEmailAddress(config, username))) if (UserEmailExists(mailService, config, GetUserEmailAddress(config, username)))
DeleteUserEmail(config, GetUserEmailAddress(config, username)); DeleteUserEmail(mailService, config, GetUserEmailAddress(config, username));
// Delete Git Account // Delete Git Account
if (UserGitExists(config, username)) if (UserGitExists(config, username))
@ -621,58 +622,61 @@ If you recieved this email and you did not reset your password, you can ignore t
#region Email Management #region Email Management
public static string GetUserEmailAddress(Config config, string username) public static string GetUserEmailAddress(Config config, string username)
{ {
if (config.EmailConfig == null)
return null;
return string.Format("{0}@{1}", username, config.EmailConfig.Domain); return string.Format("{0}@{1}", username, config.EmailConfig.Domain);
} }
public static IMailService CreateMailService(Config config) public static IMailService CreateMailService(Config config, ILogger logger)
{ {
return new HMailService( if (config.EmailConfig != null &&
config.EmailConfig.MailHost, config.EmailConfig.Enabled)
config.EmailConfig.Username, return new HMailService(
config.EmailConfig.Password, config.EmailConfig.MailHost,
config.EmailConfig.Domain, config.EmailConfig.Username,
config.EmailConfig.CounterDatabase.Server, config.EmailConfig.Password,
config.EmailConfig.CounterDatabase.Database, config.EmailConfig.Domain,
config.EmailConfig.CounterDatabase.Username, config.EmailConfig.CounterDatabase.Server,
config.EmailConfig.CounterDatabase.Password, config.EmailConfig.CounterDatabase.Database,
config.EmailConfig.CounterDatabase.Port config.EmailConfig.CounterDatabase.Username,
); config.EmailConfig.CounterDatabase.Password,
config.EmailConfig.CounterDatabase.Port,
logger
);
return new EmptyMailService();
} }
public static bool UserEmailExists(Config config, string email) public static bool UserEmailExists(IMailService mailService, Config config, string email)
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); return mailService.AccountExists(email);
return svc.AccountExists(email);
} }
return false; return false;
} }
public static DateTime UserEmailLastActive(Config config, string email) public static DateTime UserEmailLastActive(IMailService mailService, Config config, string email)
{ {
DateTime lastActive = new DateTime(1900, 1, 1); DateTime lastActive = new DateTime(1900, 1, 1);
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); var lastEmail = mailService.LastActive(email);
var lastEmail = svc.LastActive(email);
if (lastActive < lastEmail) if (lastActive < lastEmail)
lastActive = lastEmail; lastActive = lastEmail;
} }
return lastActive; return lastActive;
} }
public static bool UserEmailEnabled(Config config, string email) public static bool UserEmailEnabled(IMailService mailService, Config config, string email)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); return mailService.IsEnabled(email);
return svc.Enabled(email);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -682,15 +686,14 @@ If you recieved this email and you did not reset your password, you can ignore t
return false; return false;
} }
public static void CreateUserEmail(Config config, string email, string password) public static void CreateUserEmail(IMailService mailService, Config config, string email, string password)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); mailService.CreateAccount(email, password, config.EmailConfig.MaxSize);
svc.CreateAccount(email, password, config.EmailConfig.MaxSize);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -699,15 +702,14 @@ If you recieved this email and you did not reset your password, you can ignore t
} }
} }
public static void EnableUserEmail(Config config, string email) public static void EnableUserEmail(IMailService mailService, Config config, string email)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); mailService.EnableAccount(email);
svc.EnableAccount(email);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -716,15 +718,14 @@ If you recieved this email and you did not reset your password, you can ignore t
} }
} }
public static void DisableUserEmail(Config config, string email) public static void DisableUserEmail(IMailService mailService, Config config, string email)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); mailService.DisableAccount(email);
svc.DisableAccount(email);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -733,15 +734,14 @@ If you recieved this email and you did not reset your password, you can ignore t
} }
} }
public static void EditUserEmailPassword(Config config, string email, string password) public static void EditUserEmailPassword(IMailService mailService, Config config, string email, string password)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); mailService.EditPassword(email, password);
svc.EditPassword(email, password);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -750,15 +750,14 @@ If you recieved this email and you did not reset your password, you can ignore t
} }
} }
public static void EditUserEmailMaxSize(Config config, string email, long size) public static void EditUserEmailMaxSize(IMailService mailService, Config config, string email, long size)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); mailService.EditMaxSize(email, size);
svc.EditMaxSize(email, size);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -767,15 +766,31 @@ If you recieved this email and you did not reset your password, you can ignore t
} }
} }
public static void EditUserEmailMaxEmailsPerDay(Config config, string email, int maxPerDay) public static long GetUserEmailMaxSize(IMailService mailService, Config config, string email)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); return mailService.GetMaxSize(email);
svc.EditMaxEmailsPerDay(email, maxPerDay); }
}
catch (Exception ex)
{
throw new Exception("Unable to edit email account mailbox size.", ex);
}
return -1;
}
public static void EditUserEmailMaxEmailsPerDay(IMailService mailService, Config config, string email, int maxPerDay)
{
try
{
// If Email Server is enabled
if (config.EmailConfig.Enabled)
{
mailService.EditMaxEmailsPerDay(email, maxPerDay);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -784,15 +799,14 @@ If you recieved this email and you did not reset your password, you can ignore t
} }
} }
public static void DeleteUserEmail(Config config, string email) public static void DeleteUserEmail(IMailService mailService, Config config, string email)
{ {
try try
{ {
// If Email Server is enabled // If Email Server is enabled
if (config.EmailConfig.Enabled) if (config.EmailConfig.Enabled)
{ {
var svc = CreateMailService(config); mailService.DeleteAccount(email);
svc.DeleteAccount(email);
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -96,7 +96,7 @@
{ {
<li class="list-group-item text-right"><span class="pull-left"><strong>Public Key</strong></span> <a href="#" data-toggle="modal" data-target="#pgpSignature">@pgpFingerprint64.AddStringAtInterval(4, " ")</a></li> <li class="list-group-item text-right"><span class="pull-left"><strong>Public Key</strong></span> <a href="#" data-toggle="modal" data-target="#pgpSignature">@pgpFingerprint64.AddStringAtInterval(4, " ")</a></li>
} }
@if (!string.IsNullOrEmpty(Model.Email) && Config.EmailConfig.Enabled && UserHelper.UserEmailEnabled(Config, Model.Email)) @if (!string.IsNullOrEmpty(Model.Email))
{ {
<li class="list-group-item text-right"><span class="pull-left"><strong>Email</strong></span> @(Html.Raw(User.Identity.IsAuthenticated ? $"<a href=\"mailto:{Model.Email}\">{Model.Email}</a>" : $"{Model.Username} at {Config.EmailConfig?.Domain}"))</li> <li class="list-group-item text-right"><span class="pull-left"><strong>Email</strong></span> @(Html.Raw(User.Identity.IsAuthenticated ? $"<a href=\"mailto:{Model.Email}\">{Model.Email}</a>" : $"{Model.Username} at {Config.EmailConfig?.Domain}"))</li>
} }

View File

@ -20,6 +20,10 @@ $(function () {
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + parseErrorMessage(html) + '</div>'); $("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + parseErrorMessage(html) + '</div>');
} }
} }
else {
$("#top_msg").css('display', 'inline', 'important');
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>No HTML Response.</div>');
}
} }
}); });
}); });
@ -43,6 +47,37 @@ $(function () {
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + parseErrorMessage(html) + '</div>'); $("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + parseErrorMessage(html) + '</div>');
} }
} }
else {
$("#top_msg").css('display', 'inline', 'important');
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>No HTML Response.</div>');
}
}
});
});
$('.userEmailActive').on('change', function () {
var selected = $(this).find("option:selected").val();
$.ajax({
type: "POST",
url: editEmailActive,
data: AddAntiForgeryToken({ username: username, active: selected }),
success: function (html) {
if (html) {
if (html.result.success) {
$("#top_msg").css('display', 'none');
$("#top_msg").html('');
alert('Successfully changed the email active status for \'' + username + '\' to: ' + selected);
}
else {
$("#top_msg").css('display', 'inline', 'important');
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + parseErrorMessage(html) + '</div>');
}
}
else {
$("#top_msg").css('display', 'inline', 'important');
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>No HTML Response.</div>');
}
} }
}); });
}); });

View File

@ -30,6 +30,8 @@ using Teknik.WebCommon.Middleware;
using Teknik.WebCommon; using Teknik.WebCommon;
using Teknik.Areas.Error.Controllers; using Teknik.Areas.Error.Controllers;
using Teknik.Services; using Teknik.Services;
using Teknik.MailService;
using Teknik.Areas.Users.Utility;
namespace Teknik namespace Teknik
{ {
@ -67,6 +69,7 @@ namespace Teknik
// Resolve the services from the service provider // Resolve the services from the service provider
var config = sp.GetService<Config>(); var config = sp.GetService<Config>();
var logger = sp.GetService<ILogger<Logger>>();
var devEnv = config?.DevEnvironment ?? true; var devEnv = config?.DevEnvironment ?? true;
var defaultConn = config?.DbConnection ?? string.Empty; var defaultConn = config?.DbConnection ?? string.Empty;
var authority = config?.UserConfig?.IdentityServerConfig?.Authority ?? string.Empty; var authority = config?.UserConfig?.IdentityServerConfig?.Authority ?? string.Empty;
@ -102,6 +105,7 @@ namespace Teknik
services.AddHostedService<TaskQueueService>(); services.AddHostedService<TaskQueueService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>(); services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
services.AddSingleton<ObjectCache, ObjectCache>(c => new ObjectCache(300)); services.AddSingleton<ObjectCache, ObjectCache>(c => new ObjectCache(300));
services.AddSingleton<IMailService, IMailService>(s => UserHelper.CreateMailService(config, logger));
services.AddHostedService<CacheCleanerService>(); services.AddHostedService<CacheCleanerService>();
services.AddScoped<IErrorController, ErrorController>(); services.AddScoped<IErrorController, ErrorController>();