예제 #1
0
 public IEnumerable <IAuction> GetAuctions(bool onlyNotEnded)
 {
     if (Utils.IsSiteDisposed(this))
     {
         throw new InvalidOperationException("Invalid operation: this site is disposed.");
     }
     using (var context = new AuctionSiteContext(ConnectionString))
     {
         List <Auction> auctions;
         if (!onlyNotEnded)
         {
             auctions = (
                 from auction in context.Auctions
                 where auction.SiteName == Name
                 select auction
                 ).ToList();
         }
         else
         {
             auctions = (
                 from auction in context.Auctions
                 where auction.SiteName == Name && auction.EndsOn > AlarmClock.Now
                 select auction
                 ).ToList();
         }
         return(Utils.AuctionsToAuctionsBLL(auctions, this));
     }
 }
예제 #2
0
        public int GetTheTimezoneOf(string connectionString, string name)
        {
            if (null == connectionString)
            {
                throw new ArgumentNullException($"{nameof(connectionString)} cannot be null.");
            }
            if (null == name)
            {
                throw new ArgumentNullException($"{nameof(name)} cannot be null.");
            }
            if (!IsValidSiteName(name))
            {
                throw new ArgumentException($"{nameof(name)} is not a valid site name.");
            }
            using (var context = new AuctionSiteContext(connectionString))
            {
                if (!ExistsDb(context))
                {
                    throw new UnavailableDbException("Database connection error");
                }
                var site =
                    (from siteDb in context.Sites
                     where siteDb.Name == name
                     select siteDb).FirstOrDefault();

                if (null == site)
                {
                    throw new InexistentNameException($"{nameof(name)}: {name} inexistent.");
                }

                return(site.Timezone);
            }
        }
예제 #3
0
 private SessionBLL GetUserSession(UserBLL user)
 {
     using (var context = new AuctionSiteContext(ConnectionString))
     {
         var session = context.Sessions.Find(Utils.CreateSessionId(this, user));
         if (null == session)
         {
             user.Session = Utils.CreateNewSession(this, user);
             return(user.Session);
         }
         var sessionBLL = new SessionBLL(session, user);
         if (!sessionBLL.IsValid())
         {
             sessionBLL.Logout();
             user.Session = Utils.CreateNewSession(this, user);
         }
         else
         {
             var validUntil = AlarmClock.Now.AddSeconds(SessionExpirationInSeconds);
             session.ValidUntil           = validUntil;
             user.Session.ValidUntil      = validUntil;
             context.Entry(session).State = EntityState.Modified;
             context.SaveChanges();
         }
         return(user.Session);
     }
 }
예제 #4
0
 public void CleanupSessions()
 {
     if (Utils.IsSiteDisposed(this))
     {
         throw new InvalidOperationException("Invalid operation: this site is disposed.");
     }
     using (var context = new AuctionSiteContext(ConnectionString))
     {
         foreach (var iUser in GetUsers())
         {
             var user = iUser as UserBLL;
             if (user?.Session != null)
             {
                 if (!user.Session.IsValid())
                 {
                     var dbUser = context.Users.Find(user.UserID);
                     if (null == dbUser)
                     {
                         throw new InvalidOperationException("Invalid operation: user not found.");
                     }
                     dbUser.Session              = null;
                     dbUser.SessionId            = null;
                     context.Entry(dbUser).State = EntityState.Modified;
                     context.Entry(context.Sessions.Find(user.Session.Id)).State = EntityState.Deleted;
                 }
             }
         }
         context.SaveChanges();
     }
 }
