mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
- Added account status of either active or banned.
- Cleaned up admin pages. - Added Type and Status to user's profile page. - Banned users cannot login, or associate API calls with their account
This commit is contained in:
parent
e3e5a60de7
commit
51b4260f3c
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Optimization;
|
||||
using Teknik.Configuration;
|
||||
@ -28,11 +28,11 @@ namespace Teknik.Areas.Admin
|
||||
new[] { typeof(Controllers.AdminController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
"Admin.Search", // Route name
|
||||
"Admin.UserSearch", // Route name
|
||||
new List<string>() { "admin" }, // Subdomains
|
||||
new List<string>() { config.Host },
|
||||
"Search/Users", // URL with parameters
|
||||
new { controller = "Admin", action = "Search" }, // Parameter defaults
|
||||
new { controller = "Admin", action = "UserSearch" }, // Parameter defaults
|
||||
new[] { typeof(Controllers.AdminController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
@ -61,8 +61,8 @@ namespace Teknik.Areas.Admin
|
||||
);
|
||||
|
||||
// Register Script Bundles
|
||||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/Search", config.CdnHost).Include(
|
||||
"~/Areas/Admin/Scripts/Search.js"));
|
||||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UserSearch", config.CdnHost).Include(
|
||||
"~/Areas/Admin/Scripts/UserSearch.js"));
|
||||
|
||||
// Register Script Bundles
|
||||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/UploadSearch", config.CdnHost).Include(
|
||||
@ -73,4 +73,4 @@ namespace Teknik.Areas.Admin
|
||||
"~/Areas/Admin/Scripts/UserInfo.js"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -27,9 +27,9 @@ namespace Teknik.Areas.Admin.Controllers
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult Search()
|
||||
public ActionResult UserSearch()
|
||||
{
|
||||
SearchViewModel model = new SearchViewModel();
|
||||
UserSearchViewModel model = new UserSearchViewModel();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ namespace Teknik.Areas.Admin.Controllers
|
||||
UserInfoViewModel model = new UserInfoViewModel();
|
||||
model.Username = user.Username;
|
||||
model.AccountType = user.AccountType;
|
||||
model.AccountStatus = user.AccountStatus;
|
||||
return View(model);
|
||||
}
|
||||
return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
|
||||
@ -55,9 +56,9 @@ namespace Teknik.Areas.Admin.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult GetSearchResults(string query)
|
||||
public ActionResult GetUserSearchResults(string query)
|
||||
{
|
||||
List<SearchResultViewModel> models = new List<SearchResultViewModel>();
|
||||
List<UserResultViewModel> models = new List<UserResultViewModel>();
|
||||
|
||||
var results = db.Users.Where(u => u.Username.Contains(query)).ToList();
|
||||
if (results != null)
|
||||
@ -66,7 +67,7 @@ namespace Teknik.Areas.Admin.Controllers
|
||||
{
|
||||
try
|
||||
{
|
||||
SearchResultViewModel model = new SearchResultViewModel();
|
||||
UserResultViewModel model = new UserResultViewModel();
|
||||
model.Username = user.Username;
|
||||
if (Config.EmailConfig.Enabled)
|
||||
{
|
||||
@ -83,7 +84,7 @@ namespace Teknik.Areas.Admin.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
return PartialView("~/Areas/Admin/Views/Admin/SearchResults.cshtml", models);
|
||||
return PartialView("~/Areas/Admin/Views/Admin/UserResults.cshtml", models);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
@ -118,5 +119,18 @@ namespace Teknik.Areas.Admin.Controllers
|
||||
}
|
||||
return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public ActionResult EditUserAccountStatus(string username, AccountStatus accountStatus)
|
||||
{
|
||||
if (UserHelper.UserExists(db, username))
|
||||
{
|
||||
// Edit the user's account type
|
||||
UserHelper.EditAccountStatus(db, Config, username, accountStatus);
|
||||
return Json(new { result = new { success = true } });
|
||||
}
|
||||
return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
$(function () {
|
||||
$(function () {
|
||||
|
||||
$('.userAccountType').on('change', function () {
|
||||
var selected = $(this).find("option:selected").val();
|
||||
@ -23,4 +23,27 @@
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
$('.userAccountStatus').on('change', function () {
|
||||
var selected = $(this).find("option:selected").val();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: editAccountStatus,
|
||||
data: AddAntiForgeryToken({ username: username, accountStatus: 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 status for \'' + username + '\' to: ' + selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
$(document).ready(function () {
|
||||
$(document).ready(function () {
|
||||
$('#Query').on('input', function (e) {
|
||||
query = $(this).val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: searchResultsURL,
|
||||
url: userSearchResultsURL,
|
||||
data: { query: query },
|
||||
success: function (html) {
|
||||
if (html) {
|
||||
@ -18,4 +18,4 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -11,5 +11,6 @@ namespace Teknik.Areas.Admin.ViewModels
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public AccountType AccountType { get; set; }
|
||||
public AccountStatus AccountStatus { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -6,7 +6,7 @@ using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Admin.ViewModels
|
||||
{
|
||||
public class SearchResultViewModel : ViewModelBase
|
||||
public class UserResultViewModel : ViewModelBase
|
||||
{
|
||||
public string Username { get; set; }
|
||||
|
||||
@ -16,4 +16,4 @@ namespace Teknik.Areas.Admin.ViewModels
|
||||
|
||||
public DateTime LastSeen { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -6,7 +6,7 @@ using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Admin.ViewModels
|
||||
{
|
||||
public class SearchViewModel : ViewModelBase
|
||||
public class UserSearchViewModel : ViewModelBase
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
@model Teknik.Areas.Admin.ViewModels.DashboardViewModel
|
||||
@model Teknik.Areas.Admin.ViewModels.DashboardViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<a href="@Url.SubRouteUrl("admin", "Admin.Search")">Search</a>
|
||||
<a href="@Url.SubRouteUrl("admin", "Admin.UserSearch")">User Search</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@ -13,4 +13,4 @@
|
||||
<a href="@Url.SubRouteUrl("admin", "Admin.UploadSearch")">Upload Search</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,10 +1,11 @@
|
||||
@model Teknik.Areas.Admin.ViewModels.UserInfoViewModel
|
||||
@model Teknik.Areas.Admin.ViewModels.UserInfoViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
|
||||
<script>
|
||||
// We need to define the action URLs for the script
|
||||
var editAccountType = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountType" })';
|
||||
var editAccountStatus = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "EditUserAccountStatus" })';
|
||||
var username = '@Model.Username';
|
||||
</script>
|
||||
|
||||
@ -12,20 +13,43 @@
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<div class="col-sm-2 col-sm-offset-1">
|
||||
Username:
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<a href="@Url.SubRouteUrl("user", "User.ViewProfile", new { username = Model.Username })">@Model.Username</a>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-sm-offset-1">Account Type:
|
||||
<div class="col-sm-2 col-sm-offset-1">
|
||||
Account Type:
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<select class="userAccountType">
|
||||
@{
|
||||
foreach (AccountType value in Enum.GetValues(typeof(AccountType)))
|
||||
{
|
||||
<option @(value == Model.AccountType ? "selected" : string.Empty)>@value.ToString()</option>
|
||||
}
|
||||
foreach (AccountType value in Enum.GetValues(typeof(AccountType)))
|
||||
{
|
||||
<option @(value == Model.AccountType ? "selected" : string.Empty)>@value.ToString()</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-sm-2 col-sm-offset-1">
|
||||
Account Status:
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<select class="userAccountStatus">
|
||||
@{
|
||||
foreach (AccountStatus value in Enum.GetValues(typeof(AccountStatus)))
|
||||
{
|
||||
<option @(value == Model.AccountStatus ? "selected" : string.Empty)>@value.ToString()</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
@model Teknik.Areas.Admin.ViewModels.SearchResultViewModel
|
||||
@model Teknik.Areas.Admin.ViewModels.UserResultViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
|
||||
@ -11,4 +11,4 @@
|
||||
<div class="col-sm-3"><time datetime="@Model.JoinDate.ToString("s")">@Model.JoinDate.ToString("MMMM dd, yyyy hh:mm tt")</time></div>
|
||||
<div class="col-sm-3"><time datetime="@Model.LastSeen.ToString("s")">@Model.LastSeen.ToString("MMMM dd, yyyy hh:mm tt")</time></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
@model List<Teknik.Areas.Admin.ViewModels.SearchResultViewModel>
|
||||
@model List<Teknik.Areas.Admin.ViewModels.UserResultViewModel>
|
||||
|
||||
@if (Model.Any())
|
||||
{
|
||||
@ -10,10 +10,10 @@
|
||||
</div>
|
||||
foreach (var post in Model)
|
||||
{
|
||||
@Html.Partial("SearchResult", post)
|
||||
@Html.Partial("UserResult", post)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<h3>No Results</h3>
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
@model Teknik.Areas.Admin.ViewModels.SearchViewModel
|
||||
@model Teknik.Areas.Admin.ViewModels.UserSearchViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
|
||||
<script>
|
||||
// We need to define the action URLs for the script
|
||||
var searchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetSearchResults" })';
|
||||
var userSearchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUserSearchResults" })';
|
||||
</script>
|
||||
|
||||
@Scripts.Render("~/bundles/Search")
|
||||
@Scripts.Render("~/bundles/UserSearch")
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@ -24,4 +24,4 @@
|
||||
<div class="results" id="results"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
@ -99,7 +99,7 @@ namespace Teknik.Areas.Error.Controllers
|
||||
|
||||
return View("~/Areas/Error/Views/Error/Http403.cshtml", model);
|
||||
}
|
||||
|
||||
|
||||
[AllowAnonymous]
|
||||
public ActionResult Http404(Exception exception)
|
||||
{
|
||||
@ -163,4 +163,4 @@ namespace Teknik.Areas.Error.Controllers
|
||||
Logger.WriteEntry(level, message, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using Teknik.Configuration;
|
||||
|
||||
@ -43,4 +43,4 @@ namespace Teknik.Areas.Error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
@ -69,6 +69,8 @@ namespace Teknik.Areas.Users.Controllers
|
||||
}
|
||||
model.JoinDate = user.JoinDate;
|
||||
model.LastSeen = UserHelper.GetLastAccountActivity(db, Config, user);
|
||||
model.AccountType = user.AccountType;
|
||||
model.AccountStatus = user.AccountStatus;
|
||||
|
||||
model.UserSettings = user.UserSettings;
|
||||
model.SecuritySettings = user.SecuritySettings;
|
||||
@ -197,6 +199,15 @@ namespace Teknik.Areas.Users.Controllers
|
||||
db.Entry(user).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
|
||||
// Make sure they aren't banned or anything
|
||||
if (user.AccountStatus == AccountStatus.Banned)
|
||||
{
|
||||
model.Error = true;
|
||||
model.ErrorMessage = "Account has been banned.";
|
||||
|
||||
return GenerateActionResult(new { error = model.ErrorMessage }, View("/Areas/User/Views/User/ViewLogin.cshtml", model));
|
||||
}
|
||||
|
||||
// Let's double check their email and git accounts to make sure they exist
|
||||
string email = UserHelper.GetUserEmailAddress(Config, username);
|
||||
if (Config.EmailConfig.Enabled && !UserHelper.UserEmailExists(Config, email))
|
||||
@ -1012,4 +1023,4 @@ namespace Teknik.Areas.Users.Controllers
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNet.Identity.EntityFramework;
|
||||
using System.Collections.Generic;
|
||||
@ -26,6 +26,8 @@ namespace Teknik.Areas.Users.Models
|
||||
|
||||
public AccountType AccountType { get; set; }
|
||||
|
||||
public AccountStatus AccountStatus { get; set; }
|
||||
|
||||
public virtual ICollection<Group> Groups { get; set; }
|
||||
|
||||
public virtual UserSettings UserSettings { get; set; }
|
||||
@ -56,9 +58,10 @@ namespace Teknik.Areas.Users.Models
|
||||
JoinDate = DateTime.Now;
|
||||
LastSeen = DateTime.Now;
|
||||
AccountType = AccountType.Basic;
|
||||
AccountStatus = AccountStatus.Active;
|
||||
Groups = new List<Group>();
|
||||
TrustedDevices = new List<TrustedDevice>();
|
||||
AuthTokens = new List<AuthToken>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
@ -261,6 +261,45 @@ namespace Teknik.Areas.Users.Utility
|
||||
}
|
||||
}
|
||||
|
||||
public static void EditAccountStatus(TeknikEntities db, Config config, string username, AccountStatus status)
|
||||
{
|
||||
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.AccountStatus = status;
|
||||
EditUser(db, config, user);
|
||||
|
||||
// Add/Remove account type features depending on the type
|
||||
switch (status)
|
||||
{
|
||||
case AccountStatus.Active:
|
||||
// Enable Email
|
||||
EnableUserEmail(config, email);
|
||||
// Enable Git
|
||||
EnableUserGit(config, username);
|
||||
break;
|
||||
case AccountStatus.Banned:
|
||||
// Disable Email
|
||||
DisableUserEmail(config, email);
|
||||
// Disable Git
|
||||
DisableUserGit(config, username);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Unable to edit the account status [{status}] for: {username}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteAccount(TeknikEntities db, Config config, User user)
|
||||
{
|
||||
try
|
||||
@ -385,7 +424,7 @@ namespace Teknik.Areas.Users.Utility
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool UserHasRoles(TeknikEntities db, User user, params string[] roles)
|
||||
public static bool UserHasRoles(User user, params string[] roles)
|
||||
{
|
||||
bool hasRole = true;
|
||||
if (user != null)
|
||||
@ -862,6 +901,38 @@ If you recieved this email and you did not reset your password, you can ignore t
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableUserEmail(Config config, string email)
|
||||
{
|
||||
EditUserEmailActivity(config, email, true);
|
||||
}
|
||||
|
||||
public static void DisableUserEmail(Config config, string email)
|
||||
{
|
||||
EditUserEmailActivity(config, email, false);
|
||||
}
|
||||
|
||||
public static void EditUserEmailActivity(Config config, string email, bool active)
|
||||
{
|
||||
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.Active = active;
|
||||
account.Save();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to edit email account mailbox size.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EditUserEmailPassword(Config config, string email, string password)
|
||||
{
|
||||
try
|
||||
@ -1069,6 +1140,47 @@ If you recieved this email and you did not reset your password, you can ignore t
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableUserGit(Config config, string username)
|
||||
{
|
||||
EditUserGitActivity(config, username, true);
|
||||
}
|
||||
|
||||
public static void DisableUserGit(Config config, string username)
|
||||
{
|
||||
EditUserGitActivity(config, username, false);
|
||||
}
|
||||
|
||||
public static void EditUserGitActivity(Config config, string username, bool active)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If Git is enabled
|
||||
if (config.GitConfig.Enabled)
|
||||
{
|
||||
// Git user exists?
|
||||
if (!UserGitExists(config, username))
|
||||
{
|
||||
throw new Exception($"Git User '{username}' does not exist.");
|
||||
}
|
||||
|
||||
string email = GetUserEmailAddress(config, username);
|
||||
using (var client = new WebClient())
|
||||
{
|
||||
var obj = new { active = active, email = email };
|
||||
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/" + username + "?token=" + config.GitConfig.AccessToken);
|
||||
string result = client.UploadString(finalUri, "PATCH", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to edit git account password.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CreateUserGitTwoFactor(Config config, string username, string secret, int unixTime)
|
||||
{
|
||||
try
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -29,6 +29,7 @@ namespace Teknik.Areas.Users.ViewModels
|
||||
|
||||
public string Quote { get; set; }
|
||||
|
||||
[AllowHtml]
|
||||
public string About { get; set; }
|
||||
|
||||
public string BlogTitle { get; set; }
|
||||
@ -37,4 +38,4 @@ namespace Teknik.Areas.Users.ViewModels
|
||||
|
||||
public bool Encrypt { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.Areas.Users.Models;
|
||||
using Teknik.Utilities;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Users.ViewModels
|
||||
@ -19,6 +20,10 @@ namespace Teknik.Areas.Users.ViewModels
|
||||
|
||||
public DateTime LastSeen { get; set; }
|
||||
|
||||
public AccountType AccountType { get; set; }
|
||||
|
||||
public AccountStatus AccountStatus { get; set; }
|
||||
|
||||
public List<Upload.Models.Upload> Uploads { get; set; }
|
||||
|
||||
public List<Paste.Models.Paste> Pastes { get; set; }
|
||||
@ -35,4 +40,4 @@ namespace Teknik.Areas.Users.ViewModels
|
||||
|
||||
public UploadSettings UploadSettings { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
@model Teknik.Areas.Users.ViewModels.ProfileViewModel
|
||||
@model Teknik.Areas.Users.ViewModels.ProfileViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
@using Teknik.Utilities.Cryptography
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="container">
|
||||
@if (!Model.Error)
|
||||
{
|
||||
bool OwnProfile = (Model.Username == User.Identity.Name || User.IsInRole("Admin"));
|
||||
bool OwnProfile = (Model.Username == User.Identity.Name || User.IsInRole("Admin")) && User.Identity.IsAuthenticated;
|
||||
string gitHost = Model.Config.GitConfig.Host;
|
||||
string gitFullUrl = string.Empty;
|
||||
if (!string.IsNullOrEmpty(gitHost))
|
||||
@ -32,6 +32,12 @@
|
||||
<div class="row text-center">
|
||||
<div class="col-sm-3"><h1>@Model.Username</h1></div>
|
||||
</div>
|
||||
if (User.IsInRole("Admin"))
|
||||
{
|
||||
<div class="row text-center">
|
||||
<div class="col-sm-3"><a href="@Url.SubRouteUrl("admin", "Admin.UserInfo", new { username = Model.Username })">edit</a></div>
|
||||
</div>
|
||||
}
|
||||
<div class="modal fade" id="pgpSignature" tabindex="-1" role="dialog" aria-labelledby="pgpSignatureLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
@ -78,11 +84,18 @@
|
||||
<!-- Left Info Box -->
|
||||
<div class="col-sm-3"><!--left col-->
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item text-muted">Profile</li>
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Joined</strong></span> <time datetime="@Model.LastSeen.ToString("s")">@Model.JoinDate.ToString("MMMM dd, yyyy")</time></li>
|
||||
@if (OwnProfile && User.Identity.IsAuthenticated)
|
||||
@if (OwnProfile)
|
||||
{
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Last Seen</strong></span> <time datetime="@Model.LastSeen.ToString("s")">@Model.LastSeen.ToString("MMMM dd, yyyy hh:mm tt")</time></li>
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Last Seen</strong></span> <time datetime="@Model.LastSeen.ToString("s")">@Model.LastSeen.ToString("dd/MM/yyyy hh:mm tt")</time></li>
|
||||
}
|
||||
@if (OwnProfile)
|
||||
{
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Account Type</strong></span> @Model.AccountType</li>
|
||||
}
|
||||
@if (User.IsInRole("Admin"))
|
||||
{
|
||||
<li class="list-group-item text-right"><span class="pull-left"><strong>Account Status</strong></span> @Model.AccountStatus</li>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(pgpFingerprint))
|
||||
{
|
||||
@ -276,4 +289,4 @@
|
||||
}
|
||||
</div>
|
||||
|
||||
@Scripts.Render("~/bundles/profile")
|
||||
@Scripts.Render("~/bundles/profile")
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -122,7 +122,8 @@ namespace Teknik.Attributes
|
||||
if (validToken)
|
||||
{
|
||||
User user = UserHelper.GetUserFromToken(entities, authCreds.Key, authCreds.Value);
|
||||
return UserHelper.UserHasRoles(entities, user, Roles);
|
||||
|
||||
return UserHelper.UserHasRoles(user, Roles);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -204,4 +205,4 @@ namespace Teknik.Attributes
|
||||
validationStatus = base.OnCacheAuthorization(new HttpContextWrapper(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
@ -77,70 +77,70 @@ namespace Teknik
|
||||
}
|
||||
}
|
||||
|
||||
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
|
||||
{
|
||||
// We support both Auth Tokens and Cookie Authentication
|
||||
//protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
|
||||
//{
|
||||
// // We support both Auth Tokens and Cookie Authentication
|
||||
|
||||
// Username and Roles for the current user
|
||||
string username = string.Empty;
|
||||
// // Username and Roles for the current user
|
||||
// string username = string.Empty;
|
||||
|
||||
bool hasAuthToken = false;
|
||||
if (Request != null)
|
||||
{
|
||||
if (Request.Headers.HasKeys())
|
||||
{
|
||||
string auth = Request.Headers["Authorization"];
|
||||
if (!string.IsNullOrEmpty(auth))
|
||||
{
|
||||
string[] parts = auth.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string type = string.Empty;
|
||||
string value = string.Empty;
|
||||
if (parts.Length > 0)
|
||||
{
|
||||
type = parts[0].ToLower();
|
||||
}
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
value = parts[1];
|
||||
}
|
||||
// bool hasAuthToken = false;
|
||||
// if (Request != null)
|
||||
// {
|
||||
// if (Request.Headers.HasKeys())
|
||||
// {
|
||||
// string auth = Request.Headers["Authorization"];
|
||||
// if (!string.IsNullOrEmpty(auth))
|
||||
// {
|
||||
// string[] parts = auth.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
// string type = string.Empty;
|
||||
// string value = string.Empty;
|
||||
// if (parts.Length > 0)
|
||||
// {
|
||||
// type = parts[0].ToLower();
|
||||
// }
|
||||
// if (parts.Length > 1)
|
||||
// {
|
||||
// value = parts[1];
|
||||
// }
|
||||
|
||||
using (TeknikEntities entities = new TeknikEntities())
|
||||
{
|
||||
// Get the user information based on the auth type
|
||||
switch (type)
|
||||
{
|
||||
case "basic":
|
||||
KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value);
|
||||
// using (TeknikEntities entities = new TeknikEntities())
|
||||
// {
|
||||
// // Get the user information based on the auth type
|
||||
// switch (type)
|
||||
// {
|
||||
// case "basic":
|
||||
// KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value);
|
||||
|
||||
bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value);
|
||||
if (tokenValid)
|
||||
{
|
||||
// it's valid, so let's update it's Last Used date
|
||||
UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now);
|
||||
// bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value);
|
||||
// if (tokenValid)
|
||||
// {
|
||||
// // it's valid, so let's update it's Last Used date
|
||||
// UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now);
|
||||
|
||||
// Set the username
|
||||
username = authCreds.Key;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// // Set the username
|
||||
// username = authCreds.Key;
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (FormsAuthentication.CookiesSupported == true && !hasAuthToken)
|
||||
{
|
||||
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
|
||||
{
|
||||
//let us take out the username now
|
||||
username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
|
||||
}
|
||||
}
|
||||
// if (FormsAuthentication.CookiesSupported == true && !hasAuthToken)
|
||||
// {
|
||||
// if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
|
||||
// {
|
||||
// //let us take out the username now
|
||||
// username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
|
||||
// }
|
||||
// }
|
||||
|
||||
HttpContext.Current.User = new TeknikPrincipal(username);
|
||||
}
|
||||
// HttpContext.Current.User = new TeknikPrincipal(username);
|
||||
//}
|
||||
|
||||
protected void Application_Error(object sender, EventArgs e)
|
||||
{
|
||||
|
113
Teknik/Modules/UserCheckModule.cs
Normal file
113
Teknik/Modules/UserCheckModule.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Security;
|
||||
using Teknik.Areas.Error.Controllers;
|
||||
using Teknik.Areas.Users.Utility;
|
||||
using Teknik.Models;
|
||||
using Teknik.Security;
|
||||
using Teknik.Utilities;
|
||||
|
||||
namespace Teknik.Modules
|
||||
{
|
||||
public class UserCheckModule : IHttpModule
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void Init(HttpApplication context)
|
||||
{
|
||||
context.PostAuthenticateRequest += OnPostAuthenticateRequestHandlerExecute;
|
||||
}
|
||||
|
||||
private void OnPostAuthenticateRequestHandlerExecute(object sender, EventArgs e)
|
||||
{
|
||||
HttpContext context = HttpContext.Current;
|
||||
string username = string.Empty;
|
||||
|
||||
bool hasAuthToken = false;
|
||||
if (context.Request != null)
|
||||
{
|
||||
if (context.Request.Headers.HasKeys())
|
||||
{
|
||||
string auth = context.Request.Headers["Authorization"];
|
||||
if (!string.IsNullOrEmpty(auth))
|
||||
{
|
||||
string[] parts = auth.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string type = string.Empty;
|
||||
string value = string.Empty;
|
||||
if (parts.Length > 0)
|
||||
{
|
||||
type = parts[0].ToLower();
|
||||
}
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
value = parts[1];
|
||||
}
|
||||
|
||||
using (TeknikEntities entities = new TeknikEntities())
|
||||
{
|
||||
// Get the user information based on the auth type
|
||||
switch (type)
|
||||
{
|
||||
case "basic":
|
||||
KeyValuePair<string, string> authCreds = StringHelper.ParseBasicAuthHeader(value);
|
||||
|
||||
bool tokenValid = UserHelper.UserTokenCorrect(entities, authCreds.Key, authCreds.Value);
|
||||
if (tokenValid)
|
||||
{
|
||||
// it's valid, so let's update it's Last Used date
|
||||
UserHelper.UpdateTokenLastUsed(entities, authCreds.Key, authCreds.Value, DateTime.Now);
|
||||
|
||||
// Set the username
|
||||
username = authCreds.Key;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if they have a Forms Auth cookie
|
||||
if (FormsAuthentication.CookiesSupported == true && !hasAuthToken)
|
||||
{
|
||||
if (context.Request.Cookies[FormsAuthentication.FormsCookieName] != null)
|
||||
{
|
||||
//let us take out the username now
|
||||
username = FormsAuthentication.Decrypt(context.Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
|
||||
}
|
||||
}
|
||||
|
||||
context.User = new TeknikPrincipal(username);
|
||||
|
||||
// Check to see if we need to logout this user
|
||||
if (context.User != null && context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
TeknikPrincipal user = (context.User as TeknikPrincipal);
|
||||
// Is the user banned?
|
||||
if (user?.Info.AccountStatus == AccountStatus.Banned)
|
||||
{
|
||||
// Get cookie
|
||||
HttpCookie authCookie = UserHelper.CreateAuthCookie(user.Identity.Name, false, context.Request.Url.Host.GetDomain(), context.Request.IsLocal);
|
||||
|
||||
// Signout
|
||||
FormsAuthentication.SignOut();
|
||||
context.Session?.Abandon();
|
||||
|
||||
// Destroy Cookies
|
||||
authCookie.Expires = DateTime.Now.AddYears(-1);
|
||||
context.Response.Cookies.Add(authCookie);
|
||||
|
||||
// Reset the context user
|
||||
context.User = new TeknikPrincipal(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
@ -6,6 +6,7 @@ using System.Web;
|
||||
using Teknik.Areas.Users.Models;
|
||||
using Teknik.Areas.Users.Utility;
|
||||
using Teknik.Models;
|
||||
using Teknik.Utilities;
|
||||
|
||||
namespace Teknik.Security
|
||||
{
|
||||
@ -41,21 +42,7 @@ namespace Teknik.Security
|
||||
|
||||
public bool IsInRole(string role)
|
||||
{
|
||||
if (Info != null)
|
||||
{
|
||||
// Grab all their roles
|
||||
foreach (Group grp in Info.Groups)
|
||||
{
|
||||
foreach (Role curRole in grp.Roles)
|
||||
{
|
||||
if (curRole.Name == role)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return UserHelper.UserHasRoles(Info, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<Use64BitIISExpress />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -219,10 +220,10 @@
|
||||
<Compile Include="Areas\Admin\AdminAreaRegistration.cs" />
|
||||
<Compile Include="Areas\Admin\Controllers\AdminController.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\DashboardViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\SearchResultViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\UserResultViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\UploadResultViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\UploadSearchViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\SearchViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\UserSearchViewModel.cs" />
|
||||
<Compile Include="Areas\Admin\ViewModels\UserInfoViewModel.cs" />
|
||||
<Compile Include="Areas\API\APIAreaRegistration.cs" />
|
||||
<Compile Include="Areas\API\Controllers\APIController.cs" />
|
||||
@ -309,6 +310,7 @@
|
||||
<Compile Include="Areas\Vault\ViewModels\VaultItemViewModel.cs" />
|
||||
<Compile Include="Attributes\TeknikAuthorizeAttribute.cs" />
|
||||
<Compile Include="Hubs\IRCClientHub.cs" />
|
||||
<Compile Include="Modules\UserCheckModule.cs" />
|
||||
<Compile Include="Security\ITeknikPrincipal.cs" />
|
||||
<Compile Include="Security\TeknikPrincipal.cs" />
|
||||
<Compile Include="Filters\CORSActionFilter.cs" />
|
||||
@ -389,7 +391,7 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Areas\Admin\Scripts\UploadSearch.js" />
|
||||
<Content Include="Areas\Admin\Scripts\Search.js" />
|
||||
<Content Include="Areas\Admin\Scripts\UserSearch.js" />
|
||||
<Content Include="Areas\Admin\Scripts\UserInfo.js" />
|
||||
<Content Include="Areas\Blog\Content\Blog.css" />
|
||||
<Content Include="Areas\Blog\Scripts\Blog.js" />
|
||||
@ -628,10 +630,10 @@
|
||||
<Content Include="Areas\Help\Views\Help\Markdown.cshtml" />
|
||||
<Content Include="Areas\Help\Views\Help\Tools.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\web.config" />
|
||||
<Content Include="Areas\Admin\Views\Admin\Search.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\UserSearch.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\Dashboard.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\SearchResult.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\SearchResults.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\UserResult.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\Admin\UserResults.cshtml" />
|
||||
<Content Include="Areas\Admin\Views\_ViewStart.cshtml" />
|
||||
<Content Include="App_Data\MachineKey.config" />
|
||||
<Content Include="Areas\Admin\Views\Admin\UserInfo.cshtml" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
For more information on how to configure your ASP.NET application, please visit
|
||||
http://go.microsoft.com/fwlink/?LinkId=301880
|
||||
@ -55,6 +55,7 @@
|
||||
<remove name="FormsAuthentication" />
|
||||
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
|
||||
<add name="PerfModule" type="Teknik.Modules.PerformanceMonitorModule, Teknik" />
|
||||
<add name="UserCheckModule" type="Teknik.Modules.UserCheckModule, Teknik" />
|
||||
<remove name="UrlRoutingModule-4.0" />
|
||||
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
|
||||
</modules>
|
||||
@ -199,4 +200,4 @@
|
||||
<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>
|
||||
</configuration>
|
||||
|
8
Utilities/Utilities/AccountStatus.cs
Normal file
8
Utilities/Utilities/AccountStatus.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Teknik.Utilities
|
||||
{
|
||||
public enum AccountStatus
|
||||
{
|
||||
Active = 0,
|
||||
Banned = 1
|
||||
}
|
||||
}
|
@ -1,14 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Utilities
|
||||
{
|
||||
public enum AccountType
|
||||
{
|
||||
Basic,
|
||||
Premium
|
||||
Basic = 0,
|
||||
Premium = 1
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AccountStatus.cs" />
|
||||
<Compile Include="AccountType.cs" />
|
||||
<Compile Include="Cryptography\AES.cs" />
|
||||
<Compile Include="Cryptography\Aes128CFB.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user