示例#1
0
        public async Task RecoverUserGivenMalformedTokenReturnsFalse()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(RecoverUserGivenMalformedTokenReturnsFalse));

            var databaseSettings = new DatabaseSettings
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                EnvironmentType = EnvironmentType.Test
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 5, TimeOutPeriodInMinutes = 5
            };

            var  expectedResult = false;
            bool result;

            // Act
            await using (var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings))
            {
                var accountService = new AccountService(context, environmentSettings, new Mock <ITokenService>().Object,
                                                        new Mock <IEmailService>().Object, new Mock <IHashService>().Object,
                                                        new Mock <IHttpContextAccessor>().Object, new Mock <ILoginLimiter>().Object, loginLimiterSettings);
                result = await accountService.RecoverUserAsync("bogus", "3433");
            }

            // Assert
            Assert.Equal(expectedResult, result);
        }
示例#2
0
        public TokenServiceTest()
        {
            _identity = new IdentitySettings();

            //creates the key for signing the token
            var keyForHmacSha256 = new byte[64];
            var randomGen        = RandomNumberGenerator.Create();

            randomGen.GetBytes(keyForHmacSha256);
            _identity.TokenKey = new SymmetricSecurityKey(keyForHmacSha256).ToString();

            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(TokenServiceTest));

            var databaseSettings = new DatabaseSettings
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                EnvironmentType = EnvironmentType.Test
            };

            _context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
        }
示例#3
0
 public PurchaseService(CoffeeCardContext context, IMobilePayPaymentsService mobilePayPaymentsService, ITicketService ticketService, IEmailService emailService)
 {
     _context = context;
     _mobilePayPaymentsService = mobilePayPaymentsService;
     _ticketService = ticketService;
     _emailService = emailService;
 }
示例#4
0
 public PurchaseService(CoffeeCardContext context, IMobilePayService mobilePayService,
                        MobilePaySettings mobilePaySettings, IEmailService emailService, IMapperService mapper)
 {
     _context           = context;
     _mobilePayService  = mobilePayService;
     _mobilePaySettings = mobilePaySettings;
     _emailService      = emailService;
     _mapper            = mapper;
 }
示例#5
0
        public async Task RecoverUserGivenValidTokenReturnsTrue()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(RecoverUserGivenValidTokenReturnsTrue));

            var databaseSettings = new DatabaseSettings
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                EnvironmentType = EnvironmentType.Test
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 5, TimeOutPeriodInMinutes = 5
            };

            var  expectedResult = true;
            bool result;

            var claim  = new Claim(ClaimTypes.Email, "*****@*****.**");
            var claims = new List <Claim> {
                claim
            };
            var validToken = new JwtSecurityToken("analog", "all", claims);

            var tokenService = new Mock <ITokenService>();

            tokenService.Setup(t => t.ReadToken("valid")).Returns(validToken);
            tokenService.Setup(t => t.ValidateToken("valid")).ReturnsAsync(true);

            // Act
            await using (var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings))
            {
                var token      = new Token("valid");
                var userTokens = new List <Token> {
                    token
                };

                var user = new User {
                    Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme()
                };
                context.Add(user);
                context.SaveChanges();

                var accountService = new AccountService(context, environmentSettings, tokenService.Object,
                                                        new Mock <IEmailService>().Object, new Mock <IHashService>().Object,
                                                        new Mock <IHttpContextAccessor>().Object, new Mock <ILoginLimiter>().Object, loginLimiterSettings);

                result = await accountService.RecoverUserAsync("valid", "3433");
            }

            // Assert
            Assert.Equal(expectedResult, result);
        }
示例#6
0
        public async Task LoginThrowsExceptionWhenLimitIsReached()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(LoginThrowsExceptionWhenLimitIsReached));

            var databaseSettings = new DatabaseSettings()
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                DeploymentUrl = "test", EnvironmentType = EnvironmentType.Test, MinAppVersion = "2.1.0"
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 1, TimeOutPeriodInMinutes = 1
            };

            var userTokens = new List <Token>();
            var user       = new User
            {
                Id       = 1, Name = "test", Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme(),
                Password = "******", IsVerified = true
            };

            var wrongPass = "******";

            var httpContextAccessor = new Mock <IHttpContextAccessor>();

            httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext);

            // Act
            await using (var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings))
            {
                context.Add(user);
                context.SaveChanges();

                var accountService = new AccountService(context, environmentSettings, new Mock <ITokenService>().Object,
                                                        new Mock <IEmailService>().Object, new HashService(), httpContextAccessor.Object,
                                                        new LoginLimiter(loginLimiterSettings), loginLimiterSettings);

                //Attempts to login with the wrong credentials
                Assert.Throws <ApiException>(() => accountService.Login(user.Email, wrongPass, "2.1.0"));

                //Attempts to login a sixth time with the same credentials and captures the exception
                var tooManyLoginsException =
                    (ApiException)Record.Exception(() => accountService.Login(user.Email, wrongPass, "2.1.0"));
                // Assert
                var expectedException =
                    new ApiException(
                        $"Amount of failed login attempts exceeds the allowed amount, please wait for {loginLimiterSettings.TimeOutPeriodInMinutes} minutes before trying again",
                        429);
                Assert.Equal(tooManyLoginsException.StatusCode, expectedException.StatusCode);
                Assert.Equal(tooManyLoginsException.Message, expectedException.Message);
            }
        }
