mirror of
https://gitlab.com/buildfeed/BuildFeed.git
synced 2024-03-22 21:10:34 +08:00
Refresh Pt 2
This commit is contained in:
parent
a55b8ada0f
commit
e11ac1cd38
|
@ -1,10 +1,10 @@
|
|||
using System;
|
||||
using RedisAuth;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Security;
|
||||
using BuildFeed.Auth;
|
||||
|
||||
namespace BuildFeed.Areas.admin.Controllers
|
||||
{
|
||||
|
|
|
@ -1,496 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web.Security;
|
||||
using NServiceKit.DataAnnotations;
|
||||
using NServiceKit.DesignPatterns.Model;
|
||||
using NServiceKit.Redis;
|
||||
using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
|
||||
|
||||
namespace BuildFeed.Auth
|
||||
{
|
||||
public class RedisMembershipProvider : MembershipProvider
|
||||
{
|
||||
private bool _enablePasswordReset = true;
|
||||
private int _maxInvalidPasswordAttempts = 5;
|
||||
private int _minRequiredNonAlphanumericCharacters = 1;
|
||||
private int _minRequriedPasswordLength = 12;
|
||||
private int _passwordAttemptWindow = 60;
|
||||
private bool _requiresUniqueEmail = true;
|
||||
|
||||
public override string ApplicationName
|
||||
{
|
||||
get { return ""; }
|
||||
set { }
|
||||
}
|
||||
|
||||
public override bool EnablePasswordReset
|
||||
{
|
||||
get { return _enablePasswordReset; }
|
||||
}
|
||||
|
||||
public override bool EnablePasswordRetrieval
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override int MaxInvalidPasswordAttempts
|
||||
{
|
||||
get { return _maxInvalidPasswordAttempts; }
|
||||
}
|
||||
|
||||
public override int MinRequiredNonAlphanumericCharacters
|
||||
{
|
||||
get { return _minRequiredNonAlphanumericCharacters; }
|
||||
}
|
||||
|
||||
public override int MinRequiredPasswordLength
|
||||
{
|
||||
get { return _minRequriedPasswordLength; }
|
||||
}
|
||||
|
||||
public override int PasswordAttemptWindow
|
||||
{
|
||||
get { return _passwordAttemptWindow; }
|
||||
}
|
||||
|
||||
public override MembershipPasswordFormat PasswordFormat
|
||||
{
|
||||
get { return MembershipPasswordFormat.Hashed; }
|
||||
}
|
||||
|
||||
public override string PasswordStrengthRegularExpression
|
||||
{
|
||||
get { return ""; }
|
||||
}
|
||||
|
||||
public override bool RequiresQuestionAndAnswer
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool RequiresUniqueEmail
|
||||
{
|
||||
get { return _requiresUniqueEmail; }
|
||||
}
|
||||
|
||||
public override void Initialize(string name, NameValueCollection config)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new ArgumentNullException("config");
|
||||
}
|
||||
|
||||
base.Initialize(name, config);
|
||||
|
||||
_enablePasswordReset = tryReadBool(config["enablePasswordReset"], _enablePasswordReset);
|
||||
_maxInvalidPasswordAttempts = tryReadInt(config["maxInvalidPasswordAttempts"], _maxInvalidPasswordAttempts);
|
||||
_minRequiredNonAlphanumericCharacters = tryReadInt(config["minRequiredNonAlphanumericCharacters"], _minRequiredNonAlphanumericCharacters);
|
||||
_minRequriedPasswordLength = tryReadInt(config["minRequriedPasswordLength"], _minRequriedPasswordLength);
|
||||
_passwordAttemptWindow = tryReadInt(config["passwordAttemptWindow"], _passwordAttemptWindow);
|
||||
_requiresUniqueEmail = tryReadBool(config["requiresUniqueEmail"], _requiresUniqueEmail);
|
||||
}
|
||||
|
||||
public override bool ChangePassword(string username, string oldPassword, string newPassword)
|
||||
{
|
||||
bool isAuthenticated = ValidateUser(username, oldPassword);
|
||||
|
||||
if (isAuthenticated)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetAll().SingleOrDefault(m => m.UserName.ToLower() == username.ToLower());
|
||||
|
||||
byte[] salt = new byte[24];
|
||||
byte[] hash = calculateHash(newPassword, ref salt);
|
||||
|
||||
rm.PassSalt = salt;
|
||||
rm.PassHash = hash;
|
||||
|
||||
client.Store(rm);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
if (password.Length < MinRequiredPasswordLength)
|
||||
{
|
||||
status = MembershipCreateStatus.InvalidPassword;
|
||||
return null;
|
||||
}
|
||||
|
||||
MembershipUser mu = null;
|
||||
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var users = client.GetAll();
|
||||
|
||||
if (users.Any(m => m.UserName.ToLower() == username.ToLower()))
|
||||
{
|
||||
status = MembershipCreateStatus.DuplicateUserName;
|
||||
}
|
||||
else if (users.Any(m => m.EmailAddress.ToLower() == email.ToLower()))
|
||||
{
|
||||
status = MembershipCreateStatus.DuplicateEmail;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] salt = new byte[24];
|
||||
byte[] hash = calculateHash(password, ref salt);
|
||||
|
||||
RedisMember rm = new RedisMember()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
UserName = username,
|
||||
PassHash = hash,
|
||||
PassSalt = salt,
|
||||
EmailAddress = email,
|
||||
|
||||
IsApproved = false,
|
||||
IsLockedOut = false,
|
||||
|
||||
CreationDate = DateTime.Now,
|
||||
LastLoginDate = DateTime.MinValue,
|
||||
LastActivityDate = DateTime.MinValue,
|
||||
LastLockoutDate = DateTime.MinValue
|
||||
};
|
||||
|
||||
client.Store(rm);
|
||||
|
||||
status = MembershipCreateStatus.Success;
|
||||
mu = new MembershipUser(this.Name, rm.UserName, rm.Id, rm.EmailAddress, "", "", rm.IsApproved, rm.IsLockedOut, rm.CreationDate, rm.LastLoginDate, rm.LastActivityDate, DateTime.MinValue, rm.LastLockoutDate);
|
||||
}
|
||||
}
|
||||
|
||||
return mu;
|
||||
}
|
||||
|
||||
private static byte[] calculateHash(string password, ref byte[] salt)
|
||||
{
|
||||
if (!salt.Any(v => v != 0))
|
||||
{
|
||||
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
|
||||
rng.GetBytes(salt);
|
||||
}
|
||||
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
|
||||
|
||||
byte[] hashPlaintext = new byte[salt.Length + passwordBytes.Length];
|
||||
|
||||
passwordBytes.CopyTo(hashPlaintext, 0);
|
||||
salt.CopyTo(hashPlaintext, passwordBytes.Length);
|
||||
|
||||
SHA512CryptoServiceProvider sha = new SHA512CryptoServiceProvider();
|
||||
byte[] hash = sha.ComputeHash(hashPlaintext);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override bool DeleteUser(string username, bool deleteAllRelatedData)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var user = client.GetAll().SingleOrDefault(m => m.UserName.ToLower() == username.ToLower());
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
client.DeleteById(user.Id);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
MembershipUserCollection muc = new MembershipUserCollection();
|
||||
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var users = client.GetAll();
|
||||
|
||||
totalRecords = users.Count;
|
||||
var pageItems = users.Skip(pageIndex * pageSize).Take(pageSize);
|
||||
|
||||
foreach (var rm in pageItems)
|
||||
{
|
||||
muc.Add(new MembershipUser(this.Name, rm.UserName, rm.Id, rm.EmailAddress, "", "", rm.IsApproved, rm.IsLockedOut, rm.CreationDate, rm.LastLoginDate, rm.LastActivityDate, DateTime.MinValue, rm.LastLockoutDate));
|
||||
}
|
||||
}
|
||||
|
||||
return muc;
|
||||
}
|
||||
|
||||
public override int GetNumberOfUsersOnline()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string GetPassword(string username, string answer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUser GetUser(string username, bool userIsOnline)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetAll().SingleOrDefault(m => m.UserName.ToLower() == username.ToLower());
|
||||
|
||||
if (rm == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new MembershipUser(this.Name, rm.UserName, rm.Id, rm.EmailAddress, "", "", rm.IsApproved, rm.IsLockedOut, rm.CreationDate, rm.LastLoginDate, rm.LastActivityDate, DateTime.MinValue, rm.LastLockoutDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetById(providerUserKey);
|
||||
|
||||
if (rm == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new MembershipUser(this.Name, rm.UserName, rm.Id, rm.EmailAddress, "", "", rm.IsApproved, rm.IsLockedOut, rm.CreationDate, rm.LastLoginDate, rm.LastActivityDate, DateTime.MinValue, rm.LastLockoutDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetUserNameByEmail(string email)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetAll().SingleOrDefault(m => m.EmailAddress.ToLower() == email.ToLower());
|
||||
|
||||
if (rm == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
return rm.UserName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ResetPassword(string username, string answer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void ChangeApproval(Guid Id, bool newStatus)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetById(Id);
|
||||
|
||||
if (rm != null)
|
||||
{
|
||||
rm.IsApproved = newStatus;
|
||||
client.Store(rm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeLockStatus(Guid Id, bool newStatus)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetById(Id);
|
||||
|
||||
if (rm != null)
|
||||
{
|
||||
rm.IsLockedOut = newStatus;
|
||||
|
||||
if (newStatus)
|
||||
{
|
||||
rm.LastLockoutDate = DateTime.Now;
|
||||
}
|
||||
else
|
||||
{
|
||||
rm.LockoutWindowAttempts = 0;
|
||||
rm.LockoutWindowStart = DateTime.MinValue;
|
||||
}
|
||||
|
||||
client.Store(rm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool UnlockUser(string userName)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetAll().SingleOrDefault(m => m.UserName.ToLower() == userName.ToLower());
|
||||
|
||||
rm.IsLockedOut = false;
|
||||
|
||||
client.Store(rm);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateUser(MembershipUser user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool ValidateUser(string username, string password)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisMember>();
|
||||
var rm = client.GetAll().SingleOrDefault(m => m.UserName.ToLower() == username.ToLower());
|
||||
|
||||
if (rm == null || !(rm.IsApproved && !rm.IsLockedOut))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] salt = rm.PassSalt;
|
||||
byte[] hash = calculateHash(password, ref salt);
|
||||
|
||||
bool isFail = false;
|
||||
|
||||
for (int i = 0; i > hash.Length; i++)
|
||||
{
|
||||
isFail |= (hash[i] != rm.PassHash[i]);
|
||||
}
|
||||
|
||||
if (isFail)
|
||||
{
|
||||
if (rm.LockoutWindowStart == DateTime.MinValue)
|
||||
{
|
||||
rm.LockoutWindowStart = DateTime.Now;
|
||||
rm.LockoutWindowAttempts = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rm.LockoutWindowStart.AddMinutes(PasswordAttemptWindow) > DateTime.Now)
|
||||
{
|
||||
// still within window
|
||||
rm.LockoutWindowAttempts++;
|
||||
if (rm.LockoutWindowAttempts >= MaxInvalidPasswordAttempts)
|
||||
{
|
||||
rm.IsLockedOut = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// outside of window, reset
|
||||
rm.LockoutWindowStart = DateTime.Now;
|
||||
rm.LockoutWindowAttempts = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rm.LastLoginDate = DateTime.Now;
|
||||
rm.LockoutWindowStart = DateTime.MinValue;
|
||||
rm.LockoutWindowAttempts = 0;
|
||||
}
|
||||
client.Store(rm);
|
||||
|
||||
return !isFail;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool tryReadBool(string config, bool defaultValue)
|
||||
{
|
||||
bool temp = false;
|
||||
bool success = bool.TryParse(config, out temp);
|
||||
return success ? temp : defaultValue;
|
||||
}
|
||||
|
||||
private static int tryReadInt(string config, int defaultValue)
|
||||
{
|
||||
int temp = 0;
|
||||
bool success = int.TryParse(config, out temp);
|
||||
return success ? temp : defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
[DataObject]
|
||||
public class RedisMember : IHasId<Guid>
|
||||
{
|
||||
[Key]
|
||||
[Index]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[@Required]
|
||||
[DisplayName("Username")]
|
||||
[Key]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[@Required]
|
||||
[MaxLength(512)]
|
||||
public byte[] PassHash { get; set; }
|
||||
|
||||
[@Required]
|
||||
[MaxLength(24)]
|
||||
public byte[] PassSalt { get; set; }
|
||||
|
||||
[@Required]
|
||||
[DisplayName("Email Address")]
|
||||
[Key]
|
||||
public string EmailAddress { get; set; }
|
||||
|
||||
public bool IsApproved { get; set; }
|
||||
public bool IsLockedOut { get; set; }
|
||||
|
||||
public DateTime CreationDate { get; set; }
|
||||
public DateTime LastActivityDate { get; set; }
|
||||
public DateTime LastLockoutDate { get; set; }
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
|
||||
public DateTime LockoutWindowStart { get; set; }
|
||||
public int LockoutWindowAttempts { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,244 +0,0 @@
|
|||
using NServiceKit.DataAnnotations;
|
||||
using NServiceKit.DesignPatterns.Model;
|
||||
using NServiceKit.Redis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Web.Security;
|
||||
using Required = System.ComponentModel.DataAnnotations.RequiredAttribute;
|
||||
|
||||
namespace BuildFeed.Auth
|
||||
{
|
||||
public class RedisRoleProvider : RoleProvider
|
||||
{
|
||||
public override string ApplicationName
|
||||
{
|
||||
get { return ""; }
|
||||
set { }
|
||||
}
|
||||
|
||||
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
var uClient = rClient.As<RedisMember>();
|
||||
|
||||
List<RedisRole> roles = new List<RedisRole>();
|
||||
roles.AddRange(from r in client.GetAll()
|
||||
where roleNames.Any(n => n == r.RoleName)
|
||||
select r);
|
||||
|
||||
List<RedisMember> users = new List<RedisMember>();
|
||||
users.AddRange(from u in uClient.GetAll()
|
||||
where usernames.Any(n => n == u.UserName)
|
||||
select u);
|
||||
|
||||
for (int i = 0; i < roles.Count; i++)
|
||||
{
|
||||
List<Guid> newUsers = new List<Guid>();
|
||||
|
||||
if(roles[i].Users != null)
|
||||
{
|
||||
var usersToAdd = from u in users
|
||||
where !roles[i].Users.Any(v => v == u.Id)
|
||||
select u.Id;
|
||||
|
||||
newUsers.AddRange(roles[i].Users);
|
||||
|
||||
newUsers.AddRange(usersToAdd);
|
||||
}
|
||||
|
||||
roles[i].Users = newUsers.ToArray();
|
||||
}
|
||||
|
||||
client.StoreAll(roles);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CreateRole(string roleName)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
|
||||
RedisRole rr = new RedisRole()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
RoleName = roleName
|
||||
};
|
||||
|
||||
client.Store(rr);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
|
||||
var role = client.GetAll().SingleOrDefault(r => r.RoleName == roleName);
|
||||
|
||||
if (role.Users.Length > 0 && throwOnPopulatedRole)
|
||||
{
|
||||
throw new Exception("This role still has users");
|
||||
}
|
||||
|
||||
client.DeleteById(role.Id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
var uClient = rClient.As<RedisMember>();
|
||||
|
||||
var userIds = from r in client.GetAll()
|
||||
where r.RoleName == roleName
|
||||
from u in r.Users
|
||||
select u;
|
||||
|
||||
var users = uClient.GetByIds(userIds);
|
||||
|
||||
return (from u in users
|
||||
where u.UserName.ToLower().Contains(usernameToMatch.ToLower())
|
||||
select u.UserName).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] GetAllRoles()
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
|
||||
return (from r in client.GetAll()
|
||||
select r.RoleName).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] GetRolesForUser(string username)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
var uClient = rClient.As<RedisMember>();
|
||||
|
||||
var user = uClient.GetAll().SingleOrDefault(u => u.UserName.ToLower() == username.ToLower());
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
throw new Exception("Username does not exist");
|
||||
}
|
||||
|
||||
return (from r in client.GetAll()
|
||||
where r.Users != null
|
||||
where r.Users.Any(u => u == user.Id)
|
||||
select r.RoleName).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] GetUsersInRole(string roleName)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
var uClient = rClient.As<RedisMember>();
|
||||
|
||||
var userIds = from r in client.GetAll()
|
||||
where r.RoleName == roleName
|
||||
from u in r.Users
|
||||
select u;
|
||||
|
||||
var users = uClient.GetByIds(userIds);
|
||||
|
||||
return (from u in users
|
||||
select u.UserName).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUserInRole(string username, string roleName)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
var uClient = rClient.As<RedisMember>();
|
||||
|
||||
var user = uClient.GetAll().SingleOrDefault(u => u.UserName.ToLower() == username.ToLower());
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
var role = client.GetAll().SingleOrDefault(r => r.RoleName == roleName);
|
||||
|
||||
if(role.Users == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return role.Users.Any(u => u == user.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
var uClient = rClient.As<RedisMember>();
|
||||
|
||||
List<RedisRole> roles = new List<RedisRole>();
|
||||
roles.AddRange(from r in client.GetAll()
|
||||
where roleNames.Any(n => n == r.RoleName)
|
||||
select r);
|
||||
|
||||
List<RedisMember> users = new List<RedisMember>();
|
||||
users.AddRange(from u in uClient.GetAll()
|
||||
where usernames.Any(n => n == u.UserName)
|
||||
select u);
|
||||
|
||||
for (int i = 0; i < roles.Count; i++)
|
||||
{
|
||||
roles[i].Users = (from u in roles[i].Users
|
||||
where !users.Any(v => v.Id == u)
|
||||
select u).ToArray();
|
||||
}
|
||||
|
||||
client.StoreAll(roles);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool RoleExists(string roleName)
|
||||
{
|
||||
using (RedisClient rClient = new RedisClient(DatabaseConfig.Host, DatabaseConfig.Port, db: DatabaseConfig.Database))
|
||||
{
|
||||
var client = rClient.As<RedisRole>();
|
||||
|
||||
return client.GetAll().Any(r => r.RoleName == roleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DataObject]
|
||||
public class RedisRole : IHasId<Guid>
|
||||
{
|
||||
[Key]
|
||||
[Index]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[@Required]
|
||||
[DisplayName("Role name")]
|
||||
[Key]
|
||||
public string RoleName { get; set; }
|
||||
|
||||
public Guid[] Users { get; set; }
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.UI;
|
||||
|
||||
namespace BuildFeed.Controllers
|
||||
{
|
||||
|
@ -12,7 +13,9 @@ public class frontController : Controller
|
|||
private const int _pageSize = 25;
|
||||
|
||||
[Route("")]
|
||||
#if !DEBUG
|
||||
[OutputCache(Duration = 600, VaryByParam = "none")]
|
||||
#endif
|
||||
public ActionResult index()
|
||||
{
|
||||
var buildGroups = from b in Build.Select()
|
||||
|
@ -30,5 +33,19 @@ bg.Key.Revision descending
|
|||
select bg;
|
||||
return View(buildGroups);
|
||||
}
|
||||
|
||||
[Route("group/{major}.{minor}.{number}.{revision}")]
|
||||
public ActionResult viewGroup(byte major, byte minor, ushort number, ushort? revision = null)
|
||||
{
|
||||
var builds = from b in Build.Select()
|
||||
where b.MajorVersion == major
|
||||
where b.MinorVersion == minor
|
||||
where b.Number == number
|
||||
where b.Revision == revision
|
||||
orderby b.BuildTime descending
|
||||
select b;
|
||||
|
||||
return PartialView(builds);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,8 +12,7 @@ namespace BuildFeed.Controllers
|
|||
{
|
||||
public class rssController : Controller
|
||||
{
|
||||
//
|
||||
// GET: /rss/
|
||||
[Route("rss/compiled")]
|
||||
public async Task<ActionResult> index()
|
||||
{
|
||||
var builds = Build.SelectInBuildOrder().Take(20);
|
||||
|
@ -46,6 +45,7 @@ public async Task<ActionResult> index()
|
|||
return new EmptyResult();
|
||||
}
|
||||
|
||||
[Route("rss/added")]
|
||||
public async Task<ActionResult> added()
|
||||
{
|
||||
var builds = Build.Select().OrderByDescending(b => b.Added).Take(20);
|
||||
|
@ -79,6 +79,7 @@ public async Task<ActionResult> added()
|
|||
return new EmptyResult();
|
||||
}
|
||||
|
||||
[Route("rss/leaked")]
|
||||
public async Task<ActionResult> leaked()
|
||||
{
|
||||
var builds = Build.Select().Where(b => b.LeakDate.HasValue).OrderByDescending(b => b.LeakDate.Value).Take(20);
|
||||
|
@ -112,7 +113,7 @@ public async Task<ActionResult> leaked()
|
|||
return new EmptyResult();
|
||||
}
|
||||
|
||||
|
||||
[Route("rss/version")]
|
||||
public async Task<ActionResult> version()
|
||||
{
|
||||
var builds = Build.SelectInVersionOrder()
|
||||
|
@ -147,7 +148,7 @@ public async Task<ActionResult> version()
|
|||
return new EmptyResult();
|
||||
}
|
||||
|
||||
|
||||
[Route("rss/flight/{id}")]
|
||||
public async Task<ActionResult> flight(LevelOfFlight id)
|
||||
{
|
||||
var builds = Build.SelectInBuildOrder()
|
||||
|
|
|
@ -17,18 +17,14 @@ namespace BuildFeed.Controllers
|
|||
{
|
||||
public class supportController : Controller
|
||||
{
|
||||
// GET: support
|
||||
public ActionResult index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("login")]
|
||||
public ActionResult login()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("login")]
|
||||
public ActionResult login(LoginUser ru)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
|
@ -56,12 +52,14 @@ public ActionResult login(LoginUser ru)
|
|||
}
|
||||
|
||||
[Authorize]
|
||||
[Route("password")]
|
||||
public ActionResult password()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("password")]
|
||||
public ActionResult password(ChangePassword cp)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
|
@ -79,18 +77,21 @@ public ActionResult password(ChangePassword cp)
|
|||
return View(cp);
|
||||
}
|
||||
|
||||
[Route("logout")]
|
||||
public ActionResult logout()
|
||||
{
|
||||
FormsAuthentication.SignOut();
|
||||
return Redirect("/");
|
||||
}
|
||||
|
||||
[Route("register")]
|
||||
public ActionResult register()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("register")]
|
||||
public ActionResult register(RegistrationUser ru)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
|
@ -120,6 +121,7 @@ public ActionResult register(RegistrationUser ru)
|
|||
return View(ru);
|
||||
}
|
||||
|
||||
[Route("register")]
|
||||
public ActionResult thanks_register()
|
||||
{
|
||||
return View();
|
||||
|
@ -162,13 +164,16 @@ public async Task<ActionResult> question(QuestionForm qf)
|
|||
}
|
||||
}
|
||||
|
||||
[Route("rss")]
|
||||
public ActionResult rss()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("support/sitemap")]
|
||||
[Route("sitemap")]
|
||||
#if !DEBUG
|
||||
[OutputCache(Duration = 3600, VaryByParam = "none")]
|
||||
#endif
|
||||
public ActionResult sitemap()
|
||||
{
|
||||
IEnumerable<Build> builds = Build.SelectInVersionOrder();
|
||||
|
@ -267,8 +272,10 @@ orderby bv.Key
|
|||
return View(model);
|
||||
}
|
||||
|
||||
[Route("support/xmlsitemap")]
|
||||
[Route("xml-sitemap")]
|
||||
#if !DEBUG
|
||||
[OutputCache(Duration = 3600, VaryByParam = "none")]
|
||||
#endif
|
||||
public ActionResult xmlsitemap()
|
||||
{
|
||||
XNamespace xn = XNamespace.Get("http://www.sitemaps.org/schemas/sitemap/0.9");
|
||||
|
@ -303,8 +310,10 @@ public ActionResult xmlsitemap()
|
|||
return new EmptyResult();
|
||||
}
|
||||
|
||||
[Route("support/stats")]
|
||||
[Route("statistics")]
|
||||
#if !DEBUG
|
||||
[OutputCache(Duration = 3600, VaryByParam = "none")]
|
||||
#endif
|
||||
public ActionResult stats()
|
||||
{
|
||||
var builds = Build.Select();
|
||||
|
|
|
@ -66,26 +66,6 @@ public class Build : IHasId<long>
|
|||
[DisplayFormat(ConvertEmptyStringToNull = true, ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
|
||||
public DateTime? LeakDate { get; set; }
|
||||
|
||||
[RegularExpression("http://betawiki\\.net/.+")]
|
||||
[DisplayName("BetaWiki (Client)")]
|
||||
public Uri BetaWikiUri { get; set; }
|
||||
|
||||
[RegularExpression("http://betawiki\\.net/.+")]
|
||||
[DisplayName("BetaWiki (Server)")]
|
||||
public Uri BetaWikiServerUri { get; set; }
|
||||
|
||||
[RegularExpression("http://www\\.betaarchive\\.com/wiki/.+")]
|
||||
[DisplayName("BetaArchive Wiki")]
|
||||
public Uri BetaArchiveUri { get; set; }
|
||||
|
||||
[RegularExpression("http://longhorn\\.ms/.+")]
|
||||
[DisplayName("Longhorn.ms")]
|
||||
public Uri LonghornMsUri { get; set; }
|
||||
|
||||
[RegularExpression("https://winworldpc\\.com/.+")]
|
||||
[DisplayName("WinWorldPC Library")]
|
||||
public Uri WinWorldPCUri { get; set; }
|
||||
|
||||
[DisplayName("Flight Level")]
|
||||
[EnumDataType(typeof(LevelOfFlight))]
|
||||
public LevelOfFlight FlightLevel { get; set; }
|
||||
|
|
1
Scripts/index-page.ts
Normal file
1
Scripts/index-page.ts
Normal file
|
@ -0,0 +1 @@
|
|||
|
3148
Scripts/typings/jquery/jquery.d.ts
vendored
Normal file
3148
Scripts/typings/jquery/jquery.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -7,13 +7,13 @@
|
|||
@foreach (var group in Model)
|
||||
{
|
||||
<div class="col-sm-2">
|
||||
<h3>@group.Key.ToString()</h3>
|
||||
<h3 class="build-group-title"><a href="#"><i class="fa fa-plus-square"></i></a> @group.Key.ToString()</h3>
|
||||
<p>
|
||||
@if(group.Any(k => k.BuildTime.HasValue))
|
||||
{
|
||||
<span><i class="fa fa-calendar fa-fw"></i> @group.Max(k => k.BuildTime).Value.ToString("dd MMMM yyyy")</span><br />
|
||||
}
|
||||
<i class="fa fa-server fa-fw"></i> @group.Count().ToString() variants
|
||||
<i class="fa fa-server fa-fw"></i> @group.Count().ToString() builds
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
|
11
Views/front/viewGroup.cshtml
Normal file
11
Views/front/viewGroup.cshtml
Normal file
|
@ -0,0 +1,11 @@
|
|||
@model IEnumerable<BuildFeed.Models.Build>
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<ul>
|
||||
@foreach (var build in Model)
|
||||
{
|
||||
<li>@build.FullBuildString</li>
|
||||
}
|
||||
</ul>
|
|
@ -48,9 +48,9 @@
|
|||
<div class="container">
|
||||
@Html.ActionLink("BuildFeed", "index", new { controller = "front", area = "" }, new { @class = "navbar-brand" })
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="https://twitter.com/buildfeed" title="Twitter" target="_blank"><i class="fa fa-twitter"></i> Twitter</a></li>
|
||||
<li><a href="@Url.Action("stats", new { controller = "support", area = "" }) " title="Statistics"><i class="fa fa-line-chart"></i> Statistics</a></li>
|
||||
<li><a href="@Url.Action("rss", new { controller = "support", area = "" })" title="RSS Feeds"><i class="fa fa-rss"></i> RSS Feeds</a></li>
|
||||
<li><a href="https://twitter.com/buildfeed" title="Twitter" target="_blank"><i class="fa fa-twitter"></i> Twitter</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
96
Web.config
96
Web.config
|
@ -1,42 +1,42 @@
|
|||
<?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
|
||||
-->
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="webpages:Version" value="3.0.0.0"/>
|
||||
<add key="webpages:Enabled" value="false"/>
|
||||
<add key="PreserveLoginUrl" value="true"/>
|
||||
<add key="ClientValidationEnabled" value="true"/>
|
||||
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
|
||||
<add key="data:ServerHost" value="localhost"/>
|
||||
<add key="data:ServerPort" value="6379"/>
|
||||
<add key="data:ServerDB" value="1"/>
|
||||
<add key="form:QuestionFromEmail" value="smtp@betawiki.net"/>
|
||||
<add key="form:QuestionToEmail" value="thomas@buildfeed.net"/>
|
||||
<add key="RouteDebugger:Enabled" value="false"/>
|
||||
<add key="webpages:Version" value="3.0.0.0" />
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
<add key="PreserveLoginUrl" value="true" />
|
||||
<add key="ClientValidationEnabled" value="true" />
|
||||
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
|
||||
<add key="data:ServerHost" value="localhost" />
|
||||
<add key="data:ServerPort" value="6379" />
|
||||
<add key="data:ServerDB" value="1" />
|
||||
<add key="form:QuestionFromEmail" value="smtp@betawiki.net" />
|
||||
<add key="form:QuestionToEmail" value="thomas@buildfeed.net" />
|
||||
<add key="RouteDebugger:Enabled" value="false" />
|
||||
</appSettings>
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.5"/>
|
||||
<httpRuntime targetFramework="4.5"/>
|
||||
<globalization culture="en-gb" uiCulture="en-gb"/>
|
||||
<trace enabled="false" requestLimit="40" pageOutput="true"/>
|
||||
<sessionState cookieless="UseCookies"/>
|
||||
<anonymousIdentification cookieless="UseCookies" enabled="false"/>
|
||||
<compilation debug="true" targetFramework="4.5" />
|
||||
<httpRuntime targetFramework="4.5" />
|
||||
<globalization culture="en-gb" uiCulture="en-gb" />
|
||||
<trace enabled="false" requestLimit="40" pageOutput="true" />
|
||||
<sessionState cookieless="UseCookies" />
|
||||
<anonymousIdentification cookieless="UseCookies" enabled="false" />
|
||||
<authentication mode="Forms">
|
||||
<forms loginUrl="/support/login/" cookieless="UseCookies" name="BuildFeedAuth"/>
|
||||
<forms loginUrl="/login/" cookieless="UseCookies" name="BuildFeedAuth" />
|
||||
</authentication>
|
||||
<membership defaultProvider="BuildFeedMemberProvider">
|
||||
<providers>
|
||||
<clear/>
|
||||
<add name="BuildFeedMemberProvider" type="BuildFeed.Auth.RedisMembershipProvider"/>
|
||||
<clear />
|
||||
<add name="BuildFeedMemberProvider" type="RedisAuth.RedisMembershipProvider,RedisAuth" />
|
||||
</providers>
|
||||
</membership>
|
||||
<roleManager defaultProvider="BuildFeedRoleProvider" enabled="true">
|
||||
<providers>
|
||||
<clear/>
|
||||
<add name="BuildFeedRoleProvider" type="BuildFeed.Auth.RedisRoleProvider"/>
|
||||
<clear />
|
||||
<add name="BuildFeedRoleProvider" type="RedisAuth.RedisRoleProvider,RedisAuth" />
|
||||
</providers>
|
||||
</roleManager>
|
||||
<httpModules>
|
||||
|
@ -45,57 +45,57 @@
|
|||
<system.webServer>
|
||||
<modules>
|
||||
</modules>
|
||||
<urlCompression doDynamicCompression="true"/>
|
||||
<validation validateIntegratedModeConfiguration="false"/>
|
||||
<urlCompression doDynamicCompression="true" />
|
||||
<validation validateIntegratedModeConfiguration="false" />
|
||||
<handlers>
|
||||
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
|
||||
<remove name="OPTIONSVerbHandler"/>
|
||||
<remove name="TRACEVerbHandler"/>
|
||||
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
|
||||
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
|
||||
<remove name="OPTIONSVerbHandler" />
|
||||
<remove name="TRACEVerbHandler" />
|
||||
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
<system.net>
|
||||
<mailSettings>
|
||||
<smtp configSource="smtp.config"/>
|
||||
<smtp configSource="smtp.config" />
|
||||
</mailSettings>
|
||||
</system.net>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.EventSource" publicKeyToken="B03F5F7F11D50A3A" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.1.20.0" newVersion="1.1.20.0"/>
|
||||
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.EventSource" publicKeyToken="B03F5F7F11D50A3A" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.1.20.0" newVersion="1.1.20.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
|
||||
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
|
||||
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930"/>
|
||||
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2"/>
|
||||
<assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.EventSource" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.1.14.0" newVersion="1.1.14.0"/>
|
||||
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.EventSource" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.1.20.0" newVersion="1.1.20.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
|
||||
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
|
|
@ -20,6 +20,19 @@ h1
|
|||
padding-top: 70px;
|
||||
}
|
||||
|
||||
.build-group-title
|
||||
{
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.build-group-title a
|
||||
{
|
||||
font-size: 0.6em;
|
||||
vertical-align: 3px;
|
||||
display: inline-block;
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
|
||||
.build-head
|
||||
{
|
||||
margin-bottom: 0.33em;
|
||||
|
|
|
@ -1,33 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Antlr" version="3.5.0.2" targetFramework="net45" />
|
||||
<package id="Chart.js" version="1.0.1" targetFramework="net45" />
|
||||
<package id="jQuery" version="2.1.3" targetFramework="net45" />
|
||||
<package id="jQuery.Validation" version="1.13.1" targetFramework="net45" />
|
||||
<package id="Microsoft.ApplicationInsights" version="0.13.2-build00132" targetFramework="net45" />
|
||||
<package id="Microsoft.ApplicationInsights.PerformanceCollector" version="0.13.2-build00132" targetFramework="net45" />
|
||||
<package id="Microsoft.ApplicationInsights.RuntimeTelemetry" version="0.13.2-build00132" targetFramework="net45" />
|
||||
<package id="Microsoft.ApplicationInsights.Web" version="0.13.2-build00132" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
|
||||
<package id="Microsoft.Diagnostics.Instrumentation.Extensions.Intercept" version="0.13.0-build22724" targetFramework="net45" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.EventSource.Redist" version="1.1.20-beta" targetFramework="net45" />
|
||||
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="NServiceKit.Common" version="1.0.27" targetFramework="net45" />
|
||||
<package id="NServiceKit.Redis" version="1.0.10" targetFramework="net45" />
|
||||
<package id="NServiceKit.Text" version="1.0.10" targetFramework="net45" />
|
||||
<package id="routedebugger" version="2.1.4.0" targetFramework="net45" />
|
||||
<package id="WebGrease" version="1.6.0" targetFramework="net45" />
|
||||
<package id="xwebrss" version="1.2.1.130" targetFramework="net45" />
|
||||
<package id="Antlr" version="3.5.0.2" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Chart.js" version="1.0.1" targetFramework="net45" userInstalled="true" />
|
||||
<package id="jQuery" version="2.1.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="jquery.TypeScript.DefinitelyTyped" version="2.2.2" targetFramework="net45" userInstalled="true" />
|
||||
<package id="jQuery.Validation" version="1.13.1" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights" version="0.13.2-build00132" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.PerformanceCollector" version="0.13.2-build00132" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.RuntimeTelemetry" version="0.13.2-build00132" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.ApplicationInsights.Web" version="0.13.2-build00132" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.Diagnostics.Instrumentation.Extensions.Intercept" version="0.13.0-build22724" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.EventSource.Redist" version="1.1.20-beta" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" userInstalled="true" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" userInstalled="true" />
|
||||
<package id="NServiceKit.Common" version="1.0.27" targetFramework="net45" userInstalled="true" />
|
||||
<package id="NServiceKit.Redis" version="1.0.10" targetFramework="net45" userInstalled="true" />
|
||||
<package id="NServiceKit.Text" version="1.0.10" targetFramework="net45" userInstalled="true" />
|
||||
<package id="routedebugger" version="2.1.4.0" targetFramework="net45" userInstalled="true" />
|
||||
<package id="WebGrease" version="1.6.0" targetFramework="net45" userInstalled="true" />
|
||||
<package id="xwebrss" version="1.2.1.130" targetFramework="net45" userInstalled="true" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user