Code style updates

This commit is contained in:
Thomas Hounsell 2016-08-19 13:45:52 +01:00
parent 0f614d258b
commit 1088aa7898
31 changed files with 878 additions and 801 deletions

View File

@ -10,9 +10,9 @@ internal static class DatabaseConfig
static DatabaseConfig() static DatabaseConfig()
{ {
Host = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoHost"]) ? Host = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoHost"])
ConfigurationManager.AppSettings["data:MongoHost"] : ? ConfigurationManager.AppSettings["data:MongoHost"]
"localhost"; : "localhost";
int _port; int _port;
bool success = int.TryParse(ConfigurationManager.AppSettings["data:MongoPort"], out _port); bool success = int.TryParse(ConfigurationManager.AppSettings["data:MongoPort"], out _port);
@ -22,9 +22,9 @@ static DatabaseConfig()
} }
Port = _port; Port = _port;
Database = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoDB"]) ? Database = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoDB"])
ConfigurationManager.AppSettings["data:MongoDB"] : ? ConfigurationManager.AppSettings["data:MongoDB"]
"MongoAuth"; : "MongoAuth";
} }
} }
} }

View File

@ -1,7 +1,4 @@
using MongoDB.Bson; using System;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
@ -9,12 +6,15 @@
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Security; using System.Web.Security;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
namespace MongoAuth namespace MongoAuth
{ {
public class MongoMembershipProvider : MembershipProvider public class MongoMembershipProvider : MembershipProvider
{ {
private const string _memberCollectionName = "members"; private const string MEMBER_COLLECTION_NAME = "members";
private bool _enablePasswordReset = true; private bool _enablePasswordReset = true;
private int _maxInvalidPasswordAttempts = 5; private int _maxInvalidPasswordAttempts = 5;
@ -57,18 +57,18 @@ public override void Initialize(string name, NameValueCollection config)
base.Initialize(name, config); base.Initialize(name, config);
_enablePasswordReset = tryReadBool(config["enablePasswordReset"], _enablePasswordReset); _enablePasswordReset = TryReadBool(config["enablePasswordReset"], _enablePasswordReset);
_maxInvalidPasswordAttempts = tryReadInt(config["maxInvalidPasswordAttempts"], _maxInvalidPasswordAttempts); _maxInvalidPasswordAttempts = TryReadInt(config["maxInvalidPasswordAttempts"], _maxInvalidPasswordAttempts);
_minRequiredNonAlphanumericCharacters = tryReadInt(config["minRequiredNonAlphanumericCharacters"], _minRequiredNonAlphanumericCharacters); _minRequiredNonAlphanumericCharacters = TryReadInt(config["minRequiredNonAlphanumericCharacters"], _minRequiredNonAlphanumericCharacters);
_minRequriedPasswordLength = tryReadInt(config["minRequriedPasswordLength"], _minRequriedPasswordLength); _minRequriedPasswordLength = TryReadInt(config["minRequriedPasswordLength"], _minRequriedPasswordLength);
_passwordAttemptWindow = tryReadInt(config["passwordAttemptWindow"], _passwordAttemptWindow); _passwordAttemptWindow = TryReadInt(config["passwordAttemptWindow"], _passwordAttemptWindow);
_requiresUniqueEmail = tryReadBool(config["requiresUniqueEmail"], _requiresUniqueEmail); _requiresUniqueEmail = TryReadBool(config["requiresUniqueEmail"], _requiresUniqueEmail);
_dbClient = new MongoClient(new MongoClientSettings() _dbClient = new MongoClient(new MongoClientSettings
{ {
Server = new MongoServerAddress(DatabaseConfig.Host, DatabaseConfig.Port) Server = new MongoServerAddress(DatabaseConfig.Host, DatabaseConfig.Port)
}); });
_memberCollection = _dbClient.GetDatabase(DatabaseConfig.Database).GetCollection<MongoMember>(_memberCollectionName); _memberCollection = _dbClient.GetDatabase(DatabaseConfig.Database).GetCollection<MongoMember>(MEMBER_COLLECTION_NAME);
} }
public override bool ChangePassword(string username, string oldPassword, string newPassword) public override bool ChangePassword(string username, string oldPassword, string newPassword)
@ -77,11 +77,9 @@ public override bool ChangePassword(string username, string oldPassword, string
if (isAuthenticated) if (isAuthenticated)
{ {
var task = _memberCollection Task<MongoMember> task = _memberCollection.Find(m => m.UserName.ToLower() == username.ToLower()).SingleOrDefaultAsync();
.Find(m => m.UserName.ToLower() == username.ToLower())
.SingleOrDefaultAsync();
task.Wait(); task.Wait();
var mm = task.Result; MongoMember mm = task.Result;
if (mm == null) if (mm == null)
{ {
@ -89,13 +87,12 @@ public override bool ChangePassword(string username, string oldPassword, string
} }
byte[] salt = new byte[24]; byte[] salt = new byte[24];
byte[] hash = calculateHash(newPassword, ref salt); byte[] hash = CalculateHash(newPassword, ref salt);
mm.PassSalt = salt; mm.PassSalt = salt;
mm.PassHash = hash; mm.PassHash = hash;
var replaceTask = _memberCollection Task<ReplaceOneResult> replaceTask = _memberCollection.ReplaceOneAsync(m => m.Id == mm.Id, mm);
.ReplaceOneAsync(m => m.Id == mm.Id, mm);
replaceTask.Wait(); replaceTask.Wait();
return replaceTask.IsCompleted; return replaceTask.IsCompleted;
@ -104,10 +101,7 @@ public override bool ChangePassword(string username, string oldPassword, string
return false; return false;
} }
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{ {
@ -119,12 +113,8 @@ public override MembershipUser CreateUser(string username, string password, stri
MembershipUser mu = null; MembershipUser mu = null;
var dupeUsers = _memberCollection Task<long> dupeUsers = _memberCollection.Find(m => m.UserName.ToLower() == username.ToLower()).CountAsync();
.Find(m => m.UserName.ToLower() == username.ToLower()) Task<long> dupeEmails = _memberCollection.Find(m => m.EmailAddress.ToLower() == email.ToLower()).CountAsync();
.CountAsync();
var dupeEmails = _memberCollection
.Find(m => m.EmailAddress.ToLower() == email.ToLower())
.CountAsync();
dupeUsers.Wait(); dupeUsers.Wait();
dupeEmails.Wait(); dupeEmails.Wait();
@ -139,34 +129,30 @@ public override MembershipUser CreateUser(string username, string password, stri
else else
{ {
byte[] salt = new byte[24]; byte[] salt = new byte[24];
byte[] hash = calculateHash(password, ref salt); byte[] hash = CalculateHash(password, ref salt);
MongoMember mm = new MongoMember() MongoMember mm = new MongoMember
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
UserName = username, UserName = username,
PassHash = hash, PassHash = hash,
PassSalt = salt, PassSalt = salt,
EmailAddress = email, EmailAddress = email,
IsApproved = false, IsApproved = false,
IsLockedOut = false, IsLockedOut = false,
CreationDate = DateTime.Now, CreationDate = DateTime.Now,
LastLoginDate = DateTime.MinValue, LastLoginDate = DateTime.MinValue,
LastActivityDate = DateTime.MinValue, LastActivityDate = DateTime.MinValue,
LastLockoutDate = DateTime.MinValue LastLockoutDate = DateTime.MinValue
}; };
var insertTask = _memberCollection Task insertTask = _memberCollection.InsertOneAsync(mm);
.InsertOneAsync(mm);
insertTask.Wait(); insertTask.Wait();
if (insertTask.Status == TaskStatus.RanToCompletion) if (insertTask.Status == TaskStatus.RanToCompletion)
{ {
status = MembershipCreateStatus.Success; status = MembershipCreateStatus.Success;
mu = new MembershipUser(this.Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate); mu = new MembershipUser(Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate);
} }
else else
{ {
@ -179,110 +165,85 @@ public override MembershipUser CreateUser(string username, string password, stri
public override bool DeleteUser(string username, bool deleteAllRelatedData) public override bool DeleteUser(string username, bool deleteAllRelatedData)
{ {
var task = _memberCollection Task<DeleteResult> task = _memberCollection.DeleteOneAsync(m => m.UserName.ToLower() == username.ToLower());
.DeleteOneAsync(m => m.UserName.ToLower() == username.ToLower());
task.Wait(); task.Wait();
return task.Result.IsAcknowledged && task.Result.DeletedCount == 1; return task.Result.IsAcknowledged && task.Result.DeletedCount == 1;
} }
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{ {
MembershipUserCollection muc = new MembershipUserCollection(); MembershipUserCollection muc = new MembershipUserCollection();
var users = _memberCollection IFindFluent<MongoMember, MongoMember> users = _memberCollection.Find(new BsonDocument());
.Find(new BsonDocument());
var totalRecordsTask = users Task<long> totalRecordsTask = users.CountAsync();
.CountAsync();
totalRecordsTask.Wait(); totalRecordsTask.Wait();
totalRecords = Convert.ToInt32(totalRecordsTask.Result); totalRecords = Convert.ToInt32(totalRecordsTask.Result);
users = users users = users.Skip(pageIndex * pageSize).Limit(pageSize);
.Skip(pageIndex * pageSize) Task<List<MongoMember>> pageItemsTask = users.ToListAsync();
.Limit(pageSize);
var pageItemsTask = users.ToListAsync();
pageItemsTask.Wait(); pageItemsTask.Wait();
foreach (var mm in pageItemsTask.Result) foreach (MongoMember mm in pageItemsTask.Result)
{ {
muc.Add(new MembershipUser(this.Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate)); muc.Add(new MembershipUser(Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate));
} }
return muc; return muc;
} }
public override int GetNumberOfUsersOnline() public override int GetNumberOfUsersOnline() { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public override string GetPassword(string username, string answer) public override string GetPassword(string username, string answer) { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(string username, bool userIsOnline) public override MembershipUser GetUser(string username, bool userIsOnline)
{ {
var task = _memberCollection Task<MongoMember> task = _memberCollection.Find(f => f.UserName.ToLower() == username.ToLower()).FirstOrDefaultAsync();
.Find(f => f.UserName.ToLower() == username.ToLower())
.FirstOrDefaultAsync();
task.Wait(); task.Wait();
var mm = task.Result; MongoMember mm = task.Result;
return mm == null ? null : new MembershipUser(this.Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate); return mm == null
? null
: new MembershipUser(Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate);
} }
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{ {
var task = _memberCollection Task<MongoMember> task = _memberCollection.Find(f => f.Id == (Guid)providerUserKey).FirstOrDefaultAsync();
.Find(f => f.Id == (Guid)providerUserKey)
.FirstOrDefaultAsync();
task.Wait(); task.Wait();
var mm = task.Result; MongoMember mm = task.Result;
return mm == null ? null : new MembershipUser(this.Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate); return mm == null
? null
: new MembershipUser(Name, mm.UserName, mm.Id, mm.EmailAddress, "", "", mm.IsApproved, mm.IsLockedOut, mm.CreationDate, mm.LastLoginDate, mm.LastActivityDate, DateTime.MinValue, mm.LastLockoutDate);
} }
public override string GetUserNameByEmail(string email) public override string GetUserNameByEmail(string email)
{ {
var task = _memberCollection Task<MongoMember> task = _memberCollection.Find(f => f.EmailAddress.ToLower() == email.ToLower()).FirstOrDefaultAsync();
.Find(f => f.EmailAddress.ToLower() == email.ToLower())
.FirstOrDefaultAsync();
task.Wait(); task.Wait();
return task.Result.UserName; return task.Result.UserName;
} }
public override string ResetPassword(string username, string answer) public override string ResetPassword(string username, string answer) { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public void ChangeApproval(Guid Id, bool newStatus) public void ChangeApproval(Guid id, bool newStatus)
{ {
var task = _memberCollection Task<UpdateResult> task = _memberCollection.UpdateOneAsync(Builders<MongoMember>.Filter.Eq(u => u.Id, id), Builders<MongoMember>.Update.Set(u => u.IsApproved, newStatus));
.UpdateOneAsync(
Builders<MongoMember>.Filter.Eq(u => u.Id, Id),
Builders<MongoMember>.Update.Set(u => u.IsApproved, newStatus));
task.Wait(); task.Wait();
} }
public void ChangeLockStatus(Guid Id, bool newStatus) public void ChangeLockStatus(Guid id, bool newStatus)
{ {
var updateDefinition = new List<UpdateDefinition<MongoMember>>(); List<UpdateDefinition<MongoMember>> updateDefinition = new List<UpdateDefinition<MongoMember>>();
updateDefinition.Add(Builders<MongoMember>.Update.Set(u => u.IsLockedOut, newStatus)); updateDefinition.Add(Builders<MongoMember>.Update.Set(u => u.IsLockedOut, newStatus));
if (newStatus) if (newStatus)
@ -295,50 +256,40 @@ public void ChangeLockStatus(Guid Id, bool newStatus)
updateDefinition.Add(Builders<MongoMember>.Update.Set(u => u.LastLockoutDate, DateTime.MinValue)); updateDefinition.Add(Builders<MongoMember>.Update.Set(u => u.LastLockoutDate, DateTime.MinValue));
} }
var task = _memberCollection Task<UpdateResult> task = _memberCollection.UpdateOneAsync(Builders<MongoMember>.Filter.Eq(u => u.Id, id), Builders<MongoMember>.Update.Combine(updateDefinition));
.UpdateOneAsync(
Builders<MongoMember>.Filter.Eq(u => u.Id, Id),
Builders<MongoMember>.Update.Combine(updateDefinition));
task.Wait(); task.Wait();
} }
public override bool UnlockUser(string userName) public override bool UnlockUser(string userName)
{ {
var task = _memberCollection Task<UpdateResult> task = _memberCollection.UpdateOneAsync(Builders<MongoMember>.Filter.Eq(m => m.UserName.ToLower(), userName.ToLower()), Builders<MongoMember>.Update.Set(m => m.IsLockedOut, false));
.UpdateOneAsync(
Builders<MongoMember>.Filter.Eq(m => m.UserName.ToLower(), userName.ToLower()),
Builders<MongoMember>.Update.Set(m => m.IsLockedOut, false));
task.Wait(); task.Wait();
return task.Result.IsAcknowledged && task.Result.ModifiedCount == 1; return task.Result.IsAcknowledged && task.Result.ModifiedCount == 1;
} }
public override void UpdateUser(MembershipUser user) public override void UpdateUser(MembershipUser user) { throw new NotImplementedException(); }
{
throw new NotImplementedException();
}
public override bool ValidateUser(string username, string password) public override bool ValidateUser(string username, string password)
{ {
var task = _memberCollection Task<MongoMember> task = _memberCollection.Find(f => f.UserName.ToLower() == username.ToLower()).FirstOrDefaultAsync();
.Find(f => f.UserName.ToLower() == username.ToLower())
.FirstOrDefaultAsync();
task.Wait(); task.Wait();
var mm = task.Result; MongoMember mm = task.Result;
if (mm == null || !(mm.IsApproved && !mm.IsLockedOut)) if (mm == null
|| !(mm.IsApproved && !mm.IsLockedOut))
{ {
return false; return false;
} }
byte[] salt = mm.PassSalt; byte[] salt = mm.PassSalt;
byte[] hash = calculateHash(password, ref salt); byte[] hash = CalculateHash(password, ref salt);
bool isFail = false; bool isFail = false;
for (int i = 0; i > hash.Length; i++) for (int i = 0; i > hash.Length; i++)
{ {
isFail |= (hash[i] != mm.PassHash[i]); isFail |= hash[i] != mm.PassHash[i];
} }
@ -375,16 +326,13 @@ public override bool ValidateUser(string username, string password)
mm.LockoutWindowAttempts = 0; mm.LockoutWindowAttempts = 0;
} }
var updTask = _memberCollection Task<ReplaceOneResult> updTask = _memberCollection.ReplaceOneAsync(Builders<MongoMember>.Filter.Eq(u => u.Id, mm.Id), mm);
.ReplaceOneAsync(
Builders<MongoMember>.Filter.Eq(u => u.Id, mm.Id),
mm);
updTask.Wait(); updTask.Wait();
return !isFail; return !isFail;
} }
private static byte[] calculateHash(string password, ref byte[] salt) private static byte[] CalculateHash(string password, ref byte[] salt)
{ {
if (!salt.Any(v => v != 0)) if (!salt.Any(v => v != 0))
{ {
@ -405,18 +353,22 @@ private static byte[] calculateHash(string password, ref byte[] salt)
return hash; return hash;
} }
private static bool tryReadBool(string config, bool defaultValue) private static bool TryReadBool(string config, bool defaultValue)
{ {
bool temp = false; bool temp;
bool success = bool.TryParse(config, out temp); bool success = bool.TryParse(config, out temp);
return success ? temp : defaultValue; return success
? temp
: defaultValue;
} }
private static int tryReadInt(string config, int defaultValue) private static int TryReadInt(string config, int defaultValue)
{ {
int temp = 0; int temp;
bool success = int.TryParse(config, out temp); bool success = int.TryParse(config, out temp);
return success ? temp : defaultValue; return success
? temp
: defaultValue;
} }
} }
@ -441,5 +393,4 @@ public class MongoMember
public DateTime LockoutWindowStart { get; set; } public DateTime LockoutWindowStart { get; set; }
public int LockoutWindowAttempts { get; set; } public int LockoutWindowAttempts { get; set; }
} }
}
}

View File

@ -1,254 +1,217 @@
using MongoDB.Bson; using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration.Provider;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Security;
using MongoAuth.Properties;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver; using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Security;
using System.Collections.Specialized;
using System.Configuration.Provider;
namespace MongoAuth namespace MongoAuth
{ {
public class MongoRoleProvider : RoleProvider public class MongoRoleProvider : RoleProvider
{ {
private const string _roleCollectionName = "roles"; private const string MEMBER_COLLECTION_NAME = "members";
private const string _memberCollectionName = "members"; private const string ROLE_COLLECTION_NAME = "roles";
private MongoClient _dbClient; private MongoClient _dbClient;
private IMongoCollection<MongoRole> _roleCollection; private IMongoCollection<MongoRole> _roleCollection;
private IMongoCollection<MongoMember> _memberCollection; private IMongoCollection<MongoMember> _memberCollection;
public override string ApplicationName public override string ApplicationName
{ {
get { return ""; } get { return ""; }
set { } set { }
} }
public override void Initialize(string name, NameValueCollection config) public override void Initialize(string name, NameValueCollection config)
{ {
base.Initialize(name, config); base.Initialize(name, config);
_dbClient = new MongoClient(new MongoClientSettings() _dbClient = new MongoClient(new MongoClientSettings
{
Server = new MongoServerAddress(DatabaseConfig.Host, DatabaseConfig.Port)
});
_roleCollection = _dbClient.GetDatabase(DatabaseConfig.Database).GetCollection<MongoRole>(ROLE_COLLECTION_NAME);
_memberCollection = _dbClient.GetDatabase(DatabaseConfig.Database).GetCollection<MongoMember>(MEMBER_COLLECTION_NAME);
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
Task<List<MongoRole>> roleTask = _roleCollection.Find(r => roleNames.Contains(r.RoleName)).ToListAsync();
roleTask.Wait();
List<MongoRole> roles = roleTask.Result;
Task<List<MongoMember>> userTask = _memberCollection.Find(u => usernames.Contains(u.UserName)).ToListAsync();
userTask.Wait();
List<MongoMember> users = userTask.Result;
for (int i = 0; i < roles.Count; i++)
{
List<Guid> newUsers = new List<Guid>();
if (roles[i].Users != null)
{ {
Server = new MongoServerAddress(DatabaseConfig.Host, DatabaseConfig.Port) newUsers.AddRange(roles[i].Users);
});
_roleCollection = _dbClient.GetDatabase(DatabaseConfig.Database).GetCollection<MongoRole>(_roleCollectionName);
_memberCollection = _dbClient.GetDatabase(DatabaseConfig.Database).GetCollection<MongoMember>(_memberCollectionName);
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
var roleTask = _roleCollection
.Find(r => roleNames.Contains(r.RoleName))
.ToListAsync();
roleTask.Wait();
List<MongoRole> roles = roleTask.Result;
var userTask = _memberCollection
.Find(u => usernames.Contains(u.UserName))
.ToListAsync();
userTask.Wait();
List<MongoMember> users = userTask.Result;
for (int i = 0; i < roles.Count; i++)
{
List<Guid> newUsers = new List<Guid>();
if (roles[i].Users != null)
{
newUsers.AddRange(roles[i].Users);
}
var usersToAdd = from u in users
where !newUsers.Any(v => v == u.Id)
select u.Id;
newUsers.AddRange(usersToAdd);
roles[i].Users = newUsers.ToArray();
var update = _roleCollection
.ReplaceOneAsync(Builders<MongoRole>.Filter.Eq(r => r.Id, roles[i].Id), roles[i]);
update.Wait();
}
}
public override void CreateRole(string roleName)
{
MongoRole r = new MongoRole()
{
Id = Guid.NewGuid(),
RoleName = roleName
};
var task = _roleCollection
.InsertOneAsync(r);
task.Wait();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
var role = _roleCollection
.Find(r => r.RoleName == roleName)
.SingleOrDefaultAsync();
role.Wait();
if (role.Result != null && role.Result.Users.Length > 0 && throwOnPopulatedRole)
{
throw new ProviderException(Properties.Resources.RoleNotEmpty);
} }
var task = _roleCollection IEnumerable<Guid> usersToAdd = from u in users
.DeleteOneAsync(r => r.RoleName == roleName); where newUsers.All(v => v != u.Id)
task.Wait(); select u.Id;
return true; newUsers.AddRange(usersToAdd);
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch) roles[i].Users = newUsers.ToArray();
{
var role = _roleCollection
.Find(r => r.RoleName == roleName)
.SingleOrDefaultAsync();
role.Wait();
if (role == null) Task<ReplaceOneResult> update = _roleCollection.ReplaceOneAsync(Builders<MongoRole>.Filter.Eq(r => r.Id, roles[i].Id), roles[i]);
{ update.Wait();
return Array.Empty<string>(); }
} }
var users = _memberCollection public override void CreateRole(string roleName)
.Find(u => role.Result.Users.Contains(u.Id) && u.UserName.ToLower().Contains(usernameToMatch.ToLower())) {
.ToListAsync(); MongoRole r = new MongoRole
users.Wait(); {
Id = Guid.NewGuid(),
RoleName = roleName
};
return users.Result Task task = _roleCollection.InsertOneAsync(r);
.Select(r => r.UserName) task.Wait();
.ToArray(); }
}
public override string[] GetAllRoles() public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{ {
var roles = _roleCollection Task<MongoRole> role = _roleCollection.Find(r => r.RoleName == roleName).SingleOrDefaultAsync();
.Find(new BsonDocument()) role.Wait();
.ToListAsync();
roles.Wait();
return roles.Result if (role.Result != null
.Select(r => r.RoleName) && role.Result.Users.Length > 0
.ToArray(); && throwOnPopulatedRole)
} {
throw new ProviderException(Resources.RoleNotEmpty);
}
public override string[] GetRolesForUser(string username) Task<DeleteResult> task = _roleCollection.DeleteOneAsync(r => r.RoleName == roleName);
{ task.Wait();
var user = _memberCollection
.Find(u => u.UserName.ToLower() == username.ToLower())
.SingleOrDefaultAsync();
user.Wait();
if (user == null) return true;
{ }
return Array.Empty<string>();
}
var role = _roleCollection public override string[] FindUsersInRole(string roleName, string usernameToMatch)
.Find(r => r.Users != null && r.Users.Contains(user.Result.Id)) {
.ToListAsync(); Task<MongoRole> role = _roleCollection.Find(r => r.RoleName == roleName).SingleOrDefaultAsync();
role.Wait(); role.Wait();
return role.Result if (role.Result == null)
.Select(r => r.RoleName) {
.ToArray(); return Array.Empty<string>();
} }
public override string[] GetUsersInRole(string roleName) Task<List<MongoMember>> users = _memberCollection.Find(u => role.Result.Users.Contains(u.Id) && u.UserName.ToLower().Contains(usernameToMatch.ToLower())).ToListAsync();
{ users.Wait();
var role = _roleCollection
.Find(r => r.RoleName == roleName)
.SingleOrDefaultAsync();
role.Wait();
if (role == null) return users.Result.Select(r => r.UserName).ToArray();
{ }
return Array.Empty<string>();
}
var users = _memberCollection public override string[] GetAllRoles()
.Find(u => role.Result.Users.Contains(u.Id)) {
.ToListAsync(); Task<List<MongoRole>> roles = _roleCollection.Find(new BsonDocument()).ToListAsync();
users.Wait(); roles.Wait();
return users.Result return roles.Result.Select(r => r.RoleName).ToArray();
.Select(u => u.UserName) }
.ToArray();
}
public override bool IsUserInRole(string username, string roleName) public override string[] GetRolesForUser(string username)
{ {
var user = _memberCollection Task<MongoMember> user = _memberCollection.Find(u => u.UserName.ToLower() == username.ToLower()).SingleOrDefaultAsync();
.Find(u => u.UserName.ToLower() == username.ToLower()) user.Wait();
.SingleOrDefaultAsync();
var role = _roleCollection
.Find(r => r.RoleName == roleName)
.SingleOrDefaultAsync();
user.Wait();
role.Wait();
if (user.Result == null || role.Result == null || role.Result.Users == null) if (user.Result == null)
{ {
return false; return Array.Empty<string>();
} }
return role.Result.Users.Contains(user.Result.Id); Task<List<MongoRole>> role = _roleCollection.Find(r => r.Users != null && r.Users.Contains(user.Result.Id)).ToListAsync();
} role.Wait();
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) return role.Result.Select(r => r.RoleName).ToArray();
{ }
var roleTask = _roleCollection
.Find(r => roleNames.Contains(r.RoleName))
.ToListAsync();
roleTask.Wait();
List<MongoRole> roles = roleTask.Result;
var userTask = _memberCollection public override string[] GetUsersInRole(string roleName)
.Find(u => usernames.Contains(u.UserName)) {
.ToListAsync(); Task<MongoRole> role = _roleCollection.Find(r => r.RoleName == roleName).SingleOrDefaultAsync();
userTask.Wait(); role.Wait();
List<MongoMember> users = userTask.Result;
for (int i = 0; i < roles.Count; i++) if (role.Result == null)
{ {
roles[i].Users = (from u in roles[i].Users return Array.Empty<string>();
where !users.Any(v => v.Id == u) }
select u).ToArray();
var update = _roleCollection Task<List<MongoMember>> users = _memberCollection.Find(u => role.Result.Users.Contains(u.Id)).ToListAsync();
.ReplaceOneAsync(Builders<MongoRole>.Filter.Eq(r => r.Id, roles[i].Id), roles[i]); users.Wait();
update.Wait();
}
}
public override bool RoleExists(string roleName) return users.Result.Select(u => u.UserName).ToArray();
{ }
var role = _roleCollection
.Find(r => r.RoleName == roleName)
.SingleOrDefaultAsync();
role.Wait();
return role.Result != null; public override bool IsUserInRole(string username, string roleName)
} {
} Task<MongoMember> user = _memberCollection.Find(u => u.UserName.ToLower() == username.ToLower()).SingleOrDefaultAsync();
Task<MongoRole> role = _roleCollection.Find(r => r.RoleName == roleName).SingleOrDefaultAsync();
user.Wait();
role.Wait();
[DataObject] if (user.Result == null
public class MongoRole || role.Result?.Users == null)
{ {
[BsonId] return false;
public Guid Id { get; set; } }
public string RoleName { get; set; } return role.Result.Users.Contains(user.Result.Id);
}
public Guid[] Users { get; set; } public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
} {
Task<List<MongoRole>> roleTask = _roleCollection.Find(r => roleNames.Contains(r.RoleName)).ToListAsync();
roleTask.Wait();
List<MongoRole> roles = roleTask.Result;
Task<List<MongoMember>> userTask = _memberCollection.Find(u => usernames.Contains(u.UserName)).ToListAsync();
userTask.Wait();
List<MongoMember> users = userTask.Result;
foreach (MongoRole t in roles)
{
t.Users = (from u in t.Users
where users.All(v => v.Id != u)
select u).ToArray();
Task<ReplaceOneResult> update = _roleCollection.ReplaceOneAsync(Builders<MongoRole>.Filter.Eq(r => r.Id, t.Id), t);
update.Wait();
}
}
public override bool RoleExists(string roleName)
{
Task<MongoRole> role = _roleCollection.Find(r => r.RoleName == roleName).SingleOrDefaultAsync();
role.Wait();
return role.Result != null;
}
}
[DataObject]
public class MongoRole
{
[BsonId]
public Guid Id { get; set; }
public string RoleName { get; set; }
public Guid[] Users { get; set; }
}
} }

View File

@ -4,9 +4,6 @@ namespace BuildFeed
{ {
public class FilterConfig public class FilterConfig
{ {
public static void RegisterGlobalFilters(GlobalFilterCollection filters) public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); }
{
filters.Add(new HandleErrorAttribute());
}
} }
} }

View File

@ -1,6 +1,5 @@
using BuildFeed.Models; using System.Configuration;
using System.Configuration; using BuildFeed.Models;
using System.Threading.Tasks;
namespace BuildFeed namespace BuildFeed
{ {
@ -12,9 +11,9 @@ internal static class MongoConfig
static MongoConfig() static MongoConfig()
{ {
Host = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoHost"]) ? Host = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoHost"])
ConfigurationManager.AppSettings["data:MongoHost"] : ? ConfigurationManager.AppSettings["data:MongoHost"]
"localhost"; : "localhost";
int _port; int _port;
bool success = int.TryParse(ConfigurationManager.AppSettings["data:MongoPort"], out _port); bool success = int.TryParse(ConfigurationManager.AppSettings["data:MongoPort"], out _port);
@ -24,9 +23,9 @@ static MongoConfig()
} }
Port = _port; Port = _port;
Database = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoDB"]) ? Database = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["data:MongoDB"])
ConfigurationManager.AppSettings["data:MongoDB"] : ? ConfigurationManager.AppSettings["data:MongoDB"]
"MongoAuth"; : "MongoAuth";
} }
public static void SetupIndexes() public static void SetupIndexes()

View File

@ -11,12 +11,14 @@ public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.AppendTrailingSlash = true; routes.AppendTrailingSlash = true;
routes.MapHttpRoute("API", "api/{action}/{id}", new routes.MapHttpRoute("API",
{ "api/{action}/{id}",
controller = "api", new
action = "GetBuilds", {
id = UrlParameter.Optional controller = "api",
}); action = "GetBuilds",
id = UrlParameter.Optional
});
routes.MapMvcAttributeRoutes(); routes.MapMvcAttributeRoutes();
} }
} }