示例#7
0
        public async Task LoginLimiterNotCalledWhenDisabled()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(LoginLimiterNotCalledWhenDisabled));

            var databaseSettings = new DatabaseSettings()
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                DeploymentUrl = "test", EnvironmentType = EnvironmentType.Test, MinAppVersion = "2.1.0"
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = false, MaximumLoginAttemptsWithinTimeOut = 5, TimeOutPeriodInMinutes = 5
            };

            var userTokens = new List <Token>();
            var user       = new User
            {
                Id       = 1, Name = "test", Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme(),
                Password = "******", IsVerified = true
            };

            var wrongPass = "******";

            var httpContextAccessor = new Mock <IHttpContextAccessor>();

            httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext);

            var loginLimiter = new Mock <ILoginLimiter>();

            loginLimiter.Setup(l => l.LoginAllowed(user)).Returns(true);

            // Act
            await using (var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings))
            {
                context.Add(user);
                context.SaveChanges();

                var accountService = new AccountService(context, environmentSettings, new Mock <ITokenService>().Object,
                                                        new Mock <IEmailService>().Object, new HashService(), httpContextAccessor.Object,
                                                        loginLimiter.Object, loginLimiterSettings);

                //Attempts to login
                Assert.Throws <ApiException>(() => accountService.Login(user.Email, wrongPass, "2.1.0"));

                // Assert
                loginLimiter.Verify(l => l.LoginAllowed(user), Times.Never);
            }
        }
示例#8
0
        public async Task LoginGivenValidCredentialsReturnsToken()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(LoginGivenValidCredentialsReturnsToken));

            var databaseSettings = new DatabaseSettings()
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                DeploymentUrl = "test", EnvironmentType = EnvironmentType.Test, MinAppVersion = "2.1.0"
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 5, TimeOutPeriodInMinutes = 5
            };

            var userTokens = new List <Token>();
            var user       = new User
            {
                Id       = 1, Name = "test", Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme(),
                Password = "******", IsVerified = true
            };

            var hasher = new Mock <IHashService>();

            hasher.Setup(h => h.Hash(user.Password)).Returns(user.Password);

            var    expectedToken = "valid";
            string actualToken;

            var tokenService = new Mock <ITokenService>();

            tokenService.Setup(t => t.GenerateToken(It.IsAny <IEnumerable <Claim> >())).Returns(expectedToken);

            // Act
            await using (var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings))
            {
                context.Add(user);
                context.SaveChanges();

                var accountService = new AccountService(context, environmentSettings, tokenService.Object,
                                                        new Mock <IEmailService>().Object, hasher.Object,
                                                        new Mock <IHttpContextAccessor>().Object, new LoginLimiter(loginLimiterSettings), loginLimiterSettings);

                actualToken = accountService.Login(user.Email, user.Password, "2.1.0");
            }

            // Assert
            Assert.Equal(expectedToken, actualToken);
        }
示例#9
0
 public AccountService(CoffeeCardContext context, EnvironmentSettings environmentSettings, ITokenService tokenService,
                       IEmailService emailService, IHashService hashService, IHttpContextAccessor httpContextAccessor, ILoginLimiter loginLimiter, LoginLimiterSettings loginLimiterSettings)
 {
     _context              = context;
     _environmentSettings  = environmentSettings;
     _tokenService         = tokenService;
     _emailService         = emailService;
     _hashService          = hashService;
     _httpContextAccessor  = httpContextAccessor;
     _loginLimiter         = loginLimiter;
     _loginLimiterSettings = loginLimiterSettings;
 }