예제 #5
0
        public ISession Login(string username, string password)
        {
            if (Utils.IsSiteDisposed(this))
            {
                throw new InvalidOperationException("Invalid operation: this site is disposed.");
            }
            if (null == username)
            {
                throw new ArgumentNullException($"{nameof(username)} cannot be null");
            }
            if (null == password)
            {
                throw new ArgumentNullException($"{nameof(password)} cannot be null");
            }
            if (!Utils.IsValidUsername(username))
            {
                throw new ArgumentException($"{nameof(username)} is not valid.");
            }
            if (!Utils.IsValidPassword(password))
            {
                throw new ArgumentException($"{nameof(password)} is not valid.");
            }

            var user = GetUserByUsername(username);

            if (null == user)
            {
                return(null);
            }

            if (!Utils.ArePasswordsEquals(user.Password, password, Convert.FromBase64String(user.Salt)))
            {
                return(null);
            }

            var userSession = GetUserSession(user);

            //user.Session = userSession;
            using (var context = new AuctionSiteContext(ConnectionString))
            {
                var dbUser = context.Users.Find(user.UserID);
                if (null == dbUser)
                {
                    throw new InvalidOperationException("Invalid operation: user not found.");
                }
                dbUser.SessionId            = userSession.Id;
                context.Entry(dbUser).State = EntityState.Modified;
                context.SaveChanges();
            }

            return(userSession);
        }
예제 #6
0
 private static void UpdateAuction(AuctionSiteContext context, Auction auction, ISession session, double offer, double?currentPrice)
 {
     auction.LastBid = offer;
     if (null != session)
     {
         auction.CurrentWinnerId = ((UserBLL)session.User).UserID;
     }
     if (null != currentPrice)
     {
         auction.CurrentPrice = (double)currentPrice;
     }
     context.Entry(auction).State = EntityState.Modified;
     context.SaveChanges();
 }
예제 #7
0
        public IEnumerable <IUser> GetUsers()
        {
            if (Utils.IsSiteDisposed(this))
            {
                throw new InvalidOperationException("Invalid operation: this site is disposed.");
            }
            using (var context = new AuctionSiteContext(ConnectionString))
            {
                var users =
                    (from user in context.Users.Include("Session")
                     where user.SiteName == Name
                     select user).ToList();

                return(Utils.UsersToUsersBLL(users, this));
            }
        }
예제 #8
0
 public void Delete()
 {
     if (Utils.IsSiteDisposed(this))
     {
         throw new InvalidOperationException("Invalid operation: this site is disposed.");
     }
     DeleteUsers();
     DeleteAuctions();
     using (var context = new AuctionSiteContext(ConnectionString))
     {
         var site = context.Sites.Find(this.Name);
         context.Entry(site).State = EntityState.Deleted;
         context.SaveChanges();
     }
     IsDeleted = true;
 }
예제 #9
0
        public void Delete()
        {
            if (Utils.IsAuctionDisposed(this))
            {
                throw new InvalidOperationException("Invalid operation: user is disposed.");
            }
            var sellerBLL = (UserBLL)Seller;

            using (var context = new AuctionSiteContext(sellerBLL.Site.ConnectionString))
            {
                var auction = context.Auctions.Find(Id);
                context.Entry(auction).State = EntityState.Deleted;
                context.SaveChanges();
            }
            IsDeleted = true;
        }
예제 #10
0
        public void UpdateDeletedUser()
        {
            var sellerBLL = (UserBLL)Seller;

            using (var context = new AuctionSiteContext(sellerBLL.Site.ConnectionString))
            {
                var auction = context.Auctions.Find(Id);
                if (null == auction)
                {
                    throw new InvalidOperationException("Invalid operation: auction not found.");
                }
                auction.CurrentWinner        = null;
                auction.CurrentWinnerId      = null;
                context.Entry(auction).State = EntityState.Modified;
                context.SaveChanges();
            }
        }
예제 #11
0
 public IEnumerable <string> GetSiteNames(string connectionString)
 {
     if (null == connectionString)
     {
         throw new ArgumentNullException($"{nameof(connectionString)} cannot be null.");
     }
     using (var context = new AuctionSiteContext(connectionString))
     {
         if (!ExistsDb(context))
         {
             throw new UnavailableDbException("Database connection error.");
         }
         return((
                    from site in context.Sites
                    select site.Name).ToList());
     }
 }
예제 #12
0
        /* AUX METHODS */

        private void AddUser(string username, string password, byte[] salt)
        {
            User user;

            using (var context = new AuctionSiteContext(ConnectionString))
            {
                user = new User()
                {
                    Username = username,
                    Password = Convert.ToBase64String(Utils.HashPassword(password, salt)),
                    Salt     = Convert.ToBase64String(salt),
                    SiteName = Name
                };
                context.Users.Add(user);
                context.SaveChanges();
            }
        }
