Beispiel #1
0
        public async Task GetExpensesAccessTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                await fixture.ExpectGetAsync("/api/account/Hans/export/tsv", HttpStatusCode.OK);

                await fixture.ExpectGetAsync("/api/account/Shared/export/tsv", HttpStatusCode.OK);

                await fixture.ExpectGetAsync("/api/account/Petra/expenses", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Unknown/expenses", HttpStatusCode.Unauthorized);

                fixture.Logout();

                await fixture.ExpectGetAsync("/api/account/Hans/export/tsv", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Shared/export/tsv", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Petra/expenses", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Unknown/expenses", HttpStatusCode.Unauthorized);
            }
        }
Beispiel #2
0
        public async Task CreateUpdateDeleteExpenseTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(0);

                // Create.
                var cmd = new Expense(-100, "Ausgabe", "Essen", "Pizza").AsCommand("Hans");
                (await fixture.Client.PostAsync("/api/account/Hans/expenses", cmd.AsContent())).ShouldBeOk();
                var exp = (await fixture.GetExpensesAsync("Hans")).Single();
                exp.Amount.Should().Be(-100);

                // Edit.
                exp.Amount = -200;
                (await fixture.Client.PutAsync($"/api/account/Hans/expense/{exp.Id}", exp.AsContent())).ShouldBeOk();
                exp = (await fixture.GetExpensesAsync("Hans")).Single();
                exp.Amount.Should().Be(-200);
                exp.Details.Should().Be("pidser", "PipelineBehaviors should be enabled :)");

                // Get Single.
                exp = await fixture.GetExpenseAsync("Hans", exp.Id);

                exp.Amount.Should().Be(-200);

                // Delete.
                (await fixture.Client.DeleteAsync($"/api/account/Hans/expense/{exp.Id}")).ShouldBeOk();
                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(0);
            }
        }
Beispiel #3
0
        public async Task UsersShouldNotHaveAccessToForeignAccountsTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(0);

                // Create.
                var cmd = new Expense(-100, "Ausgabe", "Essen", "Pizza").AsCommand("Hans");
                (await fixture.Client.PostAsync("/api/account/Hans/expenses", cmd.AsContent())).ShouldBeOk();
                var exp = (await fixture.GetExpensesAsync("Hans")).Single();

                // Switch user.
                fixture.Logout();
                await fixture.Login("Petra");

                // Check foreign user actions.
                (await fixture.GetExpensesAsync("Petra")).Should().HaveCount(0);
                (await fixture.Client.GetAsync("/api/account/Hans/expenses")).StatusCode.Should().Be(HttpStatusCode.Unauthorized);
                (await fixture.Client.GetAsync($"/api/account/Hans/expense/{exp.Id}")).IsUnauthorized();
                (await fixture.Client.PostAsync($"/api/account/Hans/expenses", exp.AsContent())).IsUnauthorized();
                (await fixture.Client.PutAsync($"/api/account/Hans/expense/{exp.Id}", exp.AsContent())).IsUnauthorized();
                (await fixture.Client.DeleteAsync($"/api/account/Hans/expense/{exp.Id}")).IsUnauthorized();
            }
        }
Beispiel #4
0
        public async Task HandleByCreatingExpenseTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                // Import.
                var csv = File.ReadAllBytes("Import/dkb-import-test.csv");
                await fixture.PostFileAsync("/api/account/Hans/import/csv", "csvFile", "file.csv", csv);

                // Check imported stuff.
                var imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                var importedExpense = imported.Single();

                // No expenses yet.
                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(0);

                // Handle expense by creating new expense.
                await fixture.AddExpenseAsync("Hans", 10, "Cat", "Sub", modCmd : cmd => cmd.HandlesImportedExpenseId = importedExpense.Id);

                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(1);

                // No more unhandled imported expenses expected.
                imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                imported.Should().HaveCount(0);
            }
        }
Beispiel #5
0
        public async Task ExpensePredictionTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                for (var n = 0; n < CategoryPredictionService.MinimumNumberOfExpensesForPrediction; n++)
                {
                    await fixture.AddExpenseAsync("Hans", -100, "Essen", "Pizza");
                }
                for (var n = 0; n < CategoryPredictionService.MinimumNumberOfExpensesForPrediction; n++)
                {
                    await fixture.AddExpenseAsync("Hans", -200, "Einkaufen", "Pizza");
                }

                // Learn.
                var categoryPredictionService = fixture.GetService <ICategoryPredictionService>();
                await categoryPredictionService.LearnCategoriesAsync();

                // Verify.
                (await fixture.GetAsync <CategoryPredictionResult>("/api/account/Hans/categories/predict?amount=-100&created=2019-01-01&expenseDate=2019-01-01"))
                .Category.Should().Be("Essen");
                (await fixture.GetAsync <CategoryPredictionResult>("/api/account/Hans/categories/predict?amount=-200&created=2019-01-01&expenseDate=2019-01-01"))
                .Category.Should().Be("Einkaufen");
            }
        }
