- Added item to admin page to change a user's account type.tags/3.0.0
@@ -68,6 +68,9 @@ namespace Teknik.Areas.Admin | |||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UploadSearch", config.CdnHost).Include( | |||
"~/Scripts/bootbox/bootbox.min.js", | |||
"~/Areas/Admin/Scripts/UploadSearch.js")); | |||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UserInfo", config.CdnHost).Include( | |||
"~/Areas/Admin/Scripts/UserInfo.js")); | |||
} | |||
} | |||
} |
@@ -4,10 +4,12 @@ using System.Linq; | |||
using System.Web; | |||
using System.Web.Mvc; | |||
using Teknik.Areas.Admin.ViewModels; | |||
using Teknik.Areas.Users.Models; | |||
using Teknik.Areas.Users.Utility; | |||
using Teknik.Attributes; | |||
using Teknik.Controllers; | |||
using Teknik.Models; | |||
using Teknik.Utilities; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Admin.Controllers | |||
@@ -34,9 +36,15 @@ namespace Teknik.Areas.Admin.Controllers | |||
[HttpGet] | |||
public ActionResult UserInfo(string username) | |||
{ | |||
UserInfoViewModel model = new UserInfoViewModel(); | |||
model.Username = username; | |||
return View(model); | |||
if (UserHelper.UserExists(db, username)) | |||
{ | |||
User user = UserHelper.GetUser(db, username); | |||
UserInfoViewModel model = new UserInfoViewModel(); | |||
model.Username = user.Username; | |||
model.AccountType = user.AccountType; | |||
return View(model); | |||
} | |||
return Redirect(Url.SubRouteUrl("error", "Error.Http404")); | |||
} | |||
[HttpGet] | |||
@@ -90,5 +98,18 @@ namespace Teknik.Areas.Admin.Controllers | |||
} | |||
return Json(new { error = new { message = "Upload does not exist" } }); | |||
} | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public ActionResult EditUserAccountType(string username, AccountType accountType) | |||
{ | |||
if (UserHelper.UserExists(db, username)) | |||
{ | |||
// Edit the user's account type | |||
UserHelper.EditAccountType(db, Config, username, accountType); | |||
return Json(new { result = new { success = true } }); | |||
} | |||
return Redirect(Url.SubRouteUrl("error", "Error.Http404")); | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
$(function () { | |||
$('.userAccountType').on('change', function () { | |||
var selected = $(this).find("option:selected").val(); | |||
$.ajax({ | |||
type: "POST", | |||
url: editAccountType, | |||
data: AddAntiForgeryToken({ username: username, accountType: selected }), | |||
success: function (html) { | |||
if (html) { | |||
if (html.error) { | |||
$("#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">×</button>' + html.error.message + '</div>'); | |||
} | |||
else { | |||
$("#top_msg").css('display', 'none'); | |||
$("#top_msg").html(''); | |||
alert('Successfully changed the account type for \'' + username + '\' to type: ' + selected); | |||
} | |||
} | |||
} | |||
}); | |||
}); | |||
}); |
@@ -2,6 +2,7 @@ | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Utilities; | |||
using Teknik.ViewModels; | |||
namespace Teknik.Areas.Admin.ViewModels | |||
@@ -9,5 +10,6 @@ namespace Teknik.Areas.Admin.ViewModels | |||
public class UserInfoViewModel : ViewModelBase | |||
{ | |||
public string Username { get; set; } | |||
public AccountType AccountType { get; set; } | |||
} | |||
} |
@@ -2,8 +2,30 @@ | |||
@using Teknik.Utilities | |||
<div class="row"> | |||
<div class="col-sm-10 col-sm-offset-1"> | |||
<a href="@Url.SubRouteUrl("user", "User.ViewProfile", new { username = Model.Username })">@Model.Username</a> | |||
<script> | |||
// We need to define the action URLs for the script | |||
var editAccountType = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountType" })'; | |||
var username = '@Model.Username'; | |||
</script> | |||
@Scripts.Render("~/bundles/UserInfo") | |||
<div class="container"> | |||
<div class="row"> | |||
<div class="col-sm-10 col-sm-offset-1"> | |||
<a href="@Url.SubRouteUrl("user", "User.ViewProfile", new { username = Model.Username })">@Model.Username</a> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-4 col-sm-offset-1">Account Type: | |||
<select class="userAccountType"> | |||
@{ | |||
foreach (AccountType value in Enum.GetValues(typeof(AccountType))) | |||
{ | |||
<option @(value == Model.AccountType ? "selected" : string.Empty)>@value.ToString()</option> | |||
} | |||
} | |||
</select> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -216,6 +216,47 @@ namespace Teknik.Areas.Users.Utility | |||
} | |||
} | |||
public static void EditAccountType(TeknikEntities db, Config config, string username, AccountType type) | |||
{ | |||
try | |||
{ | |||
if (!UserExists(db, username)) | |||
throw new Exception($"The user provided does not exist: {username}"); | |||
// Get the user to edit | |||
User user = GetUser(db, username); | |||
string email = GetUserEmailAddress(config, username); | |||
// Edit the user type | |||
user.AccountType = type; | |||
EditUser(db, config, user); | |||
// Add/Remove account type features depending on the type | |||
switch (type) | |||
{ | |||
case AccountType.Basic: | |||
// Set the email size to 1GB | |||
EditUserEmailMaxSize(config, email, config.EmailConfig.MaxSize); | |||
// Set the email max/day to 100 | |||
EditUserEmailMaxEmailsPerDay(config, email, 100); | |||
break; | |||
case AccountType.Premium: | |||
// Set the email size to 5GB | |||
EditUserEmailMaxSize(config, email, 5000); | |||
// Set the email max/day to infinite (-1) | |||
EditUserEmailMaxEmailsPerDay(config, email, -1); | |||
break; | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
throw new Exception($"Unable to edit the account type [{type}] for: {username}", ex); | |||
} | |||
} | |||
public static void DeleteAccount(TeknikEntities db, Config config, User user) | |||
{ | |||
try | |||
@@ -426,6 +467,11 @@ namespace Teknik.Areas.Users.Utility | |||
} | |||
} | |||
public static void EditUser(TeknikEntities db, Config config, User user) | |||
{ | |||
EditUser(db, config, user, false, string.Empty); | |||
} | |||
public static void EditUser(TeknikEntities db, Config config, User user, bool changePass, string password) | |||
{ | |||
try | |||
@@ -827,6 +873,50 @@ If you recieved this email and you did not reset your password, you can ignore t | |||
} | |||
} | |||
public static void EditUserEmailMaxSize(Config config, string email, int size) | |||
{ | |||
try | |||
{ | |||
// If Email Server is enabled | |||
if (config.EmailConfig.Enabled) | |||
{ | |||
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.MaxSize = size; | |||
account.Save(); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
throw new Exception("Unable to edit email account mailbox size.", ex); | |||
} | |||
} | |||
public static void EditUserEmailMaxEmailsPerDay(Config config, string email, int maxPerDay) | |||
{ | |||
try | |||
{ | |||
// If Email Server is enabled | |||
if (config.EmailConfig.Enabled) | |||
{ | |||
// Query the Email DB | |||
// We need to check the actual git database | |||
MysqlDatabase mySQL = new MysqlDatabase(config.EmailConfig.CounterDatabase.Server, config.EmailConfig.CounterDatabase.Database, config.EmailConfig.CounterDatabase.Username, config.EmailConfig.CounterDatabase.Password, config.EmailConfig.CounterDatabase.Port); | |||
string sql = @"INSERT INTO mailcounter.counts (qname, lastdate, qlimit, count) VALUES ({1}, NOW(), {0}, 0) | |||
ON DUPLICATE KEY UPDATE qlimit = {0}"; | |||
mySQL.Execute(sql, new object[] { maxPerDay, email }); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
throw new Exception("Unable to edit email account mailbox size.", ex); | |||
} | |||
} | |||
public static void DeleteUserEmail(Config config, string email) | |||
{ | |||
try |
@@ -1,5 +1,7 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" /> | |||
<Import Project="..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" /> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
@@ -89,6 +91,10 @@ | |||
<HintPath>..\packages\Microsoft.Azure.KeyVault.Core.2.0.4\lib\net45\Microsoft.Azure.KeyVault.Core.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Microsoft.CSharp" /> | |||
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath> | |||
@@ -382,6 +388,7 @@ | |||
</Content> | |||
<Content Include="Areas\Admin\Scripts\UploadSearch.js" /> | |||
<Content Include="Areas\Admin\Scripts\Search.js" /> | |||
<Content Include="Areas\Admin\Scripts\UserInfo.js" /> | |||
<Content Include="Areas\Blog\Content\Blog.css" /> | |||
<Content Include="Areas\Blog\Scripts\Blog.js" /> | |||
<Content Include="Areas\Contact\Scripts\Contact.js" /> | |||
@@ -855,6 +862,8 @@ | |||
<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.6.5\build\dotnet\GitVersionTask.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GitVersionTask.3.6.5\build\dotnet\GitVersionTask.targets'))" /> | |||
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props'))" /> | |||
<Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" /> | |||
</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. |
@@ -193,4 +193,10 @@ | |||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /> | |||
</DbProviderFactories> | |||
</system.data> | |||
<system.codedom> | |||
<compilers> | |||
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" /> | |||
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" /> | |||
</compilers> | |||
</system.codedom> | |||
</configuration> |
@@ -25,7 +25,9 @@ | |||
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net46" userInstalled="true" /> | |||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net46" userInstalled="true" /> | |||
<package id="Microsoft.Azure.KeyVault.Core" version="2.0.4" targetFramework="net462" /> | |||
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net462" /> | |||
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net46" userInstalled="true" /> | |||
<package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net462" developmentDependency="true" /> | |||
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net462" /> | |||
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net462" /> | |||
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net462" /> |
@@ -19,6 +19,8 @@ namespace Teknik.Configuration | |||
public int MaxSize { get; set; } | |||
public DatabaseConfig CounterDatabase { get; set; } | |||
public EmailConfig() | |||
{ | |||
Enabled = true; | |||
@@ -27,6 +29,7 @@ namespace Teknik.Configuration | |||
Domain = string.Empty; | |||
MailHost = string.Empty; | |||
MaxSize = 1000; | |||
CounterDatabase = new DatabaseConfig(); | |||
} | |||
} | |||
} |