예제 #13
0
        public double CurrentPrice()
        {
            if (Utils.IsAuctionDisposed(this))
            {
                throw new InvalidOperationException("Invalid operation: user is disposed.");
            }
            var sellerBLL = (UserBLL)Seller;

            using (var context = new AuctionSiteContext(sellerBLL.Site.ConnectionString))
            {
                var auction = context.Auctions.Find(Id);
                if (null == auction)
                {
                    throw new InvalidOperationException("Invalid operation: auction not found.");
                }
                return(auction.CurrentPrice);
            }
        }
예제 #14
0
 public void Setup(string connectionString)
 {
     if (null == connectionString)
     {
         throw new ArgumentNullException($"{nameof(connectionString)} cannot be null.");
     }
     using (var context = new AuctionSiteContext(connectionString))
     {
         try
         {
             context.Database.Delete();
             context.Database.Create();
         }
         catch (Exception e)
         {
             throw new UnavailableDbException("Database connection error.", e);
         }
     }
 }
예제 #15
0
        public ISite LoadSite(string connectionString, string name, IAlarmClock alarmClock)
        {
            if (null == connectionString)
            {
                throw new ArgumentNullException($"{nameof(connectionString)} cannot be null.");
            }
            if (null == name)
            {
                throw new ArgumentNullException($"{nameof(name)} cannot be null.");
            }
            if (null == alarmClock)
            {
                throw new ArgumentNullException($"{nameof(alarmClock)} cannot be null.");
            }
            if (!IsValidSiteName(name))
            {
                throw new ArgumentException($"{nameof(name)} is not a valid site name.");
            }
            using (var context = new AuctionSiteContext(connectionString))
            {
                if (!ExistsDb(context))
                {
                    throw new UnavailableDbException("Database connection error");
                }
                var site =
                    (from siteDb in context.Sites
                     where siteDb.Name == name
                     select siteDb).FirstOrDefault();

                if (null == site)
                {
                    throw new InexistentNameException($"{nameof(name)}: {name} inexistent.");
                }
                if (site.Timezone != alarmClock.Timezone)
                {
                    throw new ArgumentException($"Timezone of {nameof(alarmClock)} is not valid.");
                }
                return(new SiteBLL(site, alarmClock, connectionString));
            }
        }
예제 #16
0
        public bool IsValid()
        {
            if (IsLoggedOut())
            {
                return(false);
            }

            var      userBLL = User as UserBLL;
            DateTime validUntil;

            using (var context = new AuctionSiteContext(userBLL.Site.ConnectionString))
            {
                var session = context.Sessions.Find(Id);
                if (null == session)
                {
                    return(false);
                }
                validUntil = session.ValidUntil;
            }

            return(AlarmClock.Now <= validUntil);
        }
예제 #17
0
        public void Delete()
        {
            if (Utils.IsUserDisposed(this))
            {
                throw new InvalidOperationException("User disposed.");
            }
            foreach (var auction in Site.GetAuctions(true))
            {
                if (Equals(auction.CurrentWinner()))
                {
                    throw new InvalidOperationException("User cannot be deleted because is a current winner in an auction.");
                }
                if (Equals(auction.Seller))
                {
                    throw new InvalidOperationException("User cannot be deleted because is a seller.");
                }
            }
            foreach (var auction in Site.GetEndedAuctions())
            {
                var auctionBLL = (AuctionBLL)auction;
                if (Equals(auctionBLL.CurrentWinner()))
                {
                    auctionBLL.UpdateDeletedUser();
                }
                else if (Equals(auctionBLL.Seller))
                {
                    auctionBLL.Delete();
                }
            }
            Session?.Logout();
            using (var context = new AuctionSiteContext(Site.ConnectionString))
            {
                var user = context.Users.Find(UserID);
                context.Entry(user).State = EntityState.Deleted;
                context.SaveChanges();
            }

            IsDeleted = true;
        }
예제 #18
0
        public void Logout()
        {
            if (IsLoggedOut())
            {
                throw new InvalidOperationException("User already logged out.");
            }

            var userBLL = User as UserBLL;

            using (var context = new AuctionSiteContext(userBLL.Site.ConnectionString))
            {
                var session = context.Sessions.Find(Id);
                if (null == session)
                {
                    throw new InvalidOperationException("invalid operation: session not found.");
                }
                context.Users.Where(u => u.UserID == userBLL.UserID).Load();
                context.Sessions.Remove(session);
                context.SaveChanges();
            }

            LoggedOut = true;
        }