Beispiel #6
0
        public async Task FullTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                // Verify db is empty.
                var imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                imported.Length.Should().Be(0);

                // Import.
                var csv = File.ReadAllBytes("Import/dkb-import-test.csv");
                await fixture.PostFileAsync("/api/account/Hans/import/csv", "csvFile", "file.csv", csv);

                // Check imported stuff.
                imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                var importedExpense = imported.Single();
                importedExpense.Amount.Should().Be(-12.34M);
                importedExpense.BookingDay.Should().Be(DateTime.Parse("2019-10-25"));

                // Add some expenses.
                await fixture.AddExpenseAsync("Hans", -12.34M, "Wrong", "Subcategory", ex => ex.Date = importedExpense.BookingDay.AddDays(-100).Date);

                await fixture.AddExpenseAsync("Hans", -12.34M, "Wrong", "Subcategory", ex => ex.Date = importedExpense.BookingDay.AddDays(+100).Date);

                await fixture.AddExpenseAsync("Hans", -12, "Wrong", "Subcategory", ex => ex.Date = importedExpense.BookingDay.AddDays(-2).Date);

                await fixture.AddExpenseAsync("Hans", -12.34M, "Correct", "Subcategory", ex => ex.Date = importedExpense.BookingDay.AddDays(-2).Date);

                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(4);

                // Get related expenses.
                var relatedExpenses = await fixture.GetAsync <ExpenseViewModel[]>("/api/account/Hans/expenses?relatedToImportedExpense=" + importedExpense.Id);

                relatedExpenses.Should().HaveCount(1);
                var relatedExpense = relatedExpenses.Single();
                relatedExpense.CategoryName.Should().Be("Correct");

                // Handle expense by linking it.
                await fixture.ExpectPostAsync($"/api/account/Hans/import/link?importedExpenseId={importedExpense.Id}&relatedExpenseId={relatedExpense.Id}", HttpStatusCode.OK);

                (await fixture.GetExpensesAsync("Hans")).Should().HaveCount(4);
                imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                imported.Should().HaveCount(0);

                // Check link.
                var modifiedImportedExpense = fixture.QueryDb(db => db.ImportedExpenses.Include(ex => ex.Expense).Where(ex => ex.Expense != null).Single());
                modifiedImportedExpense.Expense.Id.Should().Be(relatedExpense.Id);
            }
        }
Beispiel #7
0
        public async Task GetSummaryTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Admin");

                var users = await fixture.GetAsync <UserSummary[]>("/api/users");

                users.Should().HaveCount(3);
                users[0].Name.Should().Be("Hans");
                users[1].Name.Should().Be("Petra");
                users[2].Name.Should().Be("Admin");
            }
        }
Beispiel #8
0
        public async Task CsvExportTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                var resp = await fixture.Client.GetAsync("/api/account/Hans/export/tsv");

                resp.Content.Headers.ContentType.ToString().Should().Be("text/tab-separated-values");
                resp.ShouldBeOk();
                var content = await resp.Content.ReadAsStringAsync();

                content.Should().StartWith("Id\tAccountId\tCategory");
            }
        }
Beispiel #9
0
        public async Task AuthorizationTests()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Admin");

                (await fixture.Client.GetAsync("/api/users")).ShouldBeOk();
                fixture.Logout();

                await fixture.Login("Hans");

                (await fixture.Client.GetAsync("/api/users")).ShouldBeForbidden();
                fixture.Logout();
            }
        }
