1
0
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:
Uncled1023 2018-01-09 22:06:43 -08:00
parent e3e5a60de7
commit 51b4260f3c
30 changed files with 476 additions and 162 deletions

View File

@ -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"));
}
}
}
}

View File

@ -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"));
}
}
}
}

View File

@ -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">&times;</button>' + html.error.message + '</div>');
}
else {
$("#top_msg").css('display', 'none');
$("#top_msg").html('');
alert('Successfully changed the account status for \'' + username + '\' to: ' + selected);
}
}
}
});
});
});

View File

@ -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 @@
}
});
});
});
});

View File

@ -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; }
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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
{
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>
}
}

View File

@ -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>

View File

@ -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);
}
}
}
}

View File

@ -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
);
}
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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>();
}
}
}
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

View File

@ -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

View File

@ -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; }
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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")

View File

@ -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));
}
}
}
}

View File

@ -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)
{

View 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);
}
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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" />

View File

@ -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=\&quot;Web\&quot; /optionInfer+" />
</compilers>
</system.codedom>
</configuration>
</configuration>

View File

@ -0,0 +1,8 @@
namespace Teknik.Utilities
{
public enum AccountStatus
{
Active = 0,
Banned = 1
}
}

View File

@ -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
}
}

View File

@ -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" />