Fix Validation Hashes issue(s); Admin tidy-up

refactor-intermediate-models
Thomas Hounsell 2017-05-20 23:58:04 +01:00
parent dcf0a7a7fe
commit 20064159b9
30 changed files with 332 additions and 456 deletions

View File

@ -213,6 +213,14 @@ namespace MongoAuth
return task.Result.IsAcknowledged && task.Result.DeletedCount == 1;
}
public bool DeleteUser(Guid id)
{
Task<DeleteResult> task = _memberCollection.DeleteOneAsync(m => m.Id == id);
task.Wait();
return task.Result.IsAcknowledged && task.Result.DeletedCount == 1;
}
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
@ -404,7 +412,7 @@ namespace MongoAuth
using (SHA256 sha = SHA256.Create())
{
string content = $"{mm.Id}.{mm.PassSalt}.{ConfigurationManager.AppSettings["data:SecretKey"]}";
string content = $"{mm.Id}.{Convert.ToBase64String(mm.PassSalt)}.{ConfigurationManager.AppSettings["data:SecretKey"]}";
byte[] hashBytes = sha.ComputeHash(Encoding.UTF8.GetBytes(content));
return Base32Encoding.ToString(hashBytes);
@ -421,11 +429,10 @@ namespace MongoAuth
using (SHA256 sha = SHA256.Create())
{
string content = $"{mm.Id}.{mm.PassSalt}.{ConfigurationManager.AppSettings["data:SecretKey"]}";
string content = $"{mm.Id}.{Convert.ToBase64String(mm.PassSalt)}.{ConfigurationManager.AppSettings["data:SecretKey"]}";
byte[] hashBytes = sha.ComputeHash(Encoding.UTF8.GetBytes(content));
string expected = Base32Encoding.ToString(hashBytes);
bool success = string.Equals(expected, validate, StringComparison.InvariantCultureIgnoreCase);
if (success)

View File

@ -337,66 +337,5 @@ namespace BuildFeed.Model
{
await _buildCollection.DeleteOneAsync(Builders<Build>.Filter.Eq(b => b.Id, id));
}
public async Task MigrateAddedModifiedToHistory()
{
List<Build> builds = await Select();
foreach (Build bd in builds)
{
BuildDetails item = new BuildDetails
{
MajorVersion = bd.MajorVersion,
MinorVersion = bd.MinorVersion,
Number = bd.Number,
Revision = bd.Revision,
Lab = bd.Lab,
BuildTime = bd.BuildTime,
SourceType = bd.SourceType,
LeakDate = bd.LeakDate,
SourceDetails = bd.SourceDetails
};
if (bd.Added == DateTime.MinValue)
{
continue;
}
bd.History = new List<ItemHistory<BuildDetails>>
{
new ItemHistory<BuildDetails>
{
Type = ItemHistoryType.Added,
Time = bd.Added,
UserName = "",
Item = bd.Added == bd.Modified
? item
: null
}
};
if (bd.Modified != DateTime.MinValue && bd.Added != bd.Modified)
{
bd.History.Add(new ItemHistory<BuildDetails>
{
Type = ItemHistoryType.Edited,
Time = bd.Modified,
UserName = "",
Item = item
});
}
await _buildCollection.ReplaceOneAsync(Builders<Build>.Filter.Eq(b => b.Id, bd.Id), bd);
}
}
public async Task RegenerateCachedProperties()
{
List<Build> builds = await Select();
foreach (Build bd in builds)
{
bd.RegenerateCachedProperties();
await _buildCollection.ReplaceOneAsync(Builders<Build>.Filter.Eq(b => b.Id, bd.Id), bd);
}
}
}
}

View File

@ -137,8 +137,8 @@ namespace BuildFeed.Model
public class MetaItemKey
{
public MetaType Type { get; set; }
public string Value { get; set; }
public MetaType Type { get; set; }
public MetaItemKey()
{

View File

@ -19,6 +19,7 @@ namespace BuildFeed
action = "GetBuilds",
id = UrlParameter.Optional
});
routes.MapMvcAttributeRoutes();
}
}

