mirror of
https://gitlab.com/buildfeed/BuildFeed.git
synced 2024-03-22 21:10:34 +08:00
Fix Validation Hashes issue(s); Admin tidy-up
This commit is contained in:
parent
dcf0a7a7fe
commit
20064159b9
|
@ -213,6 +213,14 @@ public override bool DeleteUser(string username, bool deleteAllRelatedData)
|
|||
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 @@ public async Task<string> GenerateValidationHash(Guid id)
|
|||
|
||||
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 @@ public async Task<bool> ValidateUserFromHash(Guid id, string validate)
|
|||
|
||||
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)
|
||||
|
|
|
@ -337,66 +337,5 @@ public async Task DeleteById(Guid id)
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -137,8 +137,8 @@ public async Task DeleteById(MetaItemKey id)
|
|||
|
||||
public class MetaItemKey
|
||||
{
|
||||
public MetaType Type { get; set; }
|
||||
public string Value { get; set; }
|
||||
public MetaType Type { get; set; }
|
||||
|
||||
public MetaItemKey()
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ public static void RegisterRoutes(RouteCollection routes)
|
|||
action = "GetBuilds",
|
||||
id = UrlParameter.Optional
|
||||
});
|
||||
|
||||
routes.MapMvcAttributeRoutes();
|
||||
}
|
||||
}
|
||||
|
|
34
BuildFeed/Areas/Admin/Controllers/RootController.cs
Normal file
34
BuildFeed/Areas/Admin/Controllers/RootController.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
21
BuildFeed/Areas/Admin/Views/Root/index.cshtml
Normal file
21
BuildFeed/Areas/Admin/Views/Root/index.cshtml
Normal 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>
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,20 +5,22 @@
|
|||
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 @@ group i by i.Id.Type
|
|||
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 @@ select b
|
|||
});
|
||||
}
|
||||
|
||||
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 @@ public ActionResult create(MetaType type, string value)
|
|||
}
|
||||
|
||||
[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 @@ await _mModel.SelectById(new MetaItemKey
|
|||
}
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,62 +6,66 @@
|
|||
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 @@ public ActionResult cleanup()
|
|||
}
|
||||
}
|
||||
|
||||
return RedirectToAction("index");
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -8,22 +8,6 @@ public class AdminAreaRegistration : AreaRegistration
|
|||
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -108,7 +108,7 @@ public async Task<ActionResult> Register(RegistrationUser ru)
|
|||
|
||||
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",
|
||||
|
|
|
@ -22,9 +22,9 @@ protected void Application_Start()
|
|||
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();
|
||||
|
||||
|
|
|
@ -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" />  
|
||||
@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" />  
|
||||
@Html.ActionLink(VariantTerms.Support_Register, nameof(AccountController.Register), new
|
||||
{
|
||||
controller = "Account"
|
||||
}, new
|
||||
{
|
||||
@class = "btn btn-default"
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)" />
|
||||
 
|
||||
<a href="/" onclick="window.history.back();return false;" class="button">
|
||||
@VariantTerms.Front_ReturnToListing
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user