View File

@ -82,11 +82,12 @@ public async Task<ActionResult> create(MetaItemModel meta)
public async Task<ActionResult> edit(MetaType type, string value) public async Task<ActionResult> edit(MetaType type, string value)
{ {
return View("create", await _mModel.SelectById(new MetaItemKey return View("create",
{ await _mModel.SelectById(new MetaItemKey
Type = type, {
Value = value Type = type,
})); Value = value
}));
} }
[HttpPost] [HttpPost]

View File

@ -67,7 +67,8 @@ public ActionResult cleanup()
foreach (MembershipUser user in users) foreach (MembershipUser user in users)
{ {
if (!user.IsApproved && (user.CreationDate.AddDays(30) < DateTime.Now)) if (!user.IsApproved
&& (user.CreationDate.AddDays(30) < DateTime.Now))
{ {
Membership.DeleteUser(user.UserName); Membership.DeleteUser(user.UserName);
} }

View File

@ -1,3 +1,3 @@
@{ @{
Layout = "~/Views/shared/_default.cshtml"; Layout = "~/Views/shared/_default.cshtml";
} }

View File

@ -19,4 +19,4 @@
<li>@Html.ActionLink("Exception test", "exception")</li> <li>@Html.ActionLink("Exception test", "exception")</li>
<li>@Html.ActionLink("Initial setup", "setup")</li> <li>@Html.ActionLink("Initial setup", "setup")</li>
} }
</ul> </ul>