Beispiel #10
0
        public async Task EnsureThatExpensesFromOtherAccountsDoNotLeak()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                // Import.
                var csv = File.ReadAllBytes("Import/dkb-import-test.csv");
                await fixture.PostFileAsync("/api/account/Hans/import/csv", "csvFile", "file.csv", csv);

                var hansImportedExpense = (await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled")).Single();

                // Add some expenses.
                await fixture.AddExpenseAsync("Hans", -12.34M, "Correct", "Subcategory", ex => ex.Date = hansImportedExpense.BookingDay.AddDays(-2).Date);

                // Get related expenses.
                var relatedExpenses = await fixture.GetAsync <ExpenseViewModel[]>("/api/account/Hans/expenses?relatedToImportedExpense=" + hansImportedExpense.Id);

                relatedExpenses.Should().HaveCount(1);
                relatedExpenses.Single().CategoryName.Should().Be("Correct");

                // Login as different user.
                fixture.Logout();
                await fixture.Login("Petra");

                // Simple leak.
                await fixture.ExpectGetAsync("/api/account/Hans/expenses?relatedToImportedExpense=" + hansImportedExpense.Id, HttpStatusCode.Unauthorized);

                // Leak via related expenses.
                await fixture.PostFileAsync("/api/account/Petra/import/csv", "csvFile", "file.csv", csv);

                var petraImportedExpense = (await fixture.GetAsync <ImportedExpense[]>("/api/account/Petra/imports/unhandled")).Single();
                var petraRelatedExpenses = await fixture.GetAsync <ExpenseViewModel[]>("/api/account/Petra/expenses?relatedToImportedExpense=" + petraImportedExpense.Id);

                petraRelatedExpenses.Should().BeEmpty();

                // Leak via linking.
                await fixture.ExpectPostAsync($"/api/account/Hans/import/link?importedExpenseId={hansImportedExpense.Id}&relatedExpenseId={relatedExpenses.Single().Id}", HttpStatusCode.Unauthorized);

                await fixture.ExpectPostAsync($"/api/account/Petra/import/link?importedExpenseId={hansImportedExpense.Id}&relatedExpenseId={relatedExpenses.Single().Id}", HttpStatusCode.NotFound);

                // Leak via creating.
                await fixture.ExpectAddExpenseAsync("Hans", 10, "Cat", "Sub", modCmd : cmd => cmd.HandlesImportedExpenseId = hansImportedExpense.Id, expectedStatus : HttpStatusCode.Unauthorized);

                await fixture.ExpectAddExpenseAsync("Petra", 10, "Cat", "Sub", modCmd : cmd => cmd.HandlesImportedExpenseId = hansImportedExpense.Id, expectedStatus : HttpStatusCode.NotFound);
            }
        }
Beispiel #11
0
        public async Task GetExpensesAccessTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                await fixture.ExpectGetAsync("/api/account/Hans/imports/unhandled", HttpStatusCode.OK);

                fixture.Logout();

                await fixture.ExpectGetAsync("/api/account/Hans/imports/unhandled", HttpStatusCode.Unauthorized);

                await fixture.Login("Petra");

                await fixture.ExpectGetAsync("/api/account/Hans/imports/unhandled", HttpStatusCode.Unauthorized);
            }
        }
Beispiel #12
0
        public async Task CreateDeleteCategoryTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                var categories = await fixture.GetCategoriesAsync("Hans");

                categories.Single().Name.Should().Be("Ausgaben");

                // Create
                var cmd = new CreateCategoryCommand("Hans", "Einnahmen");
                (await fixture.Client.PostAsync("/api/account/Hans/categories", cmd.AsContent())).ShouldBeOk();
                categories = await fixture.GetCategoriesAsync("Hans");

                categories.Skip(1).Single().Name.Should().Be("Einnahmen");

                // Create sub
                (await fixture.Client.PutAsync("/api/account/Hans/category/Einnahmen/Aktien", null)).ShouldBeOk();
                categories = await fixture.GetCategoriesAsync("Hans");

                categories.Skip(1).Single().Subcategories.Single().Should().Be("Aktien");

                // Predict
                (await fixture.Client.GetAsync("/api/account/Hans/categories/predict")).StatusCode.Should().Be(HttpStatusCode.NoContent);

                // Delete sub
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Einnahmen/Aktien")).ShouldBeOk();
                categories = await fixture.GetCategoriesAsync("Hans");

                categories.Skip(1).Single().Subcategories.Should().HaveCount(0);

                // Delete main
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Einnahmen")).ShouldBeOk();
                categories = await fixture.GetCategoriesAsync("Hans");

                categories.Should().HaveCount(1);
            }
        }
Beispiel #13
0
        public async Task PostUserText(string user, string newUserName, bool shouldBeAllowed, bool shouldSucceed, bool createDefaultAccount)
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login(user);

                var result = await fixture.Client.PostAsync("/api/users", new CreateUserCommand(newUserName, "password", createDefaultAccount).AsContent());

                if (!shouldBeAllowed)
                {
                    result.ShouldBeForbidden();
                    return;
                }

                if (!shouldSucceed)
                {
                    result.ShouldClientFail();
                    return;
                }

                var users = await fixture.GetAsync <UserSummary[]>("/api/users");

                users.Should().HaveCount(4);
                users[0].Name.Should().Be("Hans");
                users[1].Name.Should().Be("Petra");
                users[2].Name.Should().Be("Admin");
                users[3].Name.Should().Be("Neu");

                if (createDefaultAccount)
                {
                    users[3].Accounts.Single().Should().Be("Neu");
                }
                else
                {
                    users[3].Accounts.Should().BeEmpty();
                }
            }
        }