示例#10
0
        public async Task LoginFailsIfEmailIsNotVerified()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(LoginFailsIfEmailIsNotVerified));

            var databaseSettings = new DatabaseSettings()
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                DeploymentUrl = "test", EnvironmentType = EnvironmentType.Test, MinAppVersion = "2.1.0"
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 1, TimeOutPeriodInMinutes = 1
            };

            var userTokens = new List <Token>();
            var user       = new User
            {
                Id       = 1, Name = "test", Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme(),
                Password = "******", IsVerified = false
            };
            var somePass = "******";

            var httpContextAccessor = new Mock <IHttpContextAccessor>();

            httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext);

            await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
            context.Add(user);
            await context.SaveChangesAsync();

            // Act
            var accountService = new AccountService(context, environmentSettings, new Mock <ITokenService>().Object,
                                                    new Mock <IEmailService>().Object, new HashService(), httpContextAccessor.Object,
                                                    new LoginLimiter(loginLimiterSettings), loginLimiterSettings);

            // Login
            var exception = (ApiException)Record.Exception(() => accountService.Login(user.Email, somePass, "2.1.0"));

            // Assert
            var expectedException = new ApiException("E-mail has not been verified", 403);

            Assert.Equal(exception.StatusCode, expectedException.StatusCode);
            Assert.Equal(exception.Message, expectedException.Message);
        }
示例#11
0
        public async Task LoginSucceedsIfEmailIsVerified()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(LoginSucceedsIfEmailIsVerified));

            var databaseSettings = new DatabaseSettings()
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                DeploymentUrl = "test", EnvironmentType = EnvironmentType.Test, MinAppVersion = "2.1.0"
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 1, TimeOutPeriodInMinutes = 1
            };

            var userTokens = new List <Token>();
            var somePass   = "******";
            var user       = new User
            {
                Id       = 1, Name = "test", Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme(),
                Password = somePass, IsVerified = true
            };
            var httpContextAccessor = new Mock <IHttpContextAccessor>();

            httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext);

            var hashService = new Mock <IHashService>();

            hashService.Setup(m => m.Hash(It.IsAny <string>())).Returns(somePass);

            await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
            context.Add(user);
            await context.SaveChangesAsync();

            // Act
            var accountService = new AccountService(context, environmentSettings, new Mock <ITokenService>().Object,
                                                    new Mock <IEmailService>().Object, hashService.Object, httpContextAccessor.Object,
                                                    new LoginLimiter(loginLimiterSettings), loginLimiterSettings);

            // Login
            var result = accountService.Login(user.Email, somePass, "2.1.0");

            // Assert we did not fail in the above call. This test does not test the result
            Assert.Null(result);
        }
示例#12
0
        public async Task LoginWithUnknownUserThrowsApiException()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(LoginWithUnknownUserThrowsApiException));

            var databaseSettings = new DatabaseSettings()
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                DeploymentUrl = "test", EnvironmentType = EnvironmentType.Test, MinAppVersion = "2.1.0"
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 1, TimeOutPeriodInMinutes = 1
            };


            var httpContextAccessor = new Mock <IHttpContextAccessor>();

            httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext);

            await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
            await context.SaveChangesAsync();

            // Act
            var accountService = new AccountService(context, environmentSettings, new Mock <ITokenService>().Object,
                                                    new Mock <IEmailService>().Object, new Mock <IHashService>().Object, httpContextAccessor.Object,
                                                    new LoginLimiter(loginLimiterSettings), loginLimiterSettings);

            // Login
            var exception = (ApiException)Record.Exception(() => accountService.Login("unknown email", "somePass", "2.1.0"));

            // Assert
            var expectedException = new ApiException("The username or password does not match", 401);

            Assert.Equal(exception.StatusCode, expectedException.StatusCode);
            Assert.Equal(exception.Message, expectedException.Message);
        }
示例#13
0
 public LeaderboardService(CoffeeCardContext context)
 {
     _context = context;
 }
示例#14
0
 public TicketService(CoffeeCardContext context, IAccountService accountService, IProductService productService)
 {
     _context        = context;
     _accountService = accountService;
     _productService = productService;
 }
示例#15
0
 public TicketService(CoffeeCardContext context)
 {
     _context = context;
 }
示例#16
0
 public ProductService(CoffeeCardContext context)
 {
     _context = context;
 }
示例#17
0
 public WebhookService(CoffeeCardContext context, IMobilePayWebhooksService mobilePayWebhooksService, MobilePaySettingsV2 mobilePaySettings)
 {
     _context = context;
     _mobilePayWebhooksService = mobilePayWebhooksService;
     _mobilePaySettings        = mobilePaySettings;
 }
示例#18
0
 public ClaimsUtilities(CoffeeCardContext context)
 {
     _context = context;
 }
示例#19
0
 public ProgrammeService(CoffeeCardContext context)
 {
     _context = context;
 }