View File

@ -1,9 +1,9 @@
@model BuildFeed.Models.MetaItemModel @model BuildFeed.Models.MetaItemModel
@{ @{
ViewBag.Title = string.Format("Add metadata for {0} | BuildFeed", Model.Id.Value); ViewBag.Title = $"Add metadata for {Model.Id.Value} | BuildFeed";
} }
<h2>@string.Format("Add metadata for {0}", Model.Id.Value)</h2> <h2>@($"Add metadata for {Model.Id.Value}") </h2>
@using (Html.BeginForm()) @using (Html.BeginForm())
@ -15,9 +15,16 @@
<div class="form-horizontal"> <div class="form-horizontal">
<div class="form-group"> <div class="form-group">
@Html.LabelFor(model => model.MetaDescription, htmlAttributes: new { @class = "control-label" }) @Html.LabelFor(model => model.MetaDescription, new
{
@class = "control-label"
})
<div class="wide-group"> <div class="wide-group">
@Html.TextAreaFor(model => model.MetaDescription, new { @class = "form-control", rows = "2" }) @Html.TextAreaFor(model => model.MetaDescription, new
{
@class = "form-control",
rows = "2"
})
<div class="help-block"> <div class="help-block">
<span id="meta-count">0</span> characters <span id="meta-count">0</span> characters
@Html.ValidationMessageFor(model => model.MetaDescription) @Html.ValidationMessageFor(model => model.MetaDescription)
@ -26,9 +33,15 @@
</div> </div>
<div class="form-group"> <div class="form-group">
@Html.LabelFor(model => model.PageContent, new { @class = "control-label" }) @Html.LabelFor(model => model.PageContent, new
{
@class = "control-label"
})
<div class="wide-group"> <div class="wide-group">
@Html.TextAreaFor(model => model.PageContent, new { @class = "form-control" }) @Html.TextAreaFor(model => model.PageContent, new
{
@class = "form-control"
})
<div class="help-block"> <div class="help-block">
@Html.ValidationMessageFor(model => model.PageContent) @Html.ValidationMessageFor(model => model.PageContent)
</div> </div>
@ -53,36 +66,44 @@
<script type="text/javascript" src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> <script type="text/javascript" src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
function updateMetaCount() { function updateMetaCount()
{
var count = document.getElementById("@Html.IdFor(model => model.MetaDescription)").value.length; var count = document.getElementById("@Html.IdFor(model => model.MetaDescription)").value.length;
$("#meta-count").text(count.toFixed(0)); $("#meta-count").text(count.toFixed(0));
if (count === 0) { if (count === 0)
{
$("#meta-count").attr("class", ""); $("#meta-count").attr("class", "");
} }
else if (count < 160) { else if (count < 160)
{
$("#meta-count").attr("class", "text-success"); $("#meta-count").attr("class", "text-success");
} }
else { else
{
$("#meta-count").attr("class", "text-danger"); $("#meta-count").attr("class", "text-danger");
} }
} }
$(function () { $(function() {
var btnsGrps = $.trumbowyg.btnsGrps; var btnsGrps = $.trumbowyg.btnsGrps;
$("#@Html.IdFor(model => model.PageContent)").trumbowyg({ $("#@Html.IdFor(model => model.PageContent)")
semantic: true, .trumbowyg({
autogrow: true, semantic: true,
btns: ['viewHTML', autogrow: true,
'|', 'strong', 'em', btns: [
'|', 'link', 'viewHTML',
'|', btnsGrps.justify, '|', 'strong', 'em',
'|', btnsGrps.lists] '|', 'link',
}); '|', btnsGrps.justify,
'|', btnsGrps.lists
]
});
$("#@Html.IdFor(model => model.MetaDescription)").keyup(function () { $("#@Html.IdFor(model => model.MetaDescription)")
updateMetaCount(); .keyup(function() {
}); updateMetaCount();
});
updateMetaCount(); updateMetaCount();
}); });