Beispiel #14
0
        public async Task EnsureAccessIsVerifiedTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                var testCmd = new CreateCategoryCommand("Hans", "Einnahmen");

                // Test authenticated.
                await fixture.Login("Petra");

                await fixture.ExpectGetAsync("/api/account/Hans/categories", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Hans/categories/predict", HttpStatusCode.Unauthorized);

                (await fixture.Client.PostAsync("/api/account/Hans/categories", testCmd.AsContent())).IsUnauthorized();
                (await fixture.Client.PostAsync("/api/account/Teal'C/categories", testCmd.AsContent())).IsUnauthorized();
                (await fixture.Client.PutAsync("/api/account/Hans/category/Einnahmen/Aktien", null)).IsUnauthorized();
                (await fixture.Client.PutAsync("/api/account/SamCarter/category/Einnahmen/Aktien", null)).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Einnahmen/Aktien")).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Einnahmen")).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Schwarzgeld")).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/JackONeil/category/Schwarzgeld")).IsUnauthorized();

                // Test unauthenticated.
                fixture.Logout();
                await fixture.ExpectGetAsync("/api/account/Hans/categories", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Hans/categories/predict", HttpStatusCode.Unauthorized);

                (await fixture.Client.PostAsync("/api/account/Hans/categories", testCmd.AsContent())).IsUnauthorized();
                (await fixture.Client.PostAsync("/api/account/Teal'C/categories", testCmd.AsContent())).IsUnauthorized();
                (await fixture.Client.PutAsync("/api/account/Hans/category/Einnahmen/Aktien", null)).IsUnauthorized();
                (await fixture.Client.PutAsync("/api/account/SamCarter/category/Einnahmen/Aktien", null)).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Einnahmen/Aktien")).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Einnahmen")).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/Hans/category/Schwarzgeld")).IsUnauthorized();
                (await fixture.Client.DeleteAsync("/api/account/JackONeil/category/Schwarzgeld")).IsUnauthorized();
            }
        }
Beispiel #15
0
        public async Task EnsureAccessIsVerifiedTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.ExpectGetAsync("/api/account/Hans/charts/month-by-category", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Hans/charts/expense-history", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Hans/charts/revenue-history", HttpStatusCode.Unauthorized);

                await fixture.ExpectPostAsync("/api/account/Hans/charts/compare-category", new GetCompareCategoryChartQuery().AsContent(), HttpStatusCode.Unauthorized);

                await fixture.Login("Hans");

                await fixture.ExpectGetAsync("/api/account/Hans/charts/month-by-category", HttpStatusCode.OK);

                await fixture.ExpectGetAsync("/api/account/Hans/charts/expense-history", HttpStatusCode.OK);

                await fixture.ExpectGetAsync("/api/account/Hans/charts/revenue-history", HttpStatusCode.OK);

                await fixture.ExpectPostAsync("/api/account/Hans/charts/compare-category", new GetCompareCategoryChartQuery().AsContent(), HttpStatusCode.OK);

                fixture.Logout();

                await fixture.Login("Petra");

                await fixture.ExpectGetAsync("/api/account/Hans/charts/month-by-category", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Hans/charts/expense-history", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/Hans/charts/revenue-history", HttpStatusCode.Unauthorized);

                await fixture.ExpectGetAsync("/api/account/ColonelHogan/charts/revenue-history", HttpStatusCode.Unauthorized);

                await fixture.ExpectPostAsync("/api/account/Hans/charts/compare-category", new GetCompareCategoryChartQuery().AsContent(), HttpStatusCode.Unauthorized);
            }
        }
Beispiel #16
0
        public async Task HandleTest()
        {
            using (var fixture = new GeldAppFixture())
            {
                await fixture.Login("Hans");

                // Import.
                var csv = File.ReadAllBytes("Import/dkb-import-test.csv");
                await fixture.PostFileAsync("/api/account/Hans/import/csv", "csvFile", "file.csv", csv);

                // Check imported stuff.
                var imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                var importedExpense = imported.Single();

                // Handle expense by linking it.
                await fixture.ExpectPostAsync($"/api/account/Hans/imports/{importedExpense.Id}/handle", HttpStatusCode.OK);

                // No more unhandled imported expenses expected.
                imported = await fixture.GetAsync <ImportedExpense[]>("/api/account/Hans/imports/unhandled");

                imported.Should().HaveCount(0);
            }
        }