示例#20
0
        public async Task GetProductsForUserAsync_Return_Products_For_UserGroup()
        {
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(GetProductsForUserAsync_Return_Products_For_UserGroup));

            var databaseSettings = new DatabaseSettings
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                EnvironmentType = EnvironmentType.Test
            };

            await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings);
            var p1 = new Product
            {
                Id              = 1,
                Name            = "Coffee",
                Description     = "Coffee Clip card",
                NumberOfTickets = 10,
                Price           = 10,
                ExperienceWorth = 10,
                Visible         = true
            };
            await context.AddAsync(p1);

            var p2 = new Product
            {
                Id              = 2,
                Name            = "Espresso",
                Description     = "Espresso Clip card",
                NumberOfTickets = 10,
                Price           = 20,
                ExperienceWorth = 20,
                Visible         = true
            };
            await context.AddAsync(p2);

            var p3 = new Product
            {
                Id              = 3,
                Name            = "Barista Coffee",
                Description     = "Barista Coffee Clip card",
                NumberOfTickets = 10,
                Price           = 30,
                ExperienceWorth = 10,
                Visible         = true
            };
            await context.AddAsync(p3);

            await context.SaveChangesAsync();

            await context.AddAsync(new ProductUserGroup
            {
                Product   = p1,
                UserGroup = UserGroup.Barista
            });

            await context.AddAsync(new ProductUserGroup
            {
                Product   = p2,
                UserGroup = UserGroup.Barista
            });

            await context.AddAsync(new ProductUserGroup
            {
                Product   = p3,
                UserGroup = UserGroup.Barista
            });

            await context.SaveChangesAsync();

            using (var productService = new ProductService(context))
            {
                var expected = new List <Product>
                {
                    new Product
                    {
                        Id              = 1,
                        Name            = "Coffee",
                        Description     = "Coffee Clip card",
                        NumberOfTickets = 10,
                        Price           = 10,
                        ExperienceWorth = 10,
                        Visible         = true
                    },
                    new Product
                    {
                        Id              = 2,
                        Name            = "Espresso",
                        Description     = "Espresso Clip card",
                        NumberOfTickets = 10,
                        Price           = 20,
                        ExperienceWorth = 20,
                        Visible         = true
                    },
                    new Product
                    {
                        Id              = 3,
                        Name            = "Barista Coffee",
                        Description     = "Barista Coffee Clip card",
                        NumberOfTickets = 10,
                        Price           = 30,
                        ExperienceWorth = 10,
                        Visible         = true
                    }
                };

                var user = new User
                {
                    UserGroup = UserGroup.Barista
                };

                var result = await productService.GetProductsForUserAsync(user);

                Assert.Equal(expected, result);
            }
        }
示例#21
0
        public async Task RecoverUserGivenValidTokenUpdatesPasswordAndResetsUsersTokens()
        {
            // Arrange
            var builder = new DbContextOptionsBuilder <CoffeeCardContext>()
                          .UseInMemoryDatabase(nameof(RecoverUserGivenValidTokenUpdatesPasswordAndResetsUsersTokens));

            var databaseSettings = new DatabaseSettings
            {
                SchemaName = "test"
            };
            var environmentSettings = new EnvironmentSettings()
            {
                EnvironmentType = EnvironmentType.Test
            };
            var loginLimiterSettings = new LoginLimiterSettings()
            {
                IsEnabled = true, MaximumLoginAttemptsWithinTimeOut = 5, TimeOutPeriodInMinutes = 5
            };

            var claim  = new Claim(ClaimTypes.Email, "*****@*****.**");
            var claims = new List <Claim> {
                claim
            };
            var validToken = new JwtSecurityToken("analog", "all", claims);

            var tokenService = new Mock <ITokenService>();

            tokenService.Setup(t => t.ReadToken("valid")).Returns(validToken);
            tokenService.Setup(t => t.ValidateToken("valid")).ReturnsAsync(true);

            var    userPass = "******";
            string newUserPass;
            ICollection <Token> newUserTokens;

            // Act
            await using (var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings))
            {
                var token      = new Token("valid");
                var userTokens = new List <Token> {
                    token
                };

                var user = new User
                {
                    Tokens = userTokens, Email = "*****@*****.**", Programme = new Programme(), Password = userPass
                };
                context.Add(user);
                context.SaveChanges();

                var accountService = new AccountService(context, environmentSettings, tokenService.Object,
                                                        new Mock <IEmailService>().Object, new Mock <IHashService>().Object,
                                                        new Mock <IHttpContextAccessor>().Object, new Mock <ILoginLimiter>().Object, loginLimiterSettings);

                await accountService.RecoverUserAsync("valid", "3433");

                var updatedUser = context.Users.FirstOrDefault(u => u.Email == user.Email);
                newUserPass   = updatedUser.Password;
                newUserTokens = updatedUser.Tokens;
            }

            var expectedTokenCount = 0;

            // Assert
            Assert.NotEqual(newUserPass, userPass);
            Assert.Equal(newUserTokens.Count, expectedTokenCount);
        }