View File

@ -1,4 +1,5 @@
@model BuildFeed.Areas.admin.Models.ViewModel.MetaListing @using BuildFeed.Models
@model BuildFeed.Areas.admin.Models.ViewModel.MetaListing
@{ @{
ViewBag.Title = "Metadata | BuildFeed"; ViewBag.Title = "Metadata | BuildFeed";
@ -12,48 +13,70 @@
<h3>Current items</h3> <h3>Current items</h3>
<table class="table table-striped table-bordered table-admin"> <table class="table table-striped table-bordered table-admin">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th style="width:50px"></th> <th style="width: 50px"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (var group in Model.CurrentItems) @foreach (IGrouping<MetaType, MetaItemModel> group in Model.CurrentItems)
{
<tr>
<td colspan="3">
<h4>@group.Key</h4>
</td>
</tr>
foreach (MetaItemModel item in group)
{ {
<tr> <tr>
<td colspan="3"><h4>@group.Key</h4></td> <td>@item.Id.Value</td>
<td>
@Html.ActionLink("Edit", "edit", new
{
type = item.Id.Type,
value = item.Id.Value
}, new
{
@class = "button",
style = "width:50px"
})</td>
</tr> </tr>
foreach (var item in group)
{
<tr>
<td>@item.Id.Value</td>
<td>@Html.ActionLink("Edit", "edit", new { type = item.Id.Type, value = item.Id.Value }, new { @class = "button", style = "width:50px" })</td>
</tr>
}
} }
}
</tbody> </tbody>
</table> </table>
<h3>Add new metadata</h3> <h3>Add new metadata</h3>
<table class="table table-striped table-bordered table-admin"> <table class="table table-striped table-bordered table-admin">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th style="width:50px"></th> <th style="width: 50px"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (var group in Model.NewItems) @foreach (IGrouping<MetaType, MetaItemModel> group in Model.NewItems)
{
<tr>
<td colspan="3">
<h4>@group.Key</h4>
</td>
</tr>
foreach (MetaItemModel item in group)
{ {
<tr> <tr>
<td colspan="3"><h4>@group.Key</h4></td> <td>@item.Id.Value</td>
<td>
@Html.ActionLink("Create", "create", new
{
type = item.Id.Type,
value = item.Id.Value
}, new
{
@class = "button",
style = "width:50px"
})</td>
</tr> </tr>
foreach (var item in group)
{
<tr>
<td>@item.Id.Value</td>
<td>@Html.ActionLink("Create", "create", new { type = item.Id.Type, value = item.Id.Value }, new { @class = "button", style = "width:50px" })</td>
</tr>
}
} }
}
</tbody> </tbody>
</table> </table>

View File

@ -14,32 +14,34 @@
<table class="table table-striped table-bordered table-admin"> <table class="table table-striped table-bordered table-admin">
<thead> <thead>
<tr> <tr>
<th> <th>
Username Username
</th> </th>
<th> <th>
Email Address Email Address
</th> </th>
<th> <th>
Last Login Time Last Login Time
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (MembershipUser mu in Model) @foreach (MembershipUser mu in Model)
{ {
<tr> <tr>
<td> <td>
@mu.UserName @mu.UserName
</td> </td>
<td> <td>
<a href="mailto:@mu.Email">@mu.Email</a> <a href="mailto:@mu.Email">@mu.Email</a>
</td> </td>
<td> <td>
@(mu.LastLoginDate == default(DateTime) ? "Never" : mu.LastLoginDate.Humanize()) @(mu.LastLoginDate == default(DateTime)
</td> ? "Never"
</tr> : mu.LastLoginDate.Humanize())
} </td>
</tr>
}
</tbody> </tbody>
</table> </table>

View File

@ -15,60 +15,94 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<th> <th>
Username Username
</th> </th>
<th> <th>
Email Address Email Address
</th> </th>
<th> <th>
Registration Time Registration Time
</th> </th>
<th> <th>
Last Login Time Last Login Time
</th> </th>
<th> <th>
Last Lockout Time Last Lockout Time
</th> </th>
<th style="width:108px;"></th> <th style="width: 108px;"></th>
<th style="width:108px;"></th> <th style="width: 108px;"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (MembershipUser mu in Model) @foreach (MembershipUser mu in Model)
{ {
<tr> <tr>
<td> <td>
@mu.UserName @mu.UserName
</td> </td>
<td> <td>
<a href="mailto:@mu.Email">@mu.Email</a> <a href="mailto:@mu.Email">@mu.Email</a>
</td> </td>
<td> <td>
@(mu.CreationDate == default(DateTime) ? "Never" : mu.CreationDate.Humanize()) @(mu.CreationDate == default(DateTime)
</td> ? "Never"
<td> : mu.CreationDate.Humanize())
@(mu.LastLoginDate == default(DateTime) ? "Never" : mu.LastLoginDate.Humanize()) </td>
</td> <td>
<td> @(mu.LastLoginDate == default(DateTime)
@(mu.LastLockoutDate == default(DateTime) ? "Never" : mu.LastLockoutDate.Humanize()) ? "Never"
</td> : mu.LastLoginDate.Humanize())
<td class="text-right"> </td>
@( <td>
mu.IsApproved ? @(mu.LastLockoutDate == default(DateTime)
Html.ActionLink("Unapprove", "unapprove", new { id = mu.ProviderUserKey }, new { @class = "button delete-button", style = "width:70px;" }) : ? "Never"
Html.ActionLink("Approve", "approve", new { id = mu.ProviderUserKey }, new { @class = "button add-button", style = "width:70px;" }) : mu.LastLockoutDate.Humanize())
) </td>
</td> <td class="text-right">
<td class="text-right"> @(
@( mu.IsApproved
!mu.IsLockedOut ? ? Html.ActionLink("Unapprove", "unapprove", new
Html.ActionLink("Lock", "lock", new { id = mu.ProviderUserKey }, new { @class = "button delete-button", style = "width:70px;" }) : {
Html.ActionLink("Unlock", "unlock", new { id = mu.ProviderUserKey }, new { @class = "button add-button", style = "width:70px;" }) id = mu.ProviderUserKey
) }, new
</td> {
</tr> @class = "button delete-button",
} style = "width:70px;"
})
: Html.ActionLink("Approve", "approve", new
{
id = mu.ProviderUserKey
}, new
{
@class = "button add-button",
style = "width:70px;"
})
)
</td>
<td class="text-right">
@(
!mu.IsLockedOut
? Html.ActionLink("Lock", "lock", new
{
id = mu.ProviderUserKey
}, new
{
@class = "button delete-button",
style = "width:70px;"
})
: Html.ActionLink("Unlock", "unlock", new
{
id = mu.ProviderUserKey
}, new
{
@class = "button add-button",
style = "width:70px;"
})
)
</td>
</tr>
}
</tbody> </tbody>
</table> </table>

View File

@ -1,34 +1,34 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<configuration> <configuration>
<configSections> <configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup> </sectionGroup>
</configSections> </configSections>
<system.web.webPages.razor> <system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage"> <pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces> <namespaces>
<add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" /> <add namespace="System.Web.Routing" />
<add namespace="BuildFeed" /> <add namespace="BuildFeed" />
</namespaces> </namespaces>
</pages> </pages>
</system.web.webPages.razor> </system.web.webPages.razor>
<appSettings> <appSettings>
<add key="webpages:Enabled" value="false" /> <add key="webpages:Enabled" value="false" />
</appSettings> </appSettings>
<system.webServer> <system.webServer>
<handlers> <handlers>
<remove name="BlockViewHandler"/> <remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers> </handlers>
</system.webServer> </system.webServer>
</configuration> </configuration>

View File

@ -2,23 +2,28 @@
namespace BuildFeed.Areas.admin namespace BuildFeed.Areas.admin
{ {
public class AdminAreaRegistration : AreaRegistration public class AdminAreaRegistration : AreaRegistration
{ {
public override string AreaName => "admin"; public override string AreaName => "admin";
public override void RegisterArea(AreaRegistrationContext context) public override void RegisterArea(AreaRegistrationContext context)
{ {
context.MapRoute( context.MapRoute("Meta",
"Meta", "admin/{controller}/{action}/{type}/{value}",
"admin/{controller}/{action}/{type}/{value}", new
new { action = "index", controller = "meta" } {
); action = "index",
controller = "meta"
});
context.MapRoute( context.MapRoute("Admin (Default)",
"Admin (Default)", "admin/{controller}/{action}/{id}",
"admin/{controller}/{action}/{id}", new
new { action = "index", controller = "base", id = UrlParameter.Optional } {
); action = "index",
} controller = "base",
} id = UrlParameter.Optional
});
}
}
} }

View File

@ -19,8 +19,8 @@ public override object BindModel(ControllerContext controllerContext, ModelBindi
} }
return success return success
? retValue as DateTime? ? retValue as DateTime?
: null; : null;
} }
} }
} }