View File

@ -0,0 +1,34 @@
using System.Web.Mvc;
using System.Web.Security;
using BuildFeed.Controllers;
namespace BuildFeed.Admin.Controllers
{
[RouteArea("admin")]
[RoutePrefix("")]
public class RootController : BaseController
{
[Authorize(Roles = "Administrators")]
[Route("")]
public ActionResult Index()
{
return View();
}
[Authorize(Users = "hounsell")]
[Route("setup")]
public ActionResult Setup()
{
if (!Roles.RoleExists("Administrators"))
{
Roles.CreateRole("Administrators");
}
if (!Roles.IsUserInRole("hounsell", "Administrators"))
{
Roles.AddUserToRole("hounsell", "Administrators");
}
return RedirectToAction(nameof(Index));
}
}
}

View File

@ -0,0 +1,21 @@
@{
ViewBag.Title = $"Administration | {InvariantTerms.SiteName}";
}
<h1>Administration</h1>
<ul>
<li>
@Html.ActionLink("Manage users", nameof(UsersController.Index), "Users")
<ul>
<li>@Html.ActionLink("View administrators", nameof(UsersController.Admins), "Users")</li>
</ul>
</li>
<li>
@Html.ActionLink("Manage metadata", nameof(MetaController.Index), "Meta")
</li>
@if (User.Identity.Name == "hounsell")
{
<li>@Html.ActionLink("Initial setup", nameof(RootController.Setup))</li>
}
</ul>

View File

@ -1,58 +0,0 @@
using System;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Security;
using BuildFeed.Controllers;
using BuildFeed.Model;
namespace BuildFeed.Areas.admin.Controllers
{
public class baseController : BaseController
{
[Authorize(Roles = "Administrators")]
// GET: admin/base
public ActionResult index()
{
return View();
}
[Authorize(Users = "hounsell")]
public ActionResult setup()
{
if (!Roles.RoleExists("Administrators"))
{
Roles.CreateRole("Administrators");
}
if (!Roles.IsUserInRole("hounsell", "Administrators"))
{
Roles.AddUserToRole("hounsell", "Administrators");
}
return RedirectToAction("index");
}
[Authorize(Users = "hounsell")]
public ActionResult exception()
{
throw new Exception("This is a test exception");
}
[Authorize(Users = "hounsell")]
public async Task<ActionResult> migrate()
{
BuildRepository _bModel = new BuildRepository();
await _bModel.MigrateAddedModifiedToHistory();
return RedirectToAction("index");
}
[Authorize(Users = "hounsell")]
public async Task<ActionResult> cache()
{
BuildRepository _bModel = new BuildRepository();
await _bModel.RegenerateCachedProperties();
return RedirectToAction("index");
}
}
}

View File

