/// <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;
            }
        }
Пример #8
0
        /// <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 ()));

            }
        }