View File

@ -75,8 +75,8 @@ public async Task<bool> AddWin10Builds(NewBuild apiModel)
Revision = nb.Revision, Revision = nb.Revision,
Lab = nb.Lab, Lab = nb.Lab,
BuildTime = nb.BuildTime.HasValue BuildTime = nb.BuildTime.HasValue
? DateTime.SpecifyKind(nb.BuildTime.Value, DateTimeKind.Utc) ? DateTime.SpecifyKind(nb.BuildTime.Value, DateTimeKind.Utc)
: null as DateTime?, : null as DateTime?,
Added = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc), Added = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc),
Modified = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc), Modified = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc),
SourceType = TypeOfSource.PrivateLeak SourceType = TypeOfSource.PrivateLeak
@ -104,12 +104,13 @@ where s.Text.ToLower().Contains(id.ToLower())
orderby s.Text.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascending orderby s.Text.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascending
select new SearchResult select new SearchResult
{ {
Url = Url.Route("Source Root", new Url = Url.Route("Source Root",
{ new
controller = "Front", {
action = "ViewSource", controller = "Front",
source = s.Value action = "ViewSource",
}), source = s.Value
}),
Label = s.Text.Replace(id, "<strong>" + id + "</strong>"), Label = s.Text.Replace(id, "<strong>" + id + "</strong>"),
Title = s.Text, Title = s.Text,
Group = VariantTerms.Search_Source Group = VariantTerms.Search_Source
@ -123,13 +124,14 @@ orderby s.Text.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascendi
orderby v.Major descending, v.Minor descending orderby v.Major descending, v.Minor descending
select new SearchResult select new SearchResult
{ {
Url = Url.Route("Version Root", new Url = Url.Route("Version Root",
{ new
controller = "Front", {
action = "ViewVersion", controller = "Front",
major = v.Major, action = "ViewVersion",
minor = v.Minor major = v.Major,
}), minor = v.Minor
}),
Label = $"{v.Major}.{v.Minor}".Replace(id, "<strong>" + id + "</strong>"), Label = $"{v.Major}.{v.Minor}".Replace(id, "<strong>" + id + "</strong>"),
Title = "", Title = "",
Group = VariantTerms.Search_Version Group = VariantTerms.Search_Version
@ -143,12 +145,13 @@ where y.ToString().Contains(id)
orderby y descending orderby y descending
select new SearchResult select new SearchResult
{ {
Url = Url.Route("Year Root", new Url = Url.Route("Year Root",
{ new
controller = "Front", {
action = "ViewYear", controller = "Front",
year = y action = "ViewYear",
}), year = y
}),
Label = y.ToString().Replace(id, "<strong>" + id + "</strong>"), Label = y.ToString().Replace(id, "<strong>" + id + "</strong>"),
Title = "", Title = "",
Group = VariantTerms.Search_Year Group = VariantTerms.Search_Year
@ -160,12 +163,13 @@ orderby y descending
IEnumerable<SearchResult> labResults = from l in await _bModel.SearchLabs(id) IEnumerable<SearchResult> labResults = from l in await _bModel.SearchLabs(id)
select new SearchResult select new SearchResult
{ {
Url = Url.Route("Lab Root", new Url = Url.Route("Lab Root",
{ new
controller = "Front", {
action = "ViewLab", controller = "Front",
lab = l.Replace('/', '-') action = "ViewLab",
}), lab = l.Replace('/', '-')
}),
Label = l.Replace(id, $"<strong>{id}</strong>"), Label = l.Replace(id, $"<strong>{id}</strong>"),
Title = l, Title = l,
Group = VariantTerms.Search_Lab Group = VariantTerms.Search_Lab
@ -179,12 +183,13 @@ where b.FullBuildString.ToLower().Contains(id.ToLower())
orderby b.FullBuildString.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascending, b.BuildTime descending orderby b.FullBuildString.ToLower().IndexOf(id.ToLower(), StringComparison.Ordinal) ascending, b.BuildTime descending
select new SearchResult select new SearchResult
{ {
Url = Url.Route("Build", new Url = Url.Route("Build",
{ new
controller = "Front", {
action = "ViewBuild", controller = "Front",
id = b.Id action = "ViewBuild",
}), id = b.Id
}),
Label = b.FullBuildString.Replace(id, $"<strong>{id}</strong>"), Label = b.FullBuildString.Replace(id, $"<strong>{id}</strong>"),
Title = b.FullBuildString, Title = b.FullBuildString,
Group = VariantTerms.Search_Build Group = VariantTerms.Search_Build

View File

@ -74,11 +74,12 @@ public async Task<ActionResult> ViewGroup(uint major, uint minor, uint number, u
List<BuildModel> builds = await _bModel.SelectGroup(bg); List<BuildModel> builds = await _bModel.SelectGroup(bg);
return builds.Count() == 1 return builds.Count() == 1
? RedirectToAction(nameof(ViewBuild), new ? RedirectToAction(nameof(ViewBuild),
{ new
id = builds.Single().Id {
}) as ActionResult id = builds.Single().Id
: View(new Tuple<BuildGroup, List<BuildModel>>(bg, builds)); }) as ActionResult
: View(new Tuple<BuildGroup, List<BuildModel>>(bg, builds));
} }
[Route("build/{id:guid}/", Name = "Build")] [Route("build/{id:guid}/", Name = "Build")]
@ -103,10 +104,11 @@ public async Task<ActionResult> ViewBuild(long id)
{ {
return new HttpNotFoundResult(); return new HttpNotFoundResult();
} }
return RedirectToAction(nameof(ViewBuild), new return RedirectToAction(nameof(ViewBuild),
{ new
id = b.Id {
}); id = b.Id
});
} }
[Route("twitter/{id:guid}/", Name = "Twitter")] [Route("twitter/{id:guid}/", Name = "Twitter")]
@ -126,8 +128,8 @@ public async Task<ActionResult> TwitterCard(Guid id)
bool backExists = System.IO.File.Exists(path); bool backExists = System.IO.File.Exists(path);
using (Bitmap bm = backExists using (Bitmap bm = backExists
? new Bitmap(path) ? new Bitmap(path)
: new Bitmap(1120, 600)) : new Bitmap(1120, 600))
{ {
using (Graphics gr = Graphics.FromImage(bm)) using (Graphics gr = Graphics.FromImage(bm))
{ {
@ -148,8 +150,13 @@ public async Task<ActionResult> TwitterCard(Guid id)
gp.AddString($"{MvcExtensions.GetDisplayTextForEnum(b.Family)} (WinNT {b.MajorVersion}.{b.MinorVersion})", new FontFamily("Segoe UI"), 0, 48, new Point(40, 80), StringFormat.GenericTypographic); gp.AddString($"{MvcExtensions.GetDisplayTextForEnum(b.Family)} (WinNT {b.MajorVersion}.{b.MinorVersion})", new FontFamily("Segoe UI"), 0, 48, new Point(40, 80), StringFormat.GenericTypographic);
gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 280, new Point(32, 96), StringFormat.GenericTypographic); gp.AddString(b.Number.ToString(), new FontFamily("Segoe UI Light"), 0, 280, new Point(32, 96), StringFormat.GenericTypographic);
gp.AddString(b.BuildTime.HasValue gp.AddString(b.BuildTime.HasValue
? $"{b.Lab}\r\n{b.BuildTime.Value:yyyy/MM/dd HH:mm}" ? $"{b.Lab}\r\n{b.BuildTime.Value:yyyy/MM/dd HH:mm}"
: $"{b.Lab}", new FontFamily("Segoe UI"), 0, 44, new Point(40, 440), StringFormat.GenericTypographic); : $"{b.Lab}",
new FontFamily("Segoe UI"),
0,
44,
new Point(40, 440),
StringFormat.GenericTypographic);
gr.FillPath(Brushes.White, gp); gr.FillPath(Brushes.White, gp);
Response.ContentType = "image/png"; Response.ContentType = "image/png";
@ -168,17 +175,21 @@ public async Task<ActionResult> TwitterCard(long id)
{ {
return new HttpNotFoundResult(); return new HttpNotFoundResult();
} }
return RedirectToAction(nameof(TwitterCard), new return RedirectToAction(nameof(TwitterCard),
{ new
id = b.Id {
}); id = b.Id
});
} }
[Route("lab/{lab}/", Order = 1, Name = "Lab Root")] [Route("lab/{lab}/", Order = 1, Name = "Lab Root")]
#if !DEBUG #if !DEBUG
// [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")] // [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif #endif
public async Task<ActionResult> ViewLab(string lab) { return await ViewLabPage(lab, 1); } public async Task<ActionResult> ViewLab(string lab)
{
return await ViewLabPage(lab, 1);
}
[Route("lab/{lab}/page-{page:int:min(2)}/", Order = 0)] [Route("lab/{lab}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG #if !DEBUG
@ -210,7 +221,10 @@ public async Task<ActionResult> ViewLabPage(string lab, int page)
#if !DEBUG #if !DEBUG
// [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")] // [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif #endif
public async Task<ActionResult> ViewSource(TypeOfSource source) { return await ViewSourcePage(source, 1); } public async Task<ActionResult> ViewSource(TypeOfSource source)
{
return await ViewSourcePage(source, 1);
}
[Route("source/{source}/page-{page:int:min(2)}/", Order = 0)] [Route("source/{source}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG #if !DEBUG
@ -242,7 +256,10 @@ public async Task<ActionResult> ViewSourcePage(TypeOfSource source, int page)
#if !DEBUG #if !DEBUG
// [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")] // [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif #endif
public async Task<ActionResult> ViewYear(int year) { return await ViewYearPage(year, 1); } public async Task<ActionResult> ViewYear(int year)
{
return await ViewYearPage(year, 1);
}
[Route("year/{year}/page-{page:int:min(2)}/", Order = 0)] [Route("year/{year}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG #if !DEBUG
@ -274,7 +291,10 @@ public async Task<ActionResult> ViewYearPage(int year, int page)
#if !DEBUG #if !DEBUG
// [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")] // [OutputCache(Duration = 600, VaryByParam = "none", VaryByCustom = "userName")]
#endif #endif
public async Task<ActionResult> ViewVersion(uint major, uint minor) { return await ViewVersionPage(major, minor, 1); } public async Task<ActionResult> ViewVersion(uint major, uint minor)
{
return await ViewVersionPage(major, minor, 1);
}
[Route("version/{major}.{minor}/page-{page:int:min(2)}/", Order = 0)] [Route("version/{major}.{minor}/page-{page:int:min(2)}/", Order = 0)]
#if !DEBUG #if !DEBUG
@ -336,10 +356,11 @@ public async Task<ActionResult> AddBuild(BuildModel build)
{ {
return View("EditBuild", build); return View("EditBuild", build);
} }
return RedirectToAction(nameof(ViewBuild), new return RedirectToAction(nameof(ViewBuild),
{ new
id = build.Id {
}); id = build.Id
});
} }
return View("EditBuild", build); return View("EditBuild", build);
} }
@ -373,10 +394,11 @@ public async Task<ActionResult> EditBuild(Guid id, BuildModel build)
return View(build); return View(build);
} }
return RedirectToAction(nameof(ViewBuild), new return RedirectToAction(nameof(ViewBuild),
{ new
id = build.Id {
}); id = build.Id
});
} }
return View(build); return View(build);
} }

View File

@ -4,7 +4,6 @@
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Mvc; using System.Web.Mvc;
using BuildFeed.Code;
using BuildFeed.Models; using BuildFeed.Models;
using WilderMinds.RssSyndication; using WilderMinds.RssSyndication;

View File

@ -33,8 +33,8 @@ public ActionResult Login(LoginUser ru)
if (isAuthenticated) if (isAuthenticated)
{ {
int expiryLength = ru.RememberMe int expiryLength = ru.RememberMe
? 129600 ? 129600
: 60; : 60;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(ru.UserName, true, expiryLength); FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(ru.UserName, true, expiryLength);
string encryptedTicket = FormsAuthentication.Encrypt(ticket); string encryptedTicket = FormsAuthentication.Encrypt(ticket);
@ -46,8 +46,8 @@ public ActionResult Login(LoginUser ru)
Response.Cookies.Add(cookieTicket); Response.Cookies.Add(cookieTicket);
string returnUrl = string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]) string returnUrl = string.IsNullOrEmpty(Request.QueryString["ReturnUrl"])
? "/" ? "/"
: Request.QueryString["ReturnUrl"]; : Request.QueryString["ReturnUrl"];
return Redirect(returnUrl); return Redirect(returnUrl);
} }
@ -141,90 +141,100 @@ public async Task<ActionResult> Sitemap()
List<BuildModel> builds = await _bModel.SelectBuildsByOrder(); List<BuildModel> builds = await _bModel.SelectBuildsByOrder();
Dictionary<string, SitemapPagedAction[]> actions = new Dictionary<string, SitemapPagedAction[]> Dictionary<string, SitemapPagedAction[]> actions = new Dictionary<string, SitemapPagedAction[]>
{ {
{ "Pages", new[]
{ {
new SitemapPagedAction "Pages", new[]
{ {
UrlParams = new RouteValueDictionary(new new SitemapPagedAction
{ {
controller = "Front", UrlParams = new RouteValueDictionary(new
action = "Index", {
page = 1 controller = "Front",
}), action = "Index",
Pages = (builds.Count + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE page = 1
}),
Pages = (builds.Count + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE
}
} }
} }, },
{ "Versions", (from b in builds {
group b by new BuildVersion "Versions", (from b in builds
{ group b by new BuildVersion
Major = b.MajorVersion, {
Minor = b.MinorVersion Major = b.MajorVersion,
} Minor = b.MinorVersion
into bv }
orderby bv.Key.Major descending, bv.Key.Minor descending into bv
select new SitemapPagedAction orderby bv.Key.Major descending, bv.Key.Minor descending
{ select new SitemapPagedAction
Name = $"{InvariantTerms.ProductName} {bv.Key.Major}.{bv.Key.Minor}", {
UrlParams = new RouteValueDictionary(new Name = $"{InvariantTerms.ProductName} {bv.Key.Major}.{bv.Key.Minor}",
{ UrlParams = new RouteValueDictionary(new
controller = "Front", {
action = "ViewVersion", controller = "Front",
major = bv.Key.Major, action = "ViewVersion",
minor = bv.Key.Minor, major = bv.Key.Major,
page = 1 minor = bv.Key.Minor,
}), page = 1
Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE }),
}).ToArray() }, Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE
{ "Labs", (from b in builds }).ToArray()
where !string.IsNullOrEmpty(b.Lab) },
group b by b.Lab {
into bv "Labs", (from b in builds
orderby bv.Key where !string.IsNullOrEmpty(b.Lab)
select new SitemapPagedAction group b by b.Lab
{
Name = bv.Key,
UrlParams = new RouteValueDictionary(new
{
controller = "Front",
action = "ViewLab",
lab = bv.Key,
page = 1
}),
Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE
}).ToArray() },
{ "Years", (from b in builds
where b.BuildTime.HasValue
group b by b.BuildTime.Value.Year
into bv into bv
orderby bv.Key descending orderby bv.Key
select new SitemapPagedAction select new SitemapPagedAction
{ {
Name = bv.Key.ToString(), Name = bv.Key,
UrlParams = new RouteValueDictionary(new UrlParams = new RouteValueDictionary(new
{ {
controller = "Front", controller = "Front",
action = "ViewYear", action = "ViewLab",
year = bv.Key, lab = bv.Key,
page = 1 page = 1
}), }),
Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE
}).ToArray() }, }).ToArray()
{ "Sources", (from b in builds },
group b by b.SourceType {
into bv "Years", (from b in builds
orderby bv.Key where b.BuildTime.HasValue
select new SitemapPagedAction group b by b.BuildTime.Value.Year
{ into bv
Name = MvcExtensions.GetDisplayTextForEnum(bv.Key), orderby bv.Key descending
UrlParams = new RouteValueDictionary(new select new SitemapPagedAction
{ {
controller = "Front", Name = bv.Key.ToString(),
action = "ViewSource", UrlParams = new RouteValueDictionary(new
source = bv.Key, {
page = 1 controller = "Front",
}), action = "ViewYear",
Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE year = bv.Key,
}).ToArray() } page = 1
}),
Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE
}).ToArray()
},
{
"Sources", (from b in builds
group b by b.SourceType
into bv
orderby bv.Key
select new SitemapPagedAction
{
Name = MvcExtensions.GetDisplayTextForEnum(bv.Key),
UrlParams = new RouteValueDictionary(new
{
controller = "Front",
action = "ViewSource",
source = bv.Key,
page = 1
}),
Pages = (bv.Count() + (FrontController.PAGE_SIZE - 1)) / FrontController.PAGE_SIZE
}).ToArray()
}
}; };
@ -284,10 +294,13 @@ public async Task<ActionResult> XmlSitemap()
foreach (BuildModel b in await _bModel.Select()) foreach (BuildModel b in await _bModel.Select())
{ {
XElement url = new XElement(xn + "url"); XElement url = new XElement(xn + "url");
url.Add(new XElement(xn + "loc", Request.Url?.GetLeftPart(UriPartial.Authority) + Url.Action("ViewBuild", "Front", new url.Add(new XElement(xn + "loc",
{ Request.Url?.GetLeftPart(UriPartial.Authority) + Url.Action("ViewBuild",
id = b.Id "Front",
}))); new
{
id = b.Id
})));
if (b.Modified != DateTime.MinValue) if (b.Modified != DateTime.MinValue)
{ {
url.Add(new XElement(xn + "lastmod", b.Modified.ToString("yyyy-MM-dd"))); url.Add(new XElement(xn + "lastmod", b.Modified.ToString("yyyy-MM-dd")));

View File

@ -13,13 +13,14 @@ public async Task<FrontBuildGroup[]> SelectAllGroups(int limit = -1, int skip =
{ {
IAggregateFluent<BsonDocument> query = _buildCollection.Aggregate().Group(new BsonDocument IAggregateFluent<BsonDocument> query = _buildCollection.Aggregate().Group(new BsonDocument
{ {
new BsonElement("_id", new BsonDocument new BsonElement("_id",
{ new BsonDocument
new BsonElement(nameof(BuildGroup.Major), $"${nameof(BuildModel.MajorVersion)}"), {
new BsonElement(nameof(BuildGroup.Minor), $"${nameof(BuildModel.MinorVersion)}"), new BsonElement(nameof(BuildGroup.Major), $"${nameof(BuildModel.MajorVersion)}"),
new BsonElement(nameof(BuildGroup.Build), $"${nameof(BuildModel.Number)}"), new BsonElement(nameof(BuildGroup.Minor), $"${nameof(BuildModel.MinorVersion)}"),
new BsonElement(nameof(BuildGroup.Revision), $"${nameof(BuildModel.Revision)}") new BsonElement(nameof(BuildGroup.Build), $"${nameof(BuildModel.Number)}"),
}), new BsonElement(nameof(BuildGroup.Revision), $"${nameof(BuildModel.Revision)}")
}),
new BsonElement("date", new BsonDocument("$max", $"${nameof(BuildModel.BuildTime)}")), new BsonElement("date", new BsonDocument("$max", $"${nameof(BuildModel.BuildTime)}")),
new BsonElement("count", new BsonDocument("$sum", 1)) new BsonElement("count", new BsonDocument("$sum", 1))
}).Sort(new BsonDocument }).Sort(new BsonDocument
@ -56,13 +57,14 @@ public async Task<long> SelectAllGroupsCount()
{ {
List<BsonDocument> grouping = await _buildCollection.Aggregate().Group(new BsonDocument List<BsonDocument> grouping = await _buildCollection.Aggregate().Group(new BsonDocument
{ {
new BsonElement("_id", new BsonDocument new BsonElement("_id",
{ new BsonDocument
new BsonElement(nameof(BuildGroup.Major), $"${nameof(BuildModel.MajorVersion)}"), {
new BsonElement(nameof(BuildGroup.Minor), $"${nameof(BuildModel.MinorVersion)}"), new BsonElement(nameof(BuildGroup.Major), $"${nameof(BuildModel.MajorVersion)}"),
new BsonElement(nameof(BuildGroup.Build), $"${nameof(BuildModel.Number)}"), new BsonElement(nameof(BuildGroup.Minor), $"${nameof(BuildModel.MinorVersion)}"),
new BsonElement(nameof(BuildGroup.Revision), $"${nameof(BuildModel.Revision)}") new BsonElement(nameof(BuildGroup.Build), $"${nameof(BuildModel.Number)}"),
}) new BsonElement(nameof(BuildGroup.Revision), $"${nameof(BuildModel.Revision)}")
})
}).ToListAsync(); }).ToListAsync();
return grouping.Count; return grouping.Count;
} }
@ -88,15 +90,12 @@ public async Task<List<BuildModel>> SelectGroup(BuildGroup group, int limit = -1
return await query.ToListAsync(); return await query.ToListAsync();
} }
public async Task<long> SelectGroupCount(BuildGroup group) public async Task<long> SelectGroupCount(BuildGroup group) => await _buildCollection.CountAsync(new BsonDocument
{ {
return await _buildCollection.CountAsync(new BsonDocument new BsonElement(nameof(BuildModel.MajorVersion), @group.Major),
{ new BsonElement(nameof(BuildModel.MinorVersion), @group.Minor),
new BsonElement(nameof(BuildModel.MajorVersion), group.Major), new BsonElement(nameof(BuildModel.Number), @group.Build),
new BsonElement(nameof(BuildModel.MinorVersion), group.Minor), new BsonElement(nameof(BuildModel.Revision), @group.Revision)
new BsonElement(nameof(BuildModel.Number), group.Build), });
new BsonElement(nameof(BuildModel.Revision), group.Revision)
});
}
} }
} }

View File

@ -43,7 +43,7 @@ public async Task<string[]> SelectLabsForVersion(int major, int minor)
public async Task<List<string>> SearchLabs(string search) public async Task<List<string>> SearchLabs(string search)
{ {
List<Tuple<string>> result = await _buildCollection.Aggregate().Match(b => b.Lab != null).Match(b => b.Lab != "").Match(b => b.Lab.ToLower().Contains(search.ToLower())).Group(b => b.Lab.ToLower(), List<Tuple<string>> result = await _buildCollection.Aggregate().Match(b => b.Lab != null).Match(b => b.Lab != "").Match(b => b.Lab.ToLower().Contains(search.ToLower())).Group(b => b.Lab.ToLower(),
// incoming bullshit hack // incoming bullshit hack
bg => new Tuple<string>(bg.Key)).ToListAsync(); bg => new Tuple<string>(bg.Key)).ToListAsync();
// work ourselves out of aforementioned bullshit hack // work ourselves out of aforementioned bullshit hack
@ -71,6 +71,6 @@ public async Task<List<BuildModel>> SelectLab(string lab, int limit = -1, int sk
return await query.ToListAsync(); return await query.ToListAsync();
} }
public async Task<long> SelectLabCount(string lab) { return await _buildCollection.CountAsync(new BsonDocument(nameof(BuildModel.LabUrl), lab)); } public async Task<long> SelectLabCount(string lab) => await _buildCollection.CountAsync(new BsonDocument(nameof(BuildModel.LabUrl), lab));
} }
} }

View File

@ -8,9 +8,9 @@ namespace BuildFeed.Models
{ {
public partial class Build public partial class Build
{ {
public Task<TypeOfSource[]> SelectAllSources(int limit = -1, int skip = 0) { return Task.Run(() => Enum.GetValues(typeof(TypeOfSource)) as TypeOfSource[]); } public Task<TypeOfSource[]> SelectAllSources(int limit = -1, int skip = 0) => Task.Run(() => Enum.GetValues(typeof(TypeOfSource)) as TypeOfSource[]);
public Task<long> SelectAllSourcesCount() { return Task.Run(() => Enum.GetValues(typeof(TypeOfSource)).LongLength); } public Task<long> SelectAllSourcesCount() => Task.Run(() => Enum.GetValues(typeof(TypeOfSource)).LongLength);
public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int limit = -1, int skip = 0) public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int limit = -1, int skip = 0)
{ {
@ -24,6 +24,6 @@ public async Task<List<BuildModel>> SelectSource(TypeOfSource source, int limit
return await query.ToListAsync(); return await query.ToListAsync();
} }
public async Task<long> SelectSourceCount(TypeOfSource source) { return await _buildCollection.CountAsync(new BsonDocument(nameof(BuildModel.SourceType), source)); } public async Task<long> SelectSourceCount(TypeOfSource source) => await _buildCollection.CountAsync(new BsonDocument(nameof(BuildModel.SourceType), source));
} }
} }

View File

@ -10,15 +10,16 @@ public partial class Build
{ {
public async Task<BuildVersion[]> SelectAllVersions(int limit = -1, int skip = 0) public async Task<BuildVersion[]> SelectAllVersions(int limit = -1, int skip = 0)
{ {
IAggregateFluent<BsonDocument> query = _buildCollection.Aggregate().Group(new BsonDocument("_id", new BsonDocument IAggregateFluent<BsonDocument> query = _buildCollection.Aggregate().Group(new BsonDocument("_id",
{ new BsonDocument
new BsonElement(nameof(BuildVersion.Major), $"${nameof(BuildModel.MajorVersion)}"), {
new BsonElement(nameof(BuildVersion.Minor), $"${nameof(BuildModel.MinorVersion)}") new BsonElement(nameof(BuildVersion.Major), $"${nameof(BuildModel.MajorVersion)}"),
})).Sort(new BsonDocument new BsonElement(nameof(BuildVersion.Minor), $"${nameof(BuildModel.MinorVersion)}")
{ })).Sort(new BsonDocument
new BsonElement($"_id.{nameof(BuildVersion.Major)}", -1), {
new BsonElement($"_id.{nameof(BuildVersion.Minor)}", -1) new BsonElement($"_id.{nameof(BuildVersion.Major)}", -1),
}).Skip(skip); new BsonElement($"_id.{nameof(BuildVersion.Minor)}", -1)
}).Skip(skip);
if (limit > 0) if (limit > 0)
{ {
@ -37,11 +38,12 @@ public async Task<BuildVersion[]> SelectAllVersions(int limit = -1, int skip = 0
public async Task<long> SelectAllVersionsCount() public async Task<long> SelectAllVersionsCount()
{ {
List<BsonDocument> query = await _buildCollection.Aggregate().Group(new BsonDocument("_id", new BsonDocument List<BsonDocument> query = await _buildCollection.Aggregate().Group(new BsonDocument("_id",
{ new BsonDocument
new BsonElement(nameof(BuildVersion.Major), $"${nameof(BuildModel.MajorVersion)}"), {
new BsonElement(nameof(BuildVersion.Minor), $"${nameof(BuildModel.MinorVersion)}") new BsonElement(nameof(BuildVersion.Major), $"${nameof(BuildModel.MajorVersion)}"),
})).ToListAsync(); new BsonElement(nameof(BuildVersion.Minor), $"${nameof(BuildModel.MinorVersion)}")
})).ToListAsync();
return query.Count; return query.Count;
} }
@ -61,13 +63,10 @@ public async Task<List<BuildModel>> SelectVersion(uint major, uint minor, int li
return await query.ToListAsync(); return await query.ToListAsync();
} }
public async Task<long> SelectVersionCount(uint major, uint minor) public async Task<long> SelectVersionCount(uint major, uint minor) => await _buildCollection.CountAsync(new BsonDocument
{ {
return await _buildCollection.CountAsync(new BsonDocument new BsonElement(nameof(BuildModel.MajorVersion), major),
{ new BsonElement(nameof(BuildModel.MinorVersion), minor)
new BsonElement(nameof(BuildModel.MajorVersion), major), });
new BsonElement(nameof(BuildModel.MinorVersion), minor)
});
}
} }
} }

View File

@ -11,7 +11,12 @@ public partial class Build
{ {
public async Task<int[]> SelectAllYears(int limit = -1, int skip = 0) public async Task<int[]> SelectAllYears(int limit = -1, int skip = 0)
{ {
IAggregateFluent<BsonDocument> query = _buildCollection.Aggregate().Match(Builders<BuildModel>.Filter.Ne(b => b.BuildTime, null)).Group(new BsonDocument("_id", new BsonDocument("$year", $"${nameof(BuildModel.BuildTime)}"))).Sort(new BsonDocument("_id", -1)).Skip(skip); IAggregateFluent<BsonDocument> query =
_buildCollection.Aggregate()
.Match(Builders<BuildModel>.Filter.Ne(b => b.BuildTime, null))
.Group(new BsonDocument("_id", new BsonDocument("$year", $"${nameof(BuildModel.BuildTime)}")))
.Sort(new BsonDocument("_id", -1))
.Skip(skip);
if (limit > 0) if (limit > 0)
{ {
@ -34,7 +39,9 @@ public async Task<long> SelectAllYearsCount()
public async Task<List<BuildModel>> SelectYear(int year, int limit = -1, int skip = 0) public async Task<List<BuildModel>> SelectYear(int year, int limit = -1, int skip = 0)
{ {
IFindFluent<BuildModel, BuildModel> query = _buildCollection.Find(Builders<BuildModel>.Filter.And(Builders<BuildModel>.Filter.Gte(b => b.BuildTime, new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc)), Builders<BuildModel>.Filter.Lte(b => b.BuildTime, new DateTime(year, 12, 31, 23, 59, 59, DateTimeKind.Utc)))).Sort(sortByCompileDate).Skip(skip); IFindFluent<BuildModel, BuildModel> query =
_buildCollection.Find(Builders<BuildModel>.Filter.And(Builders<BuildModel>.Filter.Gte(b => b.BuildTime, new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
Builders<BuildModel>.Filter.Lte(b => b.BuildTime, new DateTime(year, 12, 31, 23, 59, 59, DateTimeKind.Utc)))).Sort(sortByCompileDate).Skip(skip);
if (limit > 0) if (limit > 0)
{ {
@ -44,6 +51,10 @@ public async Task<List<BuildModel>> SelectYear(int year, int limit = -1, int ski
return await query.ToListAsync(); return await query.ToListAsync();
} }
public async Task<long> SelectYearCount(int year) { return await _buildCollection.CountAsync(Builders<BuildModel>.Filter.And(Builders<BuildModel>.Filter.Gte(b => b.BuildTime, new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc)), Builders<BuildModel>.Filter.Lte(b => b.BuildTime, new DateTime(year, 12, 31, 23, 59, 59, DateTimeKind.Utc)))); } public async Task<long> SelectYearCount(int year)
=>
await
_buildCollection.CountAsync(Builders<BuildModel>.Filter.And(Builders<BuildModel>.Filter.Gte(b => b.BuildTime, new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
Builders<BuildModel>.Filter.Lte(b => b.BuildTime, new DateTime(year, 12, 31, 23, 59, 59, DateTimeKind.Utc))));
} }
} }

View File

@ -46,26 +46,34 @@ public async Task SetupIndexes()
List<BsonDocument> indexes = await (await _buildCollection.Indexes.ListAsync()).ToListAsync(); List<BsonDocument> indexes = await (await _buildCollection.Indexes.ListAsync()).ToListAsync();
if (indexes.All(i => i["name"] != "_idx_group")) if (indexes.All(i => i["name"] != "_idx_group"))
{ {
await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Combine(Builders<BuildModel>.IndexKeys.Descending(b => b.MajorVersion), Builders<BuildModel>.IndexKeys.Descending(b => b.MinorVersion), Builders<BuildModel>.IndexKeys.Descending(b => b.Number), Builders<BuildModel>.IndexKeys.Descending(b => b.Revision)), new CreateIndexOptions await
{ _buildCollection.Indexes.CreateOneAsync(
Name = "_idx_group" Builders<BuildModel>.IndexKeys.Combine(Builders<BuildModel>.IndexKeys.Descending(b => b.MajorVersion),
}); Builders<BuildModel>.IndexKeys.Descending(b => b.MinorVersion),
Builders<BuildModel>.IndexKeys.Descending(b => b.Number),
Builders<BuildModel>.IndexKeys.Descending(b => b.Revision)),
new CreateIndexOptions
{
Name = "_idx_group"
});
} }
if (indexes.All(i => i["name"] != "_idx_legacy")) if (indexes.All(i => i["name"] != "_idx_legacy"))
{ {
await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Ascending(b => b.LegacyId), new CreateIndexOptions await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Ascending(b => b.LegacyId),
{ new CreateIndexOptions
Name = "_idx_legacy" {
}); Name = "_idx_legacy"
});
} }
if (indexes.All(i => i["name"] != "_idx_lab")) if (indexes.All(i => i["name"] != "_idx_lab"))
{ {
await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Ascending(b => b.Lab), new CreateIndexOptions await _buildCollection.Indexes.CreateOneAsync(Builders<BuildModel>.IndexKeys.Ascending(b => b.Lab),
{ new CreateIndexOptions
Name = "_idx_lab" {
}); Name = "_idx_lab"
});
} }
} }
@ -98,44 +106,60 @@ public async Task<FrontPage> SelectFrontPage()
IFindFluent<BuildModel, BuildModel> query = _buildCollection.Find(new BsonDocument IFindFluent<BuildModel, BuildModel> query = _buildCollection.Find(new BsonDocument
{ {
{ nameof(BuildModel.LabUrl), new BsonDocument
{ {
{ "$in", new BsonArray(ConfigurationManager.AppSettings["site:OSGLab"].Split(';')) } nameof(BuildModel.LabUrl), new BsonDocument
} } {
{ "$in", new BsonArray(ConfigurationManager.AppSettings["site:OSGLab"].Split(';')) }
}
}
}).Sort(sortByCompileDate).Limit(1); }).Sort(sortByCompileDate).Limit(1);
fp.CurrentCanary = (await query.ToListAsync())[0]; fp.CurrentCanary = (await query.ToListAsync())[0];
query = _buildCollection.Find(new BsonDocument query = _buildCollection.Find(new BsonDocument
{ {
{ nameof(BuildModel.LabUrl), new BsonDocument
{ {
{ "$in", new BsonArray(ConfigurationManager.AppSettings["site:InsiderLab"].Split(';')) } nameof(BuildModel.LabUrl), new BsonDocument
} },
{ nameof(BuildModel.SourceType), new BsonDocument
{
{ "$in", new BsonArray()
{ {
TypeOfSource.PublicRelease, TypeOfSource.UpdateGDR { "$in", new BsonArray(ConfigurationManager.AppSettings["site:InsiderLab"].Split(';')) }
} } }
} } },
{
nameof(BuildModel.SourceType), new BsonDocument
{
{
"$in", new BsonArray
{
TypeOfSource.PublicRelease,
TypeOfSource.UpdateGDR
}
}
}
}
}).Sort(sortByCompileDate).Limit(1); }).Sort(sortByCompileDate).Limit(1);
fp.CurrentInsider = (await query.ToListAsync())[0]; fp.CurrentInsider = (await query.ToListAsync())[0];
query = _buildCollection.Find(new BsonDocument query = _buildCollection.Find(new BsonDocument
{ {
{ nameof(BuildModel.LabUrl), new BsonDocument
{ {
{ "$in", new BsonArray(ConfigurationManager.AppSettings["site:ReleaseLab"].Split(';')) } nameof(BuildModel.LabUrl), new BsonDocument
} },
{ nameof(BuildModel.SourceType), new BsonDocument
{
{ "$in", new BsonArray()
{ {
TypeOfSource.PublicRelease, TypeOfSource.UpdateGDR { "$in", new BsonArray(ConfigurationManager.AppSettings["site:ReleaseLab"].Split(';')) }
} } }
} } },
{
nameof(BuildModel.SourceType), new BsonDocument
{
{
"$in", new BsonArray
{
TypeOfSource.PublicRelease,
TypeOfSource.UpdateGDR
}
}
}
}
}).Sort(sortByCompileDate).Limit(1); }).Sort(sortByCompileDate).Limit(1);
fp.CurrentRelease = (await query.ToListAsync())[0]; fp.CurrentRelease = (await query.ToListAsync())[0];
@ -217,6 +241,9 @@ public async Task Update(BuildModel item)
} }
[DataObjectMethod(DataObjectMethodType.Delete, true)] [DataObjectMethod(DataObjectMethodType.Delete, true)]
public async Task DeleteById(Guid id) { await _buildCollection.DeleteOneAsync(Builders<BuildModel>.Filter.Eq(b => b.Id, id)); } public async Task DeleteById(Guid id)
{
await _buildCollection.DeleteOneAsync(Builders<BuildModel>.Filter.Eq(b => b.Id, id));
}
} }
} }

