/// <summary> /// Returns a Json serialized list of Person (user) that only specifies username. /// </summary> /// <returns>Json list of Person</returns> public ActionResult GetPersons() { using (DataContext context = new DataContext()) { return Content ( JsonConvert.SerializeObject(context.Persons.ToList().Select(x=> new Person() { Username = x.Username }))); } }
/// <summary> /// Renews a LoginSession and replaces an already existing session. /// </summary> /// <param name="context">DataContext</param> /// <param name="session">LoginSession</param> /// <param name="person">Person (user)</param> /// <returns>LoginSession</returns> public static LoginSession RenewSession(DataContext context,LoginSession session,Person person) { session = new LoginSession (Guid.NewGuid ().ToString (), DateTime.Now); if (person.LoginSession != null) context.LoginSessions.Remove (person.LoginSession); person.LoginSession = session; context.SaveChanges(); return session; }
/// <summary> /// Validates a string token representing a LoginSession. Will keep the LoginSession up to date if it's valid. /// </summary> /// <param name="context">DateContext</param> /// <param name="token">String token</param> /// <returns>bool valid</returns> public static bool ValidateLoginSession(DataContext context,string token) { Person person = context.Persons.FirstOrDefault (x => x.LoginSessionToken != null && x.LoginSessionToken == token); int loginLifetimeMs = Convert.ToInt32(WebConfigurationManager.AppSettings["LoginLifetimeMs"]); if (person == null) return false; if (DateTime.Now - person.LoginSession.LastUpdatedDateTime > new TimeSpan (0, 0, 0, 0, loginLifetimeMs)) { context.LoginSessions.Remove (person.LoginSession); person.LoginSession = null; context.SaveChanges (); return false; } return true; }
public ActionResult CreateNewStatement(TrustLessModelLib.Statement statement) { using (DataContext context = new DataContext()) { if (!PersonController.ValidateLoginSession(context,statement.Person.LoginSession.Token)) return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden); var match = context.Statements.FirstOrDefault(x => x.MedicinOne == statement.MedicinOne && x.MedicinTwo == statement.MedicinTwo); //Does a statement already exists with the same two medicins. if (match != null) // && IsStatementValid(context,match) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); //Security: Don't allow user to specify the person who created the statement. Set it to the current user logged in. statement.Person = context.Persons.FirstOrDefault(x => x.Username == statement.Person.Username); //If the person does not exist, abort. if (statement.Person == null) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); //Rule: refuse a user with zero trust from creating statements. if (CalculateBayesianModelTrust(statement.Person) == 0) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); context.Statements.Add(statement); //Add recommendation from user var recommendation = new TrustLessModelLib.Recommendation(){ Person = statement.Person, Statement = statement, IsRecommended = true, Transaction = null, Description = statement.Description, CreationDate = DateTime.Now}; //This will fail if a racecondition was to add two recommendations (given that our key assignment of the table ensures only one of the same recommendation exist). context.Recommendations.Add (recommendation); context.SaveChanges (); BlockChain.MakeRecommendation (context, recommendation); return new HttpStatusCodeResult((int)HttpStatusCode.Created); } }
public ActionResult Login(Person person) { using (DataContext context = new DataContext()) { var match = context.Persons.FirstOrDefault(x => x.PublicKey == person.PublicKey &&x.Username == person.Username && x.Password == person.Password); if (match == null) { if (!CreateNewPerson (person)) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); match = context.Persons.FirstOrDefault(x => x.PublicKey == person.PublicKey &&x.Username == person.Username && x.Password == person.Password); } if (match.LoginSession != null) return Content ( JsonConvert.SerializeObject(RenewSession(context,match.LoginSession,match))); match.LoginSession = RenewSession(context,null,match); context.SaveChanges(); return Content ( JsonConvert.SerializeObject(match.LoginSession)); } }
/// <summary> /// Refreshes a LoginSession such that the login token won't expire. /// </summary> /// <param name="context">DataContext</param> /// <param name="session">LoginSession</param> public static void UpdateLoginSession(DataContext context,LoginSession session) { session.LastUpdatedDateTime = DateTime.Now; context.SaveChanges(); }
/// <summary> /// Creates a new user and returns a boolean (success). /// </summary> /// <param name="person">Person</param> /// <returns>Success boolean</returns> private bool CreateNewPerson(Person person) { using (DataContext context = new DataContext()) { var match = context.Persons.FirstOrDefault(x => x.PublicKey == person.PublicKey); if (match != null) return false; if (String.IsNullOrEmpty(person.PublicKey) || String.IsNullOrEmpty(person.Username) || String.IsNullOrEmpty(person.Password)) return false; person.LoginSession = null; context.Persons.Add(person); context.SaveChanges(); BlockChain.ImportPublicKeyToWallet (person); return true; } }
/// <summary> /// Reserves/locks away one S and F asset and sets the recommendation to reference these assets. /// </summary> /// <param name="db">DataContext</param> /// <param name="recommendation">Recommendation</param> public static void MakeRecommendation(DataContext db, TrustLessModelLib.Recommendation recommendation) { string chainName = WebConfigurationManager.AppSettings["ChainName"]; string nodeIp = WebConfigurationManager.AppSettings["NodeIp"]; MultiChainClient client = new MultiChainClient(chainName,nodeIp); Dictionary<string,int> dictionary = new Dictionary<string, int>(); AddressBalance[] addressBalances = client.GetTotalBalances ().Balances; var lastFasset = addressBalances.OrderBy (x => x.name).LastOrDefault (x => x.name.StartsWith ("F_")); var lastSasset = addressBalances.OrderBy (x => x.name).LastOrDefault (x => x.name.StartsWith ("S_")); if (lastFasset == null || lastSasset == null) { GenerateFunds (client); MakeRecommendation (db, recommendation); return; } string lastF = lastFasset.name; string lastS = lastSasset.name; dictionary.Add(lastF,1); dictionary.Add(lastS,1); try { var resp = client.PrepareLockUnspent(dictionary); recommendation.Transaction = new ReservedTransaction() { Tx = resp.txid, Vout = resp.vout }; } catch { //Insurficient funds GenerateFunds(client); MakeRecommendation (db, recommendation); return; } db.SaveChanges (); }
/// <summary> /// Gets the recommendations for a given statement. /// </summary> /// <param name="statement">int id of statement</param> /// <returns>Json list of recommendations</returns> public ActionResult GetRecommendations(int statement) { using (DataContext context = new DataContext()) { var recommendations = context.Recommendations.Include("Person").Where (x => x.StatementId == statement).ToList (); recommendations.ForEach(x => x.Person.Reputation = CalculateBayesianModelTrust(x.Person)); return Content ( JsonConvert.SerializeObject(recommendations)); } }
/// <summary> /// Rewards users that have made a correct recommendation with an S asset and punishes users /// who were wrong in their recommendation. /// </summary> /// <param name="context">DataContext</param> /// <param name="statement">Statement</param> private void IssueTrustForStatement(DataContext context,TrustLessModelLib.Statement statement) { var recommendations = context.Recommendations.Include("Person").Include("Transaction").Where(x => x.StatementId== statement.Id && x.Transaction != null).ToList(); int sAmount = recommendations.Count (x => x.IsRecommended) +1; int fAmount = recommendations.Count (x => !x.IsRecommended); foreach (Recommendation recommendation in recommendations) { if (sAmount >= fAmount) { if (recommendation.IsRecommended) { BlockChain.Issue (recommendation,true); } else { BlockChain.Issue (recommendation,false); } } else { if (recommendation.IsRecommended) { BlockChain.Issue (recommendation,false); } else { BlockChain.Issue (recommendation,true); } } } }
/// <summary> /// Returns a boolean clarifying that a statement is complete. /// </summary> /// <param name="context"></param> /// <param name="statement"></param> /// <returns></returns> private bool IsStatementRecommendationsComplete(DataContext context,TrustLessModelLib.Statement statement) { var recommendationAmount = context.Recommendations.Count(x => x.StatementId== statement.Id && x.Transaction != null); int maxVotings = Convert.ToInt32(WebConfigurationManager.AppSettings["MaxVotings"]); return recommendationAmount >= maxVotings; }
/// <summary> /// Searches for a completed statement (recommendations complete) that fits medicineOne taken with medicineTwo parameter. /// </summary> /// <param name="medicinOne">String name</param> /// <param name="medicinTwo">String name</param> /// <returns>Statement</returns> public ActionResult SearchStatement(string medicinOne, string medicinTwo) { using (DataContext context = new DataContext()) { int maxVotings = Convert.ToInt32(WebConfigurationManager.AppSettings["MaxVotings"]); return Content ( JsonConvert.SerializeObject( context.Statements.Include("Person").Where (x => x.MedicinOne == medicinOne && x.MedicinTwo == medicinTwo && context.Recommendations.Count (y => y.StatementId == x.Id) >= maxVotings && context.Recommendations.Count (y => y.StatementId == x.Id && y.IsRecommended) >= maxVotings / 2).ToList())); } }
public ActionResult Recommend(int statement, string token, bool trust) { var possibleStatements = GetStatements (token); if(possibleStatements.GetType() != typeof(ContentResult)) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); if (!JsonConvert.DeserializeObject<List<Statement>>(((ContentResult)possibleStatements).Content, new JsonSerializerSettings{ MissingMemberHandling = MissingMemberHandling.Ignore }).Any(x => x.Id == statement)) return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden); Stream req = Request.InputStream; req.Seek (0, System.IO.SeekOrigin.Begin); string description = new StreamReader(req).ReadToEnd(); using (DataContext context = new DataContext()) { if (!PersonController.ValidateLoginSession(context,token)) return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden); Person person = context.Persons.FirstOrDefault (x => x.LoginSessionToken != null && x.LoginSessionToken == token); var statementObject = context.Statements.FirstOrDefault(x => x.Id == statement); if (statementObject == null) return new HttpStatusCodeResult((int)HttpStatusCode.NotFound); var recommendation = context.Recommendations.FirstOrDefault(x => x.StatementId== statement && x.PersonUsername == person.Username); if (recommendation != null) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); if (IsStatementRecommendationsComplete (context, statementObject)) return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden); recommendation = new TrustLessModelLib.Recommendation(){ Person = person, Statement = statementObject, IsRecommended = trust, Transaction = null, Description = description, CreationDate = DateTime.Now}; lock (recommendationLock) { if (IsStatementRecommendationsComplete(context, statementObject)) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); //This will fail if a racecondition was to add two recommendations (given that our key assignment of the table ensures only one of the same recommendation exist). context.Recommendations.Add(recommendation); //Race condition is not possible after the next line of code, only one will succeed in adding the row below from the same user. context.SaveChanges(); } BlockChain.MakeRecommendation(context, recommendation); if (IsStatementRecommendationsComplete (context, statementObject)) IssueTrustForStatement (context, statementObject); return new HttpStatusCodeResult((int)HttpStatusCode.Created); } }
/// <summary> /// Gets a Json list of statements that the current user can recommend. /// </summary> /// <param name="token">String token</param> /// <returns>Json list of Statement</returns> public ActionResult GetStatements(string token) { using (DataContext context = new DataContext()) { if (!PersonController.ValidateLoginSession (context, token)) { return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden); } Person person = context.Persons.FirstOrDefault (x => x.LoginSessionToken != null && x.LoginSessionToken == token); int maxVotings = Convert.ToInt32(WebConfigurationManager.AppSettings["MaxVotings"]); double initialTrust = Convert.ToDouble(WebConfigurationManager.AppSettings["InitialTrust"]); int maxStatementsForVoting = Convert.ToInt32(WebConfigurationManager.AppSettings["MaxStatementsForVoting"]); var statements = context.Statements.Include ("Person").Where (x => x.Person.Username != person.Username && context.Recommendations.Count (y => y.StatementId == x.Id) < maxVotings && !context.Recommendations.Any (y => y.PersonUsername == person.Username && y.StatementId == x.Id)); if (CalculateBayesianModelTrust (person) <= initialTrust) { // List<Statement> finalStatement = new List<Statement> (); // foreach (Statement statement in statements) { // var people = // context.Persons.Where(x => // //Haven't voted on the statement // x.Username != person.Username && !context.Recommendations.Any (y => y.PersonUsername == person.Username && y.StatementId == statement.Id) // //Has made a statement that is correct. // && context.Statements.Any (y=> context.Recommendations.Count(z => z.StatementId == y.Id) == maxVotings && ((y.Person.Username == x.Username && context.Recommendations.Count(z => z.StatementId == y.Id && z.IsRecommended) >= maxVotings / 2) || // //Contains a recommendation that is correct with the outcome // (context.Recommendations.Any (z => z.PersonUsername == person.Username && z.StatementId == y.Id // && context.Recommendations.Count(a => a.StatementId == z.StatementId && z.IsRecommended == a.IsRecommended) >= maxVotings / 2))))).ToList(); // // people.RemoveAll (x => CalculateBayesianModelTrust (x) <= initialTrust); // if (!people.Any ()) // finalStatement.Add (statement); // } // return Content ( JsonConvert.SerializeObject(finalStatement)); var dt = DateTime.Now ; dt.AddDays (-8); if (context.Recommendations.Any(x => x.CreationDate > dt && x.PersonUsername == person.Username)) return Content ("[]"); string newId = Guid.NewGuid ().ToString(); return Content ( JsonConvert.SerializeObject( statements.OrderBy(r => newId).Take(maxStatementsForVoting).ToList ())); } return Content ( JsonConvert.SerializeObject( statements.ToList ())); } }