@ -5,20 +5,22 @@ using BuildFeed.Areas.admin.Models.ViewModel;
using BuildFeed.Controllers;
using BuildFeed.Model;
namespace BuildFeed.Areas.admin.Controllers
namespace BuildFeed.Admin.Controllers
{
[Authorize(Roles = "Administrators")]
public class metaController : BaseController
[RouteArea("admin")]
[RoutePrefix("meta")]
public class MetaController : BaseController
{
private readonly MetaItem _mModel;
public metaController()
public MetaController()
{
_mModel = new MetaItem();
}
// GET: admin/meta
public async Task<ActionResult> index()
[Route("")]
public async Task<ActionResult> Index()
{
return View(new MetaListing
{
@ -27,6 +29,7 @@ namespace BuildFeed.Areas.admin.Controllers
into b
orderby b.Key.ToString()
select b,
NewItems = from i in (from l in await _mModel.SelectUnusedLabs()
select new MetaItemModel
{
@ -59,7 +62,8 @@ namespace BuildFeed.Areas.admin.Controllers
});
}
public ActionResult create(MetaType type, string value)
[Route("create/{type}/{value}")]
public ActionResult Create(MetaType type, string value)
{
return View(new MetaItemModel
{
@ -72,20 +76,23 @@ namespace BuildFeed.Areas.admin.Controllers
}
[HttpPost]
public async Task<ActionResult> create(MetaItemModel meta)
[ValidateAntiForgeryToken]
[Route("create/{type}/{value}")]
public async Task<ActionResult> Create(MetaItemModel meta)
{
if (ModelState.IsValid)
{
await _mModel.Insert(meta);
return RedirectToAction("index");
return RedirectToAction(nameof(Index));
}
return View(meta);
}
public async Task<ActionResult> edit(MetaType type, string value)
[Route("edit/{type}/{value}")]
public async Task<ActionResult> Edit(MetaType type, string value)
{
return View("create",
return View(nameof(Create),
await _mModel.SelectById(new MetaItemKey
{
Type = type,
@ -94,15 +101,17 @@ namespace BuildFeed.Areas.admin.Controllers
}
[HttpPost]
public async Task<ActionResult> edit(MetaItemModel meta)
[ValidateAntiForgeryToken]
[Route("edit/{type}/{value}")]
public async Task<ActionResult> Edit(MetaItemModel meta)
{
if (ModelState.IsValid)
{
await _mModel.Update(meta);
return RedirectToAction("index");
return RedirectToAction("Index");
}
return View("create", meta);
return View(nameof(Create), meta);
}
}
}

View File

@ -6,62 +6,66 @@ using System.Web.Security;
using BuildFeed.Controllers;
using MongoAuth;
namespace BuildFeed.Areas.admin.Controllers
namespace BuildFeed.Admin.Controllers
{
[Authorize(Roles = "Administrators")]
public class usersController : BaseController
[RouteArea("admin")]
[RoutePrefix("users")]
public class UsersController : BaseController
{
// GET: admin/users
public ActionResult index() => View(Membership.GetAllUsers().Cast<MembershipUser>().OrderByDescending(m => m.IsApproved).ThenBy(m => m.UserName));
[Route]
public ActionResult Index() => View(Membership.GetAllUsers().Cast<MembershipUser>());
public ActionResult admins()
[Route("admins")]
public ActionResult Admins()
{
List<MembershipUser> admins = Roles.GetUsersInRole("Administrators").Select(Membership.GetUser).ToList();
return View(admins.OrderByDescending(m => m.UserName));
}
public ActionResult promote(string id)
{
Roles.AddUserToRole(id, "Administrators");
return RedirectToAction("Index");
}
public ActionResult demote(string id)
{
Roles.RemoveUserFromRole(id, "Administrators");
return RedirectToAction("Index");
}
public ActionResult approve(Guid id)
[Route("approve/{id:guid}")]
public ActionResult Approve(Guid id)
{
MongoMembershipProvider provider = Membership.Provider as MongoMembershipProvider;
provider?.ChangeApproval(id, true);
return RedirectToAction("Index");
return RedirectToAction(nameof(Index));
}
public ActionResult unapprove(Guid id)
[Route("unapprove/{id:guid}")]
public ActionResult Unapprove(Guid id)
{
MongoMembershipProvider provider = Membership.Provider as MongoMembershipProvider;
provider?.ChangeApproval(id, false);
return RedirectToAction("Index");
return RedirectToAction(nameof(Index));
}
public ActionResult @lock(Guid id)
[Route("lock/{id:guid}")]
public ActionResult Lock(Guid id)
{
MongoMembershipProvider provider = Membership.Provider as MongoMembershipProvider;
provider?.ChangeLockStatus(id, true);
return RedirectToAction("Index");
return RedirectToAction(nameof(Index));
}
public ActionResult unlock(Guid id)
[Route("unlock/{id:guid}")]
public ActionResult Unlock(Guid id)
{
MongoMembershipProvider provider = Membership.Provider as MongoMembershipProvider;
provider?.ChangeLockStatus(id, false);
return RedirectToAction("Index");
return RedirectToAction(nameof(Index));
}
public ActionResult cleanup()
[Route("delete/{id:guid}")]
public ActionResult Delete(Guid id)
{
MongoMembershipProvider provider = Membership.Provider as MongoMembershipProvider;
provider?.DeleteUser(id);
return RedirectToAction(nameof(Index));
}
[Route("cleanup")]
public ActionResult Cleanup()
{
MembershipUserCollection users = Membership.GetAllUsers();
@ -74,7 +78,7 @@ namespace BuildFeed.Areas.admin.Controllers
}
}
return RedirectToAction("index");
return RedirectToAction(nameof(Index));
}
}
}

View File

@ -1,23 +0,0 @@
@{
ViewBag.Title = "Administration | BuildFeed";
}
<h1>Administration</h1>
<ul>
<li>
@Html.ActionLink("Manage users", "index", "users")
<ul>
<li>@Html.ActionLink("View administrators", "admins", "users")</li>
</ul>
</li>
<li>
@Html.ActionLink("Manage metadata", "index", "meta")
</li>
@if (User.Identity.Name == "hounsell")
{
<li>@Html.ActionLink("Exception test", "exception")</li>
<li>@Html.ActionLink("Initial setup", "setup")</li>
<li>@Html.ActionLink("Regenerate cached properties", "cache")</li>
}
</ul>

View File

@ -1,9 +1,9 @@
@model BuildFeed.Model.MetaItemModel
@{
ViewBag.Title = $"Add metadata for {Model.Id.Value} | BuildFeed";
ViewBag.Title = $"Add metadata for {Model.Id.Value} | {InvariantTerms.SiteName}";
}
<h1>@($"Add metadata for {Model.Id.Value}") </h1>
<h1>@($"Add metadata for {Model.Id.Value}")</h1>
@using (Html.BeginForm())
@ -13,47 +13,36 @@
@Html.HiddenFor(model => model.Id.Type)
@Html.HiddenFor(model => model.Id.Value)
<div class="form-horizontal">
<div class="form-group">
@Html.LabelFor(model => model.MetaDescription, new
<div class="form-group">
@Html.LabelFor(model => model.MetaDescription)
<div class="wide-group">
@Html.TextAreaFor(model => model.MetaDescription, new
{
@class = "control-label"
rows = "4"
})
<div class="wide-group">
@Html.TextAreaFor(model => model.MetaDescription, new
{
@class = "form-control",
rows = "4"
})
<div class="help-block">
<span id="meta-count">0</span> characters
@Html.ValidationMessageFor(model => model.MetaDescription)
</div>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.PageContent, new
{
@class = "control-label"
})
<div class="wide-group">
@Html.TextAreaFor(model => model.PageContent, new
{
@class = "form-control"
})
<div class="help-block">
@Html.ValidationMessageFor(model => model.PageContent)
</div>
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Add metadata" class="btn btn-primary" />
<span id="meta-count">0</span> characters
@Html.ValidationMessageFor(model => model.MetaDescription)
</div>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.PageContent)
<div class="wide-group">
@Html.TextAreaFor(model => model.PageContent)
<div>
@Html.ValidationMessageFor(model => model.PageContent)
</div>
</div>
</div>
<div class="form-group">
<span class="label-placeholder"></span>
<div>
<input type="submit" value="Add metadata" />
</div>
</div>
}
@section Scripts

View File

@ -2,15 +2,15 @@
@model BuildFeed.Areas.admin.Models.ViewModel.MetaListing
@{
ViewBag.Title = "Metadata | BuildFeed";
ViewBag.Title = $"Manage metadata | {InvariantTerms.SiteName}";
}
<h1>Manage metadata</h1>
<ul>
<li>@Html.ActionLink("Return to admin panel", "index", "base")</li>
<li>@Html.ActionLink("Return to admin panel", nameof(RootController.Index), "Root")</li>
</ul>
<h3>Current items</h3>
<table class="table table-striped table-bordered table-admin">
<table>
<thead>
<tr>
<th>Name</th>
@ -30,7 +30,7 @@
<tr>
<td>@item.Id.Value</td>
<td>
@Html.ActionLink("Edit", "edit", new
@Html.ActionLink("Edit", nameof(MetaController.Edit), new
{
type = item.Id.Type,
value = item.Id.Value
@ -44,8 +44,8 @@
}
</tbody>
</table>
<h3>Add new metadata</h3>
<table class="table table-striped table-bordered table-admin">
<h3>Add new items</h3>
<table>
<thead>
<tr>
<th>Name</th>
@ -65,7 +65,7 @@
<tr>
<td>@item.Id.Value</td>
<td>
@Html.ActionLink("Create", "create", new
@Html.ActionLink("Create", nameof(MetaController.Create), new
{
type = item.Id.Type,
value = item.Id.Value

View File

@ -8,8 +8,8 @@
<h1>View administrators</h1>
<ul>
<li>@Html.ActionLink("Manage users", "index")</li>
<li>@Html.ActionLink("Return to admin panel", "index", "base")</li>
<li>@Html.ActionLink("Manage users", "Index")</li>
<li>@Html.ActionLink("Return to admin panel", "Index", "Root")</li>
</ul>
<table class="table table-striped table-bordered table-admin">

View File

@ -2,15 +2,15 @@
@model IEnumerable<MembershipUser>
@{
ViewBag.Title = "Manage users | BuildFeed";
ViewBag.Title = $"Manage users | {InvariantTerms.SiteName}";
}
<h1>Manage users</h1>
<ul>
<li>@Html.ActionLink("View administrators", "admins")</li>
<li>@Html.ActionLink("Clean-up old unapproved users", "cleanup")</li>
<li>@Html.ActionLink("Return to admin panel", "index", "base")</li>
<li>@Html.ActionLink("View administrators", "Admins")</li>
<li>@Html.ActionLink("Clean-up old unapproved users", "Cleanup")</li>
<li>@Html.ActionLink("Return to admin panel", "Index", "Root")</li>
</ul>
<table id="user-table">
@ -33,6 +33,7 @@
</th>
<th style="width: 100px;"></th>
<th style="width: 100px;"></th>
<th style="width: 100px;"></th>
</tr>
</thead>
<tbody>
@ -60,14 +61,14 @@
</td>
<td class="text-right">
@(mu.IsApproved
? Html.ActionLink("Unapprove", "unapprove", new
? Html.ActionLink("Unapprove", nameof(UsersController.Unapprove), new
{
id = mu.ProviderUserKey
}, new
{
@class = "button delete-button"
})
: Html.ActionLink("Approve", "approve", new
: Html.ActionLink("Approve", nameof(UsersController.Approve), new
{
id = mu.ProviderUserKey
}, new
@ -77,14 +78,14 @@
</td>
<td class="text-right">
@(!mu.IsLockedOut
? Html.ActionLink("Lock", "lock", new
? Html.ActionLink("Lock", nameof(UsersController.Lock), new
{
id = mu.ProviderUserKey
}, new
{
@class = "button delete-button"
})
: Html.ActionLink("Unlock", "unlock", new
: Html.ActionLink("Unlock", nameof(UsersController.Unlock), new
{
id = mu.ProviderUserKey
}, new
@ -92,6 +93,16 @@
@class = "button add-button"
}))
</td>
<td>
@Html.ActionLink("Delete", nameof(UsersController.Delete), new
{
id = mu.ProviderUserKey
}, new
{
@class = "button delete-button",
onclick = @"return !(confirm(""Are you sure you want to delete this user?"") === false);"
})
</td>
</tr>
}
</tbody>

View File

@ -17,6 +17,8 @@
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="BuildFeed" />
<add namespace="BuildFeed.Local" />
<add namespace="BuildFeed.Admin.Controllers" />
</namespaces>
</pages>
</system.web.webPages.razor>

View File

@ -8,22 +8,6 @@ namespace BuildFeed.Areas.admin
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute("Meta",
"admin/{controller}/{action}/{type}/{value}",
new
{
action = "index",
controller = "meta"
});
context.MapRoute("Admin (Default)",
"admin/{controller}/{action}/{id}",
new
{
action = "index",
controller = "base",
id = UrlParameter.Optional
});
}
}
}

View File

@ -158,17 +158,17 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Areas\admin\Controllers\baseController.cs" />
<Compile Include="Areas\admin\Controllers\metaController.cs" />
<Compile Include="Areas\admin\Models\ViewModel\MetaListing.cs" />
<Compile Include="Areas\Admin\Controllers\RootController.cs" />
<Compile Include="Areas\Admin\Controllers\MetaController.cs" />
<Compile Include="Areas\Admin\Models\ViewModel\MetaListing.cs" />
<Compile Include="Code\Base32Encoding.cs" />
<Compile Include="Code\CustomContentTypeAttribute.cs" />
<Compile Include="Code\DateTimeModelBinder.cs" />
<Compile Include="Code\DisplayHelpers.cs" />
<Compile Include="App_Start\FilterConfig.cs" />
<Compile Include="App_Start\RouteConfig.cs" />
<Compile Include="Areas\admin\adminAreaRegistration.cs" />
<Compile Include="Areas\admin\Controllers\usersController.cs" />
<Compile Include="Areas\Admin\adminAreaRegistration.cs" />
<Compile Include="Areas\Admin\Controllers\UsersController.cs" />
<Compile Include="Code\EmailManager\EmailManager.cs" />
<Compile Include="Code\EmailManager\RegistrationEmail.cs" />
<Compile Include="Code\MvcIntrinsics.cs" />
@ -210,14 +210,14 @@
<Content Include="content\tile\tiny.png" />
<Content Include="favicon.ico" />
<Content Include="Global.asax" />
<Content Include="Areas\admin\Views\web.config" />
<Content Include="Areas\admin\Views\users\index.cshtml" />
<Content Include="Areas\admin\Views\_ViewStart.cshtml" />
<Content Include="Areas\Admin\Views\web.config" />
<Content Include="Areas\Admin\Views\Users\index.cshtml" />
<Content Include="Areas\Admin\Views\_ViewStart.cshtml" />
<Content Include="content\Web.config" />
<Content Include="Areas\admin\Views\base\index.cshtml" />
<Content Include="Areas\admin\Views\users\admins.cshtml" />
<Content Include="Areas\admin\Views\meta\index.cshtml" />
<Content Include="Areas\admin\Views\meta\create.cshtml" />
<Content Include="Areas\Admin\Views\Root\index.cshtml" />
<Content Include="Areas\Admin\Views\Users\admins.cshtml" />
<Content Include="Areas\Admin\Views\Meta\index.cshtml" />
<Content Include="Areas\Admin\Views\Meta\create.cshtml" />
<Content Include="res\css\dark.css">
<DependentUpon>dark.scss</DependentUpon>
</Content>

View File

@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=areas/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=code_005Cemailmanager/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -108,7 +108,7 @@ namespace BuildFeed.Controllers
MongoMembershipProvider provider = (MongoMembershipProvider)Membership.Provider;
Guid id = (Guid)mu.ProviderUserKey;
string hash = (await provider.GenerateValidationHash(id)).ToLower();
string hash = (await provider.GenerateValidationHash(id)).ToLowerInvariant();
string fullUrl = Request.Url?.GetLeftPart(UriPartial.Authority) + Url.Action("Validate",
"Account",

View File

@ -22,9 +22,9 @@ namespace BuildFeed
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
RouteConfig.RegisterRoutes(RouteTable.Routes);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
DateTimeModelBinder db = new DateTimeModelBinder();

View File

@ -20,52 +20,42 @@
</p>
}
<div class="form-horizontal">
<div class="form-group">
@Html.LabelFor(model => model.UserName, new
<div class="form-group">
@Html.LabelFor(model => model.UserName)
<div>
@Html.TextBoxFor(model => model.UserName)
@Html.ValidationMessageFor(model => model.UserName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Password)
<div>
@Html.PasswordFor(model => model.Password)
@Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group">
<span class="label-placeholder"></span>
<div>
<label for="@Html.IdFor(model => model.RememberMe)">
@Html.CheckBoxFor(model => model.RememberMe) @Html.DisplayNameFor(model => model.RememberMe)
</label>
</div>
</div>
<div class="form-group">
<span class="label-placeholder"></span>
<div>
<input type="submit" value="@VariantTerms.Support_Login" /> &ensp;
@Html.ActionLink(VariantTerms.Support_Register, nameof(AccountController.Register), new
{
@class = "control-label col-md-2"
})
<div>
@Html.TextBoxFor(model => model.UserName, new
{
@class = "form-control"
})
@Html.ValidationMessageFor(model => model.UserName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Password, new
controller = "Account"
}, new
{
@class = "control-label col-md-2"
@class = "button"
})
<div>
@Html.PasswordFor(model => model.Password, new
{
@class = "form-control"
})
@Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group">
<div>
<label for="@Html.IdFor(model => model.RememberMe)" class="checkbox checkbox-inline">@Html.CheckBoxFor(model => model.RememberMe) @Html.DisplayNameFor(model => model.RememberMe)</label>
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="@VariantTerms.Support_Login" class="btn btn-primary" /> &ensp;
@Html.ActionLink(VariantTerms.Support_Register, nameof(AccountController.Register), new
{
controller = "Account"
}, new
{
@class = "btn btn-default"
})
</div>
</div>
</div>
}

View File

@ -19,65 +19,34 @@
</p>
}
<div class="form-horizontal">
<div class="form-group">
@Html.LabelFor(model => model.OldPassword, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.PasswordFor(model => model.OldPassword, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.OldPassword)
</div>
<div class="form-group">
@Html.LabelFor(model => model.OldPassword)
<div>
@Html.PasswordFor(model => model.OldPassword)
@Html.ValidationMessageFor(model => model.OldPassword)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.NewPassword, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.PasswordFor(model => model.NewPassword, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.NewPassword)
</div>
<div class="form-group">
@Html.LabelFor(model => model.NewPassword)
<div>
@Html.PasswordFor(model => model.NewPassword)
@Html.ValidationMessageFor(model => model.NewPassword)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfirmNewPassword, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.PasswordFor(model => model.ConfirmNewPassword, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.ConfirmNewPassword)
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfirmNewPassword)
<div>
@Html.PasswordFor(model => model.ConfirmNewPassword)
@Html.ValidationMessageFor(model => model.ConfirmNewPassword)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="@VariantTerms.Support_ChangePassword" class="btn btn-primary" />
</div>
<div class="form-group">
<span class="label-placeholder"></span>
<div>
<input type="submit" value="@VariantTerms.Support_ChangePassword" class="btn btn-primary" />
</div>
</div>
}

View File

@ -19,83 +19,42 @@
</p>
}
<div class="form-horizontal">
<div class="form-group">
@Html.LabelFor(model => model.UserName, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.TextBoxFor(model => model.UserName, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="form-group">
@Html.LabelFor(model => model.UserName)
<div>
@Html.TextBoxFor(model => model.UserName)
@Html.ValidationMessageFor(model => model.UserName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Password, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.PasswordFor(model => model.Password, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.Password)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Password)
<div>
@Html.PasswordFor(model => model.Password)
@Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfirmPassword, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.PasswordFor(model => model.ConfirmPassword, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfirmPassword)
<div>
@Html.PasswordFor(model => model.ConfirmPassword)
@Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmailAddress, new
{
@class = "control-label col-md-2"
})
<div class="col-md-10">
<div class="row">
<div class="col-sm-6">
@Html.TextBoxFor(model => model.EmailAddress, new
{
@class = "form-control"
})
</div>
</div>
@Html.ValidationMessageFor(model => model.EmailAddress)
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmailAddress)
<div class="col-md-10">
@Html.TextBoxFor(model => model.EmailAddress)
@Html.ValidationMessageFor(model => model.EmailAddress)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="@VariantTerms.Support_Register" class="btn btn-primary" />
</div>
<div class="form-group">
<span class="label-placeholder"></span>
<div>
<input type="submit" value="@VariantTerms.Support_Register" />
</div>
</div>
}

View File

@ -25,12 +25,18 @@
</ul>
}
<p>@VariantTerms.Bulk_Instructions</p>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-group">
<span class="label-placeholder"></span>
<div>
@VariantTerms.Bulk_Instructions
</div>
</div>
<div class="form-group">
<label for="@Html.IdFor(m => m.Builds)">@VariantTerms.Bulk_Builds</label>
<div>
@ -42,9 +48,9 @@
</div>
<div class="form-group">
<label></label>
<span class="label-placeholder"></span>
<div>
<label>
<label for="@Html.IdFor(m => m.SendNotifications)">
@Html.CheckBoxFor(m => m.SendNotifications)
@VariantTerms.Bulk_SendNotifications
</label>
@ -52,7 +58,7 @@
</div>
<div class="form-group">
<label></label>
<span class="label-placeholder"></span>
<div>
<input type="submit" value="@VariantTerms.Bulk_AddBuilds" class="button" />
</div>

View File

@ -24,7 +24,6 @@ else
<input id="quickpaste" type="text" />
</div>
</div>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@ -107,11 +106,11 @@ else
</div>
<div class="form-group">
<label></label>
<span class="label-placeholder"></span>
<div>
<input type="submit" value="@((string)ViewContext.RouteData.Values["action"] == nameof(FrontController.AddBuild)
? VariantTerms.Common_AddBuild
: VariantTerms.Front_EditBuild)" class="btn btn-primary" />
: VariantTerms.Front_EditBuild)" />
&ensp;
<a href="/" onclick="window.history.back();return false;" class="button">
@VariantTerms.Front_ReturnToListing

View File

@ -132,9 +132,9 @@
if (Roles.IsUserInRole("Administrators"))
{
<li>
<a href="@Url.Action("index", new
<a href="@Url.Action("Index", new
{
controller = "base",
controller = "Root",
area = "admin"
})" title="@VariantTerms.Common_Admin">
<i class="fa fa-fw fa-cogs"></i> @VariantTerms.Common_Admin

View File

@ -87,7 +87,7 @@
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Frame-Options" value="DENY" />
<add name="X-XSS-Protection" value="1; mode=block" />
<add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
<add name="Referrer-Policy" value="origin-when-cross-origin" />
</customHeaders>
</httpProtocol>
<handlers>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -9,6 +9,11 @@ body
box-sizing: border-box;
}
input, textarea, select
{
font-family: 'Fira Sans', sans-serif;
}
a
{
text-decoration: none;
@ -135,11 +140,20 @@ table
.field-validation-error,
.text-danger
{
display: block;
margin: #{(1em / 3)} 0;
color: $strong-red;
}
.text-success
{
color: $strong-green;
}
.field-validation-error
{
margin: #{(1em / 3)} 0;
display: block;
}
a.button,
input[type=submit].button
{
@ -616,27 +630,35 @@ article
display: flex;
flex-wrap: wrap;
> label
> label,
> .label-placeholder
{
width: 20%;
max-width: 240px;
min-width: 120px;
max-width: 280px;
min-width: 160px;
text-align: left;
font-weight: bold;
margin-right: 1em;
display: inline-block;
display: block;
vertical-align: top;
margin-top: #{(1em / 4)};
flex-grow: 1;
text-align: right;
@media(max-width: 479px)
{
width: 100%;
max-width: none;
text-align: left;
}
}
> div
{
margin-left: calc(20% + 1em);
width: 40%;
min-width: 240px;
max-width: 560px;
display: inline-block;
display: block;
vertical-align: top;
flex-grow: 2;
@ -647,6 +669,7 @@ article
border: $border-size solid;
padding: #{(1em / 3)} #{(1em / 2)};
border-radius: #{(1em / 6)};
font-size: 1em;
line-height: 1em;
border-color: #888;
}
@ -684,13 +707,22 @@ article
{
display: inline-block;
vertical-align: middle;
padding: #{(1em / 3)} 1em;
padding: #{(1em / 2)} 1em #{(1em / 3)};
background-color: $strong-green;
color: #fff;
text-decoration: none;
border-radius: #{(1em / 6)};
border: 0;
line-height: 1.6;
font-size: 1em;
}
a.button
{
vertical-align: middle;
padding: #{(1em / 2)} 1em #{(1em / 3)};
line-height: 1.6;
font-size: 1em;
}
&.wide-group