View File

@ -8,7 +8,7 @@ public class BuildGroup
public uint? Revision { get; set; } public uint? Revision { get; set; }
public override string ToString() => Revision.HasValue public override string ToString() => Revision.HasValue
? $"{Major}.{Minor}.{Build}.{Revision.Value}" ? $"{Major}.{Minor}.{Build}.{Revision.Value}"
: $"{Major}.{Minor}.{Build}"; : $"{Major}.{Minor}.{Build}";
} }
} }

View File

@ -141,7 +141,8 @@ public ProjectFamily Family
{ {
return ProjectFamily.Windows7; return ProjectFamily.Windows7;
} }
if (MajorVersion == 6 && Number >= 5000) if (MajorVersion == 6
&& Number >= 5000)
{ {
return ProjectFamily.WindowsVista; return ProjectFamily.WindowsVista;
} }
@ -149,15 +150,18 @@ public ProjectFamily Family
{ {
return ProjectFamily.Longhorn; return ProjectFamily.Longhorn;
} }
if (MajorVersion == 5 && Number >= 3000) if (MajorVersion == 5
&& Number >= 3000)
{ {
return ProjectFamily.Server2003; return ProjectFamily.Server2003;
} }
if (MajorVersion == 5 && Number >= 2205) if (MajorVersion == 5
&& Number >= 2205)
{ {
return ProjectFamily.WindowsXP; return ProjectFamily.WindowsXP;
} }
if (MajorVersion == 5 && MinorVersion == 50) if (MajorVersion == 5
&& MinorVersion == 50)
{ {
return ProjectFamily.Neptune; return ProjectFamily.Neptune;
} }
@ -169,9 +173,6 @@ public ProjectFamily Family
} }
} }
public string GenerateLabUrl() => (Lab ?? "").Replace('/', '-')
.ToLower();
public string SourceDetailsFiltered public string SourceDetailsFiltered
{ {
get get
@ -190,5 +191,7 @@ public string SourceDetailsFiltered
return SourceDetails; return SourceDetails;
} }
} }
public string GenerateLabUrl() => (Lab ?? "").Replace('/', '-').ToLower();
} }
} }