예제 #19
0
        public IUser CurrentWinner()
        {
            if (Utils.IsAuctionDisposed(this))
            {
                throw new InvalidOperationException("Invalid operation: user is disposed.");
            }
            var userBLL = (UserBLL)Seller;

            using (var context = new AuctionSiteContext(userBLL.Site.ConnectionString))
            {
                var auction = context.Auctions.Find(Id);
                if (null == auction)
                {
                    throw new InvalidOperationException("Invalid operation: auction not found.");
                }
                var currentWinner = auction.CurrentWinner;
                if (null == currentWinner)
                {
                    return(null);
                }
                return(Utils.UserToUserBLL(currentWinner, userBLL.Site));
            }
        }
예제 #20
0
        public IAuction CreateAuction(string description, DateTime endsOn, double startingPrice)
        {
            if (!IsValid())
            {
                throw new InvalidOperationException("Session not valid.");
            }
            if (Utils.IsSessionDisposed(this))
            {
                throw new InvalidOperationException("Session disposed.");
            }
            if (null == description)
            {
                throw new ArgumentNullException($"{nameof(description)} cannot be null.");
            }
            if (string.Empty == description)
            {
                throw new ArgumentException($"{nameof(description)} cannot be an empty string.");
            }
            if (IsStartingPriceNegative())
            {
                throw new ArgumentOutOfRangeException($"{nameof(startingPrice)} cannot be a negative number.");
            }
            if (endsOn < AlarmClock.Now)
            {
                throw new UnavailableTimeMachineException($"{endsOn} cannot be in the past.");
            }
            var     userBLL = User as UserBLL;
            Auction auction;
            var     validUntil = AlarmClock.Now.AddSeconds(userBLL.Site.SessionExpirationInSeconds);

            using (var context = new AuctionSiteContext(userBLL.Site.ConnectionString))
            {
                auction = new Auction()
                {
                    Description     = description,
                    EndsOn          = endsOn,
                    SiteName        = userBLL.Site.Name,
                    SellerId        = userBLL.UserID,
                    CurrentWinnerId = null,
                    LastBid         = null,
                    StartingPrice   = startingPrice,
                    CurrentPrice    = startingPrice
                };
                context.Auctions.Add(auction);

                var session = context.Sessions.Find(Id);
                if (null == session)
                {
                    throw new InvalidOperationException("Invalid operation: session not found.");
                }
                session.ValidUntil           = validUntil;
                context.Entry(session).State = EntityState.Modified;
                context.SaveChanges();
            }
            ValidUntil = validUntil;
            return(new AuctionBLL(auction, User));

            bool IsStartingPriceNegative()
            {
                return(startingPrice < 0);
            }
        }
예제 #21
0
 /* AUX METHODS*/
 private static bool ExistsDb(AuctionSiteContext context)
 {
     return(context.Database.Exists());
 }
예제 #22
0
        public void CreateSiteOnDb(string connectionString, string name, int timezone, int sessionExpirationTimeInSeconds,
                                   double minimumBidIncrement)
        {
            if (null == connectionString)
            {
                throw new ArgumentNullException($"{nameof(connectionString)} cannot be null.");
            }

            if (null == name)
            {
                throw new ArgumentNullException($"{nameof(name)} cannot be null.");
            }

            if (!IsValidSiteName(name))
            {
                throw new ArgumentException($"{nameof(name)} is not a valid site name.");
            }

            if (!IsValidTimezone())
            {
                throw new ArgumentOutOfRangeException($"{nameof(timezone)} is not a valid timezone.");
            }

            if (!IsPositiveSessionExpiration())
            {
                throw new ArgumentOutOfRangeException($"{nameof(sessionExpirationTimeInSeconds)} must be a positive number.");
            }

            if (!IsPositiveMinimumBidIncrement())
            {
                throw new ArgumentOutOfRangeException($"{nameof(minimumBidIncrement)} must be a positive number.");
            }

            using (var context = new AuctionSiteContext(connectionString))
            {
                if (!ExistsDb(context))
                {
                    throw new UnavailableDbException("Database connection error.");
                }
                if (Utils.SiteNameAlreadyExists(context, name))
                {
                    throw new NameAlreadyInUseException($"{nameof(name)}: {name} already in use.");
                }

                var site = new Site()
                {
                    Name     = name,
                    Timezone = timezone,
                    SessionExpirationInSeconds = sessionExpirationTimeInSeconds,
                    MinimumBidIncrement        = minimumBidIncrement
                };
                context.Sites.Add(site);
                context.SaveChanges();
            }

            bool IsPositiveMinimumBidIncrement()
            {
                return(minimumBidIncrement > 0);
            }

            bool IsPositiveSessionExpiration()
            {
                return(sessionExpirationTimeInSeconds > 0);
            }

            bool IsValidTimezone()
            {
                return(timezone >= DomainConstraints.MinTimeZone && timezone <= DomainConstraints.MaxTimeZone);
            }
        }