View File

@ -3,17 +3,17 @@
namespace BuildFeed.Models.ViewModel namespace BuildFeed.Models.ViewModel
{ {
public class LoginUser public class LoginUser
{ {
[Required] [Required]
[Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_UserName))] [Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_UserName))]
public string UserName { get; set; } public string UserName { get; set; }
[Required] [Required]
[Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_Password))] [Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_Password))]
public string Password { get; set; } public string Password { get; set; }
[Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_RememberMe))] [Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_RememberMe))]
public bool RememberMe { get; set; } public bool RememberMe { get; set; }
} }
} }

View File

@ -6,10 +6,8 @@ namespace BuildFeed.Models.ViewModel
public class RegistrationUser public class RegistrationUser
{ {
[Required] [Required]
[MinLength(8)] [Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_UserName))]
[Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_ConfirmPassword))] public string UserName { get; set; }
[Compare("Password")]
public string ConfirmPassword { get; set; }
[Required] [Required]
[EmailAddress] [EmailAddress]
@ -22,7 +20,9 @@ public class RegistrationUser
public string Password { get; set; } public string Password { get; set; }
[Required] [Required]
[Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_UserName))] [MinLength(8)]
public string UserName { get; set; } [Display(ResourceType = typeof(VariantTerms), Name = nameof(VariantTerms.Support_ConfirmPassword))]
[Compare(nameof(Password))]
public string ConfirmPassword { get; set; }
} }
} }