예제 #23
0
        public bool BidOnAuction(ISession session, double offer)
        {
            if (Utils.IsAuctionDisposed(this))
            {
                throw new InvalidOperationException("Invalid operation: user is disposed.");
            }
            if (null == session)
            {
                throw new ArgumentNullException($"{nameof(session)} cannot be null.");
            }
            if (offer < 0)
            {
                throw new ArgumentOutOfRangeException($"{nameof(offer)} cannot be a negative number.");
            }
            if (!session.IsValid())
            {
                throw new ArgumentException($"{nameof(session)} not valid.");
            }
            if (Seller.Equals(session.User))
            {
                throw new ArgumentException("Bidder and seller cannot be the same user.");
            }
            if (!((UserBLL)Seller).Site.Equals(((UserBLL)session.User).Site))
            {
                throw new ArgumentException($"Seller site must be the same of bidder site.");
            }

            var sellerBLL = (UserBLL)Seller;

            using (var context = new AuctionSiteContext(sellerBLL.Site.ConnectionString))
            {
                var auction = context.Auctions.Find(Id);
                if (null == auction)
                {
                    throw new InvalidOperationException("Invalid operation: auction not found.");
                }
                var lastBid             = auction.LastBid;
                var currentWinnerId     = auction.CurrentWinnerId;
                var minimumBidIncrement = sellerBLL.Site.MinimumBidIncrement;
                var startingPrice       = auction.StartingPrice;
                if (offer < startingPrice)
                {
                    return(false);
                }
                var isFirstBid           = null == lastBid && null == currentWinnerId;
                var bidderAlreadyWinning = currentWinnerId == ((UserBLL)session.User).UserID;
                if (bidderAlreadyWinning)
                {
                    if (lastBid + minimumBidIncrement >= offer)
                    {
                        return(false);
                    }
                }
                if (offer < CurrentPrice())
                {
                    return(false);
                }
                if (!isFirstBid && offer < CurrentPrice() + minimumBidIncrement)
                {
                    return(false);
                }
                var sessionDb = context.Sessions.Find(session.Id);
                if (null == sessionDb)
                {
                    throw new InvalidOperationException("Invalid operation: session not found");
                }
                sessionDb.ValidUntil             = sellerBLL.Site.AlarmClock.Now.AddSeconds(sellerBLL.Site.SessionExpirationInSeconds);
                context.Entry(sessionDb).State   = EntityState.Modified;
                ((SessionBLL)session).ValidUntil = sellerBLL.Site.AlarmClock.Now.AddSeconds(sellerBLL.Site.SessionExpirationInSeconds);
                if (isFirstBid)
                {
                    UpdateAuction(context, auction, session, offer, null);
                    return(true);
                }
                if (bidderAlreadyWinning)
                {
                    UpdateAuction(context, auction, null, offer, null);
                    return(true);
                }
                if (offer > lastBid)
                {
                    UpdateAuction(context, auction, session, offer, Math.Min(offer, (double)lastBid + minimumBidIncrement));
                    return(true);
                }

                UpdateAuction(context, auction, null, offer, Math.Min(offer + minimumBidIncrement, (double)lastBid));

                return(true);
            }
        }