12 | This app does not currently have a real email sender registered, see these docs for how to configure a real email sender.
13 | Normally this would be emailed: Click here to confirm your account
14 |
15 | }
16 | else
17 | {
18 |
19 | Please check your email to confirm your account.
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.Data.Tests.Integration/Fakers/CounterpartyFaker.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using Gnomeshade.Data.Entities;
8 |
9 | namespace Gnomeshade.Data.Tests.Integration.Fakers;
10 |
11 | public sealed class CounterpartyFaker : NamedEntityFaker
12 | {
13 | public CounterpartyFaker(Guid userId)
14 | : base(userId)
15 | {
16 | RuleFor(party => party.Name, faker => faker.Company.CompanyName());
17 | RuleFor(party => party.NormalizedName, (_, party) => party.Name.ToUpperInvariant());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data.PostgreSQL/Dapper/NullableInstantTypeHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Data;
6 |
7 | using Dapper;
8 |
9 | using NodaTime;
10 |
11 | namespace Gnomeshade.Data.PostgreSQL.Dapper;
12 |
13 | internal sealed class NullableInstantTypeHandler : SqlMapper.TypeHandler
14 | {
15 | ///
16 | public override void SetValue(IDbDataParameter parameter, Instant? value) => parameter.Value = value;
17 |
18 | ///
19 | public override Instant? Parse(object value) => (Instant?)value;
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Entities/Abstractions/INamedEntity.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | namespace Gnomeshade.Data.Entities.Abstractions;
6 |
7 | ///
8 | /// Represents an entity that can be named by the user.
9 | ///
10 | public interface INamedEntity : IEntity
11 | {
12 | ///
13 | /// Gets or sets the name of the entity.
14 | ///
15 | string Name { get; set; }
16 |
17 | ///
18 | /// Gets or sets the normalized name of the entity.
19 | ///
20 | string NormalizedName { get; set; }
21 | }
22 |
--------------------------------------------------------------------------------
/deployment/build.ps1:
--------------------------------------------------------------------------------
1 | param (
2 | [Parameter(Mandatory = $true, Position = 0)]
3 | [System.String]
4 | $Project
5 | )
6 |
7 | $publish_dir = "source\$Project\bin\Release\"
8 | $archive_name = "${Project}.msi"
9 |
10 | $dotnetArgs = @()
11 | $dotnetArgs = $dotnetArgs + "build"
12 | $dotnetArgs = $dotnetArgs + ".\source\$Project\$Project.wixproj"
13 | $dotnetArgs = $dotnetArgs + "--configuration" + "Release"
14 | $dotnetArgs = $dotnetArgs + "--no-restore"
15 | $dotnetArgs = $dotnetArgs + "/nologo"
16 |
17 | & dotnet $dotnetArgs
18 |
19 | "artifact-name=$archive_name" >> $env:GITHUB_OUTPUT
20 | "artifact<> $env:GITHUB_OUTPUT
21 | "$publish_dir\$archive_name" >> $env:GITHUB_OUTPUT
22 | "EOF" >> $env:GITHUB_OUTPUT
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Projects/ProjectView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 |
7 | using Gnomeshade.Avalonia.Core;
8 | using Gnomeshade.Avalonia.Core.Projects;
9 |
10 | namespace Gnomeshade.Desktop.Views.Projects;
11 |
12 | ///
13 | public sealed partial class ProjectView : UserControl, IView
14 | {
15 | /// Initializes a new instance of the class.
16 | public ProjectView() => InitializeComponent();
17 | }
18 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Accounts/AccountInCurrencyCreation.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 | using System.ComponentModel.DataAnnotations;
7 |
8 | using JetBrains.Annotations;
9 |
10 | namespace Gnomeshade.WebApi.Models.Accounts;
11 |
12 | /// The information needed to add a currency to an account.
13 | [PublicAPI]
14 | public sealed record AccountInCurrencyCreation : Creation
15 | {
16 | /// The id of the currency to add to an account.
17 | [Required]
18 | public Guid? CurrencyId { get; set; }
19 | }
20 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/OpenApi/InstantSchemaFilter.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using JetBrains.Annotations;
6 |
7 | using Microsoft.OpenApi.Models;
8 |
9 | using NodaTime;
10 |
11 | namespace Gnomeshade.WebApi.OpenApi;
12 |
13 | [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
14 | internal sealed class InstantSchemaFilter : SchemaFilter
15 | {
16 | ///
17 | protected override void ApplyFilter(OpenApiSchema schema)
18 | {
19 | schema.Type = "string";
20 | schema.Format = "date-time";
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.TestingHelpers/Models/LoanExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.WebApi.Models.Loans;
6 |
7 | namespace Gnomeshade.TestingHelpers.Models;
8 |
9 | public static class LoanExtensions
10 | {
11 | public static LoanCreation ToCreation(this Loan loan) => new()
12 | {
13 | OwnerId = loan.OwnerId,
14 | Name = loan.Name,
15 | IssuingCounterpartyId = loan.IssuingCounterpartyId,
16 | ReceivingCounterpartyId = loan.ReceivingCounterpartyId,
17 | Principal = loan.Principal,
18 | CurrencyId = loan.CurrencyId,
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: type:enhancement
6 | assignees: VMelnalksnis
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Projects/ProjectCreation.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 | using System.ComponentModel.DataAnnotations;
7 |
8 | namespace Gnomeshade.WebApi.Models.Projects;
9 |
10 | /// The information needed to create or update a project.
11 | public sealed record ProjectCreation : Creation
12 | {
13 | ///
14 | [Required]
15 | public string Name { get; set; } = null!;
16 |
17 | ///
18 | public Guid? ParentProjectId { get; set; }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.WebApi.Tests.Integration.PostgreSQL/Fixtures/UnloggedTableScriptPreprocessor.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using DbUp.Engine;
6 |
7 | namespace Gnomeshade.WebApi.Tests.Integration.Fixtures;
8 |
9 | ///
10 | ///
11 | internal sealed class UnloggedTableScriptPreprocessor : IScriptPreprocessor
12 | {
13 | ///
14 | public string Process(string contents) => contents.Replace("CREATE TABLE", "CREATE UNLOGGED TABLE");
15 | }
16 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/Loan/SelectAll.sql:
--------------------------------------------------------------------------------
1 | SELECT loans.id,
2 | loans.created_at CreatedAt,
3 | loans.owner_id OwnerId,
4 | loans.created_by_user_id CreatedByUserId,
5 | loans.modified_at ModifiedAt,
6 | loans.modified_by_user_id ModifiedByUserId,
7 | loans.transaction_id TransactionId,
8 | loans.issuing_counterparty_id IssuingCounterpartyId,
9 | loans.receiving_counterparty_id ReceivingCounterpartyId,
10 | loans.amount AS Amount,
11 | loans.currency_id CurrencyId,
12 | loans.deleted_at DeletedAt,
13 | loans.deleted_by_user_id DeletedByUserId
14 | FROM loans
15 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/Aggregates/Maximum.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gnomeshade.Avalonia.Core.Reports.Aggregates;
9 |
10 | /// Aggregates the collection to the largest value.
11 | ///
12 | public sealed class Maximum : IAggregateFunction
13 | {
14 | ///
15 | public string Name => nameof(Maximum);
16 |
17 | decimal IAggregateFunction.Aggregate(IEnumerable source) => source.Max();
18 | }
19 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/Aggregates/Minimum.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gnomeshade.Avalonia.Core.Reports.Aggregates;
9 |
10 | /// Aggregates the collection to the smallest value.
11 | ///
12 | public sealed class Minimum : IAggregateFunction
13 | {
14 | ///
15 | public string Name => nameof(Minimum);
16 |
17 | decimal IAggregateFunction.Aggregate(IEnumerable source) => source.Min();
18 | }
19 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/Aggregates/Average.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gnomeshade.Avalonia.Core.Reports.Aggregates;
9 |
10 | /// Aggregates the collection to an average value.
11 | ///
12 | public sealed class Average : IAggregateFunction
13 | {
14 | ///
15 | public string Name => nameof(Average);
16 |
17 | decimal IAggregateFunction.Aggregate(IEnumerable source) => source.Average();
18 | }
19 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Loans/LoanUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 |
7 | using Gnomeshade.Avalonia.Core;
8 | using Gnomeshade.Avalonia.Core.Loans;
9 |
10 | namespace Gnomeshade.Desktop.Views.Loans;
11 |
12 | ///
13 | public sealed partial class LoanUpsertionView : UserControl, IView
14 | {
15 | /// Initializes a new instance of the class.
16 | public LoanUpsertionView() => InitializeComponent();
17 | }
18 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/Loan2/SelectAll.sql:
--------------------------------------------------------------------------------
1 | SELECT loans2.id,
2 | loans2.created_at CreatedAt,
3 | loans2.created_by_user_id CreatedByUserId,
4 | loans2.deleted_at DeletedAt,
5 | loans2.deleted_by_user_id DeletedByUserId,
6 | loans2.owner_id OwnerId,
7 | loans2.modified_at ModifiedAt,
8 | loans2.modified_by_user_id ModifiedByUserId,
9 | loans2.name,
10 | loans2.normalized_name NormalizedName,
11 |
12 | loans2.issuing_counterparty_id IssuingCounterpartyId,
13 | loans2.receiving_counterparty_id ReceivingCounterpartyId,
14 | loans2.principal,
15 | loans2.currency_id CurrencyId
16 | FROM loans2
17 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Help/AboutView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Help;
10 |
11 | namespace Gnomeshade.Desktop.Views.Help;
12 |
13 | ///
14 | public sealed partial class AboutView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public AboutView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/DialogWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | #if DEBUG
6 | using Avalonia;
7 | #endif
8 | using Avalonia.Controls;
9 | using Avalonia.Markup.Xaml;
10 |
11 | namespace Gnomeshade.Desktop.Views;
12 |
13 | /// The root element of a dialog window.
14 | public sealed partial class DialogWindow : Window
15 | {
16 | /// Initializes a new instance of the class.
17 | public DialogWindow()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 |
21 | #if DEBUG
22 | this.AttachDevTools();
23 | #endif
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Entities/OwnerEntity.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.Data.Entities.Abstractions;
6 |
7 | namespace Gnomeshade.Data.Entities;
8 |
9 | /// Represents a collection of other entities (users, roles, groups, etc.) that can own other entities.
10 | ///
11 | ///
12 | public sealed record OwnerEntity : Entity, INamedEntity
13 | {
14 | ///
15 | public string Name { get; set; } = null!;
16 |
17 | ///
18 | public string NormalizedName { get; set; } = null!;
19 | }
20 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Accesses/OwnerView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Accesses;
10 |
11 | namespace Gnomeshade.Desktop.Views.Accesses;
12 |
13 | ///
14 | public sealed partial class OwnerView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public OwnerView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.Data.Tests.Integration/Fakers/UnitFaker.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using Gnomeshade.Data.Entities;
8 |
9 | namespace Gnomeshade.Data.Tests.Integration.Fakers;
10 |
11 | public sealed class UnitFaker : NamedEntityFaker
12 | {
13 | public UnitFaker(UserEntity user)
14 | : this(user.Id)
15 | {
16 | }
17 |
18 | public UnitFaker(Guid userId)
19 | : base(userId)
20 | {
21 | RuleFor(unit => unit.Name, faker => faker.Commerce.ProductMaterial());
22 | RuleFor(unit => unit.NormalizedName, (_, unit) => unit.Name.ToUpperInvariant());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.TestingHelpers/Models/PurchaseExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.WebApi.Models.Transactions;
6 |
7 | namespace Gnomeshade.TestingHelpers.Models;
8 |
9 | public static class PurchaseExtensions
10 | {
11 | public static PurchaseCreation ToCreation(this Purchase purchase) => new()
12 | {
13 | OwnerId = purchase.OwnerId,
14 | TransactionId = purchase.TransactionId,
15 | ProductId = purchase.ProductId,
16 | Amount = purchase.Amount,
17 | CurrencyId = purchase.CurrencyId,
18 | Price = purchase.Price,
19 | DeliveryDate = purchase.DeliveryDate,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data.PostgreSQL/Dapper/UnsignedIntegerTypeHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Data;
6 |
7 | using Dapper;
8 |
9 | namespace Gnomeshade.Data.PostgreSQL.Dapper;
10 |
11 | internal sealed class UnsignedIntegerTypeHandler : SqlMapper.TypeHandler
12 | {
13 | ///
14 | public override void SetValue(IDbDataParameter parameter, uint? value)
15 | {
16 | parameter.DbType = DbType.Int32;
17 | parameter.Value = (int?)value;
18 | }
19 |
20 | ///
21 | public override uint? Parse(object? value) => value is int number ? (uint)number : null;
22 | }
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/Project/Select.sql:
--------------------------------------------------------------------------------
1 | SELECT projects.id,
2 | projects.created_at CreatedAt,
3 | projects.owner_id OwnerId,
4 | projects.created_by_user_id CreatedByUserId,
5 | projects.modified_at ModifiedAt,
6 | projects.modified_by_user_id ModifiedByUserId,
7 | projects.name,
8 | projects.normalized_name NormalizedName,
9 | projects.parent_project_id ParentProjectId
10 | FROM projects
11 | INNER JOIN owners ON owners.id = projects.owner_id
12 | INNER JOIN ownerships ON owners.id = ownerships.owner_id
13 | INNER JOIN access ON access.id = ownerships.access_id
14 | WHERE ownerships.user_id = @userId
15 | AND (access.normalized_name = @access OR access.normalized_name = 'OWNER')
16 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Imports/ImportView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Imports;
10 |
11 | namespace Gnomeshade.Desktop.Views.Imports;
12 |
13 | ///
14 | public sealed partial class ImportView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ImportView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/CategoryFilterView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 |
7 | using Gnomeshade.Avalonia.Core;
8 | using Gnomeshade.Avalonia.Core.Products;
9 |
10 | namespace Gnomeshade.Desktop.Views.Products;
11 |
12 | ///
13 | public sealed partial class CategoryFilterView : UserControl, IView
14 | {
15 | /// Initializes a new instance of the class.
16 | public CategoryFilterView()
17 | {
18 | InitializeComponent();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/UnitView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | /// An overview of of all units.
14 | public sealed partial class UnitView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public UnitView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Importing/AccountReference.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.WebApi.Models.Accounts;
6 |
7 | using JetBrains.Annotations;
8 |
9 | namespace Gnomeshade.WebApi.Models.Importing;
10 |
11 | /// A reference to an account that was used during import.
12 | [PublicAPI]
13 | public sealed record AccountReference
14 | {
15 | /// Whether or not the account was created during import.
16 | public bool Created { get; set; }
17 |
18 | /// The referenced account.
19 | public Account Account { get; set; } = null!;
20 | }
21 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.WebApi.Tests.Integration.Oidc/Gnomeshade.WebApi.Tests.Integration.Oidc.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/deployment/test-docker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | tag="ghcr.io/vmelnalksnis/gnomeshade:test"
5 | name="test"
6 |
7 | function printLogs() {
8 | docker logs $name
9 | }
10 |
11 | trap printLogs EXIT
12 |
13 | docker build --tag $tag --build-arg "BUILD_NUMBER=$1" ./
14 | docker run --name $name -d -p 8000:8080 -e "Admin__Password=$2" $tag
15 |
16 | wget --tries=10 --retry-connrefused --waitretry=1 --timeout=15 "http://localhost:8000/api/v1.0/health"
17 |
18 | if [[ $(cat health) != "Healthy" ]]; then
19 | exit 1
20 | fi
21 |
22 | curl --header "Content-Type: application/json" \
23 | --request POST \
24 | --data '{"username":"john.doe", "password": "Password123!", "email": "john.doe@example.com", "fullName": "John Doe" }' \
25 | http://localhost:8000/Authorization/Register
26 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/Calculations/CalculableValue.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.WebApi.Models.Transactions;
6 |
7 | using NodaTime;
8 |
9 | namespace Gnomeshade.Avalonia.Core.Reports.Calculations;
10 |
11 | internal struct CalculableValue
12 | {
13 | internal CalculableValue(Purchase purchase, ZonedDateTime date, decimal multiplier)
14 | {
15 | Purchase = purchase;
16 | Date = date;
17 | Multiplier = multiplier;
18 | }
19 |
20 | internal Purchase Purchase { get; }
21 |
22 | internal ZonedDateTime Date { get; }
23 |
24 | internal decimal Multiplier { get; }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/DialogWindow.axaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Help/LicensesView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Help;
10 |
11 | namespace Gnomeshade.Desktop.Views.Help;
12 |
13 | ///
14 | public sealed partial class LicensesView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public LicensesView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Accounts/AccountView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Accounts;
10 |
11 | namespace Gnomeshade.Desktop.Views.Accounts;
12 |
13 | ///
14 | public sealed partial class AccountView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public AccountView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Loans/Migration/LoanMigrationView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 |
7 | using Gnomeshade.Avalonia.Core;
8 | using Gnomeshade.Avalonia.Core.Loans.Migration;
9 |
10 | namespace Gnomeshade.Desktop.Views.Loans.Migration;
11 |
12 | ///
13 | public sealed partial class LoanMigrationView : UserControl, IView
14 | {
15 | /// Initializes a new instance of the class.
16 | public LoanMigrationView() => InitializeComponent();
17 | }
18 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/ProductView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | ///
14 | public sealed partial class ProductView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ProductView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Authentication/UserModel.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using JetBrains.Annotations;
6 |
7 | namespace Gnomeshade.WebApi.Models.Authentication;
8 |
9 | /// Information about a user.
10 | [PublicAPI]
11 | public sealed record UserModel
12 | {
13 | /// The id of the user.
14 | public string Id { get; set; } = null!;
15 |
16 | /// The username of the user.
17 | public string Username { get; set; } = null!;
18 |
19 | /// The primary email address of the user.
20 | public string Email { get; set; } = null!;
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Importing/TransferReference.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.WebApi.Models.Transactions;
6 |
7 | using JetBrains.Annotations;
8 |
9 | namespace Gnomeshade.WebApi.Models.Importing;
10 |
11 | /// A reference to an transfer that was used during import.
12 | [PublicAPI]
13 | public sealed record TransferReference
14 | {
15 | /// Whether or not the transfer was created during import.
16 | public bool Created { get; set; }
17 |
18 | /// The referenced transfer.
19 | public Transfer Transfer { get; set; } = null!;
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Authentication/LoginView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Authentication;
10 |
11 | namespace Gnomeshade.Desktop.Views.Authentication;
12 |
13 | ///
14 | public sealed partial class LoginView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public LoginView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Authentication/Login.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.ComponentModel.DataAnnotations;
6 |
7 | using JetBrains.Annotations;
8 |
9 | namespace Gnomeshade.WebApi.Models.Authentication;
10 |
11 | /// The information needed to log in.
12 | [PublicAPI]
13 | public sealed record Login
14 | {
15 | /// The username to log in with. Required.
16 | [Required]
17 | public string Username { get; set; } = null!;
18 |
19 | /// The password to log in with. Required.
20 | [Required]
21 | public string Password { get; set; } = null!;
22 | }
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Authentication/LoginResponse.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using JetBrains.Annotations;
6 |
7 | using NodaTime;
8 |
9 | namespace Gnomeshade.WebApi.Models.Authentication;
10 |
11 | /// Information about the started session.
12 | [PublicAPI]
13 | public sealed record LoginResponse(string Token, Instant ValidTo)
14 | {
15 | /// A JWT for authenticating the session.
16 | public string Token { get; set; } = Token;
17 |
18 | /// The point in time until which the session is valid.
19 | public Instant ValidTo { get; set; } = ValidTo;
20 | }
21 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.WebApi.Tests.Integration/Fixtures/DatabaseFixtureSource.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | namespace Gnomeshade.WebApi.Tests.Integration.Fixtures;
10 |
11 | public sealed class DatabaseFixtureSource : IEnumerable
12 | {
13 | internal static readonly List Fixtures = WebserverSetup.WebserverFixtures;
14 |
15 | public IEnumerator GetEnumerator()
16 | {
17 | return Fixtures
18 | .Select(fixture => new TestFixtureData(fixture).SetArgDisplayNames(fixture.Name))
19 | .GetEnumerator();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Links/LinkView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Links;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Links;
12 |
13 | ///
14 | public sealed partial class LinkView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public LinkView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Client/GnomeshadeOptions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 | using System.ComponentModel.DataAnnotations;
7 |
8 | using JetBrains.Annotations;
9 |
10 | namespace Gnomeshade.WebApi.Client;
11 |
12 | /// Settings for accessing gnomeshade API.
13 | [UsedImplicitly(ImplicitUseKindFlags.Assign, ImplicitUseTargetFlags.Members)]
14 | public sealed record GnomeshadeOptions
15 | {
16 | internal const string SectionName = "Gnomeshade";
17 |
18 | /// Gets or sets the gnomeshade API base address.
19 | [Required]
20 | public Uri? BaseAddress { get; set; }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Gnomeshade.Data.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | false
6 |
7 | CS8002
8 | true
9 | key.snk
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/AccountInCurrency/Select.sql:
--------------------------------------------------------------------------------
1 | SELECT a.id,
2 | a.owner_id OwnerId,
3 | a.created_at CreatedAt,
4 | a.created_by_user_id CreatedByUserId,
5 | a.modified_at ModifiedAt,
6 | a.modified_by_user_id ModifiedByUserId,
7 | a.account_id AccountId,
8 | a.currency_id CurrencyId
9 | FROM accounts_in_currency a
10 | INNER JOIN accounts on accounts.id = a.account_id
11 | INNER JOIN owners ON owners.id = accounts.owner_id
12 | INNER JOIN ownerships ON owners.id = ownerships.owner_id
13 | INNER JOIN access ON access.id = ownerships.access_id
14 | WHERE (ownerships.user_id = @userId AND (access.normalized_name = @access OR access.normalized_name = 'OWNER')
15 | AND accounts.deleted_at IS NULL)
16 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.Avalonia.Core.Tests/Accounts/AccountViewModelTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Threading.Tasks;
6 |
7 | using Gnomeshade.Avalonia.Core.Accounts;
8 | using Gnomeshade.Avalonia.Core.DesignTime;
9 |
10 | namespace Gnomeshade.Avalonia.Core.Tests.Accounts;
11 |
12 | public class AccountViewModelTests
13 | {
14 | [Test]
15 | public async Task DataGridView_ShouldBeGrouped()
16 | {
17 | var viewModel = new AccountViewModel(new StubbedActivityService(), new DesignTimeGnomeshadeClient());
18 | await viewModel.RefreshAsync();
19 |
20 | viewModel.DataGridView.Groups.Should().ContainSingle();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.Data.Tests.Integration/Fakers/CategoryFaker.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using Gnomeshade.Data.Entities;
8 |
9 | namespace Gnomeshade.Data.Tests.Integration.Fakers;
10 |
11 | public sealed class CategoryFaker : NamedEntityFaker
12 | {
13 | public CategoryFaker(Guid userId)
14 | : base(userId)
15 | {
16 | RuleFor(category => category.Name, faker => faker.Commerce.ProductName());
17 | RuleFor(category => category.NormalizedName, (_, product) => product.Name.ToUpperInvariant());
18 | RuleFor(category => category.Description, faker => faker.Lorem.Sentence());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/LocalDateConverter.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Globalization;
6 |
7 | using NodaTime;
8 | using NodaTime.Text;
9 |
10 | namespace Gnomeshade.Avalonia.Core;
11 |
12 | /// Converts a binding value of type .
13 | public sealed class LocalDateConverter : NodaTimeValueConverter
14 | {
15 | ///
16 | protected override LocalDate TemplateValue { get; } = new(2000, 12, 31);
17 |
18 | ///
19 | protected override LocalDatePattern GetPattern(CultureInfo culture) =>
20 | LocalDatePattern.Create("d", culture);
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/Calculations/ICalculationFunction.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections.Generic;
6 |
7 | using LiveChartsCore.Defaults;
8 |
9 | namespace Gnomeshade.Avalonia.Core.Reports.Calculations;
10 |
11 | /// A function that calculates the value to display for a purchase.
12 | public interface ICalculationFunction
13 | {
14 | /// Gets the name of the calculation.
15 | string Name { get; }
16 |
17 | internal decimal Calculate(CalculableValue value);
18 |
19 | internal IEnumerable Update(IReadOnlyCollection points);
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/UpsertedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | namespace Gnomeshade.Avalonia.Core;
8 |
9 | /// Event arguments for event.
10 | public sealed class UpsertedEventArgs : EventArgs
11 | {
12 | /// Initializes a new instance of the class.
13 | /// The id of the upserted entity.
14 | public UpsertedEventArgs(Guid id)
15 | {
16 | Id = id;
17 | }
18 |
19 | /// Gets the id of the upserted entity.
20 | public Guid Id { get; }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/CategoryView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | /// An overview of of all categories.
14 | public sealed partial class CategoryView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public CategoryView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Importing/TransactionReference.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Gnomeshade.WebApi.Models.Transactions;
6 |
7 | using JetBrains.Annotations;
8 |
9 | namespace Gnomeshade.WebApi.Models.Importing;
10 |
11 | /// A reference to an transaction that was used during import.
12 | [PublicAPI]
13 | public sealed record TransactionReference
14 | {
15 | /// Whether or not the transaction was created during import.
16 | public bool Created { get; set; }
17 |
18 | /// The referenced transaction.
19 | public Transaction Transaction { get; set; } = null!;
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Accounts/AccountFilterView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Accounts;
10 |
11 | namespace Gnomeshade.Desktop.Views.Accounts;
12 |
13 | ///
14 | public sealed partial class AccountFilterView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public AccountFilterView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/ProductFilterView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | ///
14 | public sealed partial class ProductFilterView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ProductFilterView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Loans/LoanView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Loans;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Loans;
12 |
13 | ///
14 | public sealed partial class LoanView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public LoanView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/DateAxis.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using LiveChartsCore.SkiaSharpView;
8 |
9 | namespace Gnomeshade.Avalonia.Core.Reports;
10 |
11 | internal static class DateAxis
12 | {
13 | private static double DateStep { get; } = TimeSpan.FromDays(30.4375).Ticks;
14 |
15 | internal static Axis GetXAxis() => new() { Labeler = Date, UnitWidth = DateStep, MinStep = DateStep };
16 |
17 | private static string Date(double value)
18 | {
19 | var ticks = Math.Clamp((long)value, DateTime.MinValue.Ticks, DateTime.MaxValue.Ticks);
20 | return new DateTime(ticks).ToString("yyyy MM");
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Counterparties/CounterpartyFilter.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 |
7 | using Gnomeshade.Avalonia.Core;
8 | using Gnomeshade.Avalonia.Core.Counterparties;
9 |
10 | namespace Gnomeshade.Desktop.Views.Counterparties;
11 |
12 | ///
13 | public sealed partial class CounterpartyFilterView : UserControl, IView
14 | {
15 | /// Initializes a new instance of the class.
16 | public CounterpartyFilterView()
17 | {
18 | InitializeComponent();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/ActivityScope.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 |
8 | namespace Gnomeshade.Avalonia.Core;
9 |
10 | internal readonly struct ActivityScope : IDisposable
11 | {
12 | private readonly ICollection _scopes;
13 |
14 | public ActivityScope(ICollection scopes, string name)
15 | {
16 | _scopes = scopes;
17 | Name = name;
18 |
19 | _scopes.Add(this);
20 | }
21 |
22 | /// Gets the name of the activity.
23 | public string Name { get; }
24 |
25 | ///
26 | public void Dispose() => _scopes.Remove(this);
27 | }
28 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Reports/Calculations/TotalPrice.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections.Generic;
6 |
7 | using LiveChartsCore.Defaults;
8 |
9 | namespace Gnomeshade.Avalonia.Core.Reports.Calculations;
10 |
11 | /// Calculates the purchase price as is.
12 | public sealed class TotalPrice : ICalculationFunction
13 | {
14 | ///
15 | public string Name => "Total Price";
16 |
17 | decimal ICalculationFunction.Calculate(CalculableValue value) => value.Purchase.Price;
18 |
19 | IEnumerable ICalculationFunction.Update(IReadOnlyCollection points) => points;
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/UnitCreationView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | ///
14 | public sealed partial class UnitCreationView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public UnitCreationView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.WebApi.Tests.Integration.Oidc/WebserverSetup.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Threading.Tasks;
6 |
7 | [assembly: Parallelizable(ParallelScope.Children)]
8 |
9 | namespace Gnomeshade.WebApi.Tests.Integration.Oidc;
10 |
11 | [SetUpFixture]
12 | public static class WebserverSetup
13 | {
14 | internal static readonly KeycloakFixture KeycloakFixture = new();
15 |
16 | [OneTimeSetUp]
17 | public static async Task OneTimeSetUp()
18 | {
19 | await KeycloakFixture.Initialize();
20 | }
21 |
22 | [OneTimeTearDown]
23 | public static async Task OneTimeTearDown()
24 | {
25 | await KeycloakFixture.DisposeAsync();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Configuration/PreferencesView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Configuration;
10 |
11 | namespace Gnomeshade.Desktop.Views.Configuration;
12 |
13 | ///
14 | public sealed partial class PreferencesView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public PreferencesView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/MainWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | #if DEBUG
6 | using Avalonia;
7 | #endif
8 | using Avalonia.Controls;
9 | using Avalonia.Markup.Xaml;
10 |
11 | using Gnomeshade.Avalonia.Core;
12 |
13 | namespace Gnomeshade.Desktop.Views;
14 |
15 | ///
16 | public sealed partial class MainWindow : Window, IView
17 | {
18 | /// Initializes a new instance of the class.
19 | public MainWindow()
20 | {
21 | AvaloniaXamlLoader.Load(this);
22 |
23 | #if DEBUG
24 | this.AttachDevTools();
25 | #endif
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Projects/ProjectUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Projects;
10 |
11 | namespace Gnomeshade.Desktop.Views.Projects;
12 |
13 | ///
14 | public sealed partial class ProjectUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ProjectUpsertionView() => AvaloniaXamlLoader.Load(this);
18 | }
19 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Reports/BalanceReportView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Reports;
10 |
11 | namespace Gnomeshade.Desktop.Views.Reports;
12 |
13 | ///
14 | public sealed partial class BalanceReportView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public BalanceReportView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Reports/ProductReportView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Reports;
10 |
11 | namespace Gnomeshade.Desktop.Views.Reports;
12 |
13 | ///
14 | public sealed partial class ProductReportView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ProductReportView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/TransactionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions;
12 |
13 | ///
14 | public sealed partial class TransactionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public TransactionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.WebApi.Client.Tests/RoutesTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using NodaTime;
8 |
9 | namespace Gnomeshade.WebApi.Client.Tests;
10 |
11 | public class RoutesTests
12 | {
13 | [Test]
14 | public void AccountUri_ShouldFormatGuidWithoutSeparators()
15 | {
16 | Routes.Accounts.IdUri(Guid.Empty).Should().Be("v1.0/Accounts/00000000000000000000000000000000");
17 | }
18 |
19 | [TestCaseSource(typeof(TransactionUriTestCaseSource))]
20 | public void TransactionUri_ShouldReturnExpected(Interval interval, string expectedUri)
21 | {
22 | Routes.Transactions.DateRangeUri(interval).Should().Be(expectedUri);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Entities/Abstractions/Entity.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using NodaTime;
8 |
9 | namespace Gnomeshade.Data.Entities.Abstractions;
10 |
11 | /// Base class for all entities.
12 | public abstract record Entity : IEntity
13 | {
14 | ///
15 | public Guid Id { get; init; }
16 |
17 | ///
18 | public Instant CreatedAt { get; init; }
19 |
20 | ///
21 | public Guid CreatedByUserId { get; init; }
22 |
23 | ///
24 | public Instant? DeletedAt { get; set; }
25 |
26 | ///
27 | public Guid? DeletedByUserId { get; set; }
28 | }
29 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/LoanPayment/Delete.sql:
--------------------------------------------------------------------------------
1 | WITH accessable AS
2 | (SELECT loan_payments.id
3 | FROM loan_payments
4 | INNER JOIN loans2 ON loan_payments.loan_id = loans2.id
5 | LEFT JOIN owners ON loans2.owner_id = owners.id
6 | LEFT JOIN ownerships ON owners.id = ownerships.owner_id
7 | LEFT JOIN access ON ownerships.access_id = access.id
8 | WHERE (ownerships.user_id = @userId
9 | AND (access.normalized_name = 'DELETE' OR access.normalized_name = 'OWNER')
10 | AND loans2.deleted_at IS NULL)
11 | AND loan_payments.deleted_at IS NULL
12 | AND loan_payments.id = @id)
13 |
14 | UPDATE loan_payments
15 | SET deleted_at = CURRENT_TIMESTAMP,
16 | deleted_by_user_id = @userId
17 | FROM accessable
18 | WHERE loan_payments.id IN (SELECT id FROM accessable);
19 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Reports/CategoryReportView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Reports;
10 |
11 | namespace Gnomeshade.Desktop.Views.Reports;
12 |
13 | ///
14 | public sealed partial class CategoryReportView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public CategoryReportView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/Project/Update.sql:
--------------------------------------------------------------------------------
1 | WITH accessable AS
2 | (SELECT projects.id
3 | FROM projects
4 | INNER JOIN owners ON owners.id = projects.owner_id
5 | INNER JOIN ownerships ON owners.id = ownerships.owner_id
6 | INNER JOIN access ON access.id = ownerships.access_id
7 | WHERE ownerships.user_id = @ModifiedByUserId
8 | AND (access.normalized_name = 'WRITE' OR access.normalized_name = 'OWNER')
9 | AND projects.deleted_at IS NULL
10 | AND projects.id = @Id)
11 |
12 | UPDATE projects
13 | SET modified_at = CURRENT_TIMESTAMP,
14 | modified_by_user_id = @ModifiedByUserId,
15 | name = @Name,
16 | normalized_name = upper(@Name),
17 | parent_project_id = @ParentProjectId
18 | FROM accessable
19 | WHERE projects.id IN (SELECT id FROM accessable);
20 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/Transfer/Insert.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO transfers
2 | (id,
3 | owner_id,
4 | created_by_user_id,
5 | modified_by_user_id,
6 | transaction_id,
7 | source_amount,
8 | source_account_id,
9 | target_amount,
10 | target_account_id,
11 | bank_reference,
12 | external_reference,
13 | internal_reference,
14 | "order",
15 | booked_at,
16 | valued_at)
17 | VALUES
18 | (@Id,
19 | @OwnerId,
20 | @CreatedByUserId,
21 | @ModifiedByUserId,
22 | @TransactionId,
23 | @SourceAmount,
24 | @SourceAccountId,
25 | @TargetAmount,
26 | @TargetAccountId,
27 | @BankReference,
28 | @ExternalReference,
29 | @InternalReference,
30 | @Order,
31 | @BookedAt,
32 | @ValuedAt)
33 | RETURNING id;
34 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Accesses/OwnerUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Accesses;
10 |
11 | namespace Gnomeshade.Desktop.Views.Accesses;
12 |
13 | ///
14 | public sealed partial class OwnerUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public OwnerUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Counterparties/CounterpartyView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Counterparties;
10 |
11 | namespace Gnomeshade.Desktop.Views.Counterparties;
12 |
13 | ///
14 | public sealed partial class CounterpartyView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public CounterpartyView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Purchases/PurchaseView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Purchases;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Purchases;
12 |
13 | ///
14 | public sealed partial class PurchaseView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public PurchaseView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Transfers/TransferView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Transfers;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Transfers;
12 |
13 | ///
14 | public sealed partial class TransferView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public TransferView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/LocalDateTimeConverter.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Globalization;
6 |
7 | using NodaTime;
8 | using NodaTime.Text;
9 |
10 | namespace Gnomeshade.Avalonia.Core;
11 |
12 | /// Converts a binding value of type .
13 | public sealed class LocalDateTimeConverter : NodaTimeValueConverter
14 | {
15 | ///
16 | protected override LocalDateTime TemplateValue { get; } = new(2000, 12, 31, 13, 20);
17 |
18 | ///
19 | protected override LocalDateTimePattern GetPattern(CultureInfo culture) =>
20 | LocalDateTimePattern.Create("g", culture);
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Repositories/Queries/Ownership/Delete.sql:
--------------------------------------------------------------------------------
1 | WITH accessable AS
2 | (SELECT ownerships.id AS Id,
3 | ownerships.created_at CreatedAt,
4 | ownerships.created_by_user_id AS CreatedByUserId,
5 | ownerships.owner_id OwnerId,
6 | ownerships.user_id UserId,
7 | ownerships.access_id AccessId
8 | FROM ownerships ownerships
9 | INNER JOIN owners on owners.id = ownerships.owner_id
10 | INNER JOIN ownerships o on o.owner_id = owners.id
11 | INNER JOIN access on access.id = o.access_id
12 | WHERE (o.user_id = @userId AND (access.normalized_name = 'DELETE' OR access.normalized_name = 'OWNER'))
13 | AND ownerships.id = @id)
14 |
15 | DELETE
16 | FROM ownerships
17 | WHERE ownerships.id in (SELECT id from accessable);
18 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Client/NewRequisition.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | namespace Gnomeshade.WebApi.Client;
8 |
9 | /// User approval is needed in order to access the account.
10 | public sealed class NewRequisition : ImportResult
11 | {
12 | /// Initializes a new instance of the class.
13 | /// The URI for the approval page.
14 | public NewRequisition(Uri requisitionUri)
15 | {
16 | RequisitionUri = requisitionUri;
17 | }
18 |
19 | /// Gets the URI for the approval page.
20 | public Uri RequisitionUri { get; }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Accounts/AccountUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Accounts;
10 |
11 | namespace Gnomeshade.Desktop.Views.Accounts;
12 |
13 | ///
14 | public sealed partial class AccountUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public AccountUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/ProductUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | ///
14 | public sealed partial class ProductUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ProductUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Accounts/Balance.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | namespace Gnomeshade.WebApi.Models.Accounts;
8 |
9 | /// Account balance in a single currency.
10 | public sealed record Balance
11 | {
12 | /// The id of the for which the balance was calculated for.
13 | public Guid AccountInCurrencyId { get; set; }
14 |
15 | /// The total amount withdrawn from the account.
16 | public decimal SourceAmount { get; set; }
17 |
18 | /// The total amount deposited to the account.
19 | public decimal TargetAmount { get; set; }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Entities/Abstractions/IModifiableEntity.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using NodaTime;
8 |
9 | namespace Gnomeshade.Data.Entities.Abstractions;
10 |
11 | /// Represents an entity that can be modified.
12 | ///
13 | public interface IModifiableEntity : IEntity
14 | {
15 | /// Gets or sets the timestamp of the last modification of this entity.
16 | Instant ModifiedAt { get; set; }
17 |
18 | /// Gets or sets the id of the user which last modified this entity.
19 | ///
20 | public Guid ModifiedByUserId { get; set; }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Client/Results/RequiresRegistration.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | namespace Gnomeshade.WebApi.Client.Results;
8 |
9 | /// User is not registered.
10 | public sealed class RequiresRegistration : ExternalLoginResult
11 | {
12 | /// Initializes a new instance of the class.
13 | /// The uri the the registration page.
14 | public RequiresRegistration(Uri redirectUri)
15 | {
16 | RedirectUri = redirectUri;
17 | }
18 |
19 | /// Gets the uri the the registration page.
20 | public Uri RedirectUri { get; }
21 | }
22 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | gnomeshade:
3 | image: ghcr.io/vmelnalksnis/gnomeshade:0.8.7
4 | restart: unless-stopped
5 | ports:
6 | - "8080:8080"
7 | volumes:
8 | - gnomeshade_data:/data
9 | environment:
10 | Admin__Password: "Password1!"
11 | Database__Provider: "PostgreSQL"
12 | ConnectionStrings__Gnomeshade: "Server = database; Port = 5432; Database = database; User Id = postgres; Password = Password2!; Maximum Pool Size = 20"
13 | depends_on:
14 | database:
15 | condition: service_started
16 |
17 | database:
18 | image: postgres:15.8-bookworm
19 | restart: unless-stopped
20 | volumes:
21 | - postgresql_data:/var/lib/postgresql/data
22 | environment:
23 | POSTGRES_PASSWORD: Password2!
24 |
25 | volumes:
26 | gnomeshade_data:
27 | postgresql_data:
28 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Commands/CommandBase.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 | using System.Windows.Input;
7 |
8 | namespace Gnomeshade.Avalonia.Core.Commands;
9 |
10 | ///
11 | public abstract class CommandBase : ICommand
12 | {
13 | ///
14 | public event EventHandler? CanExecuteChanged;
15 |
16 | ///
17 | public abstract bool CanExecute(object? parameter);
18 |
19 | ///
20 | public abstract void Execute(object? parameter);
21 |
22 | /// Invokes .
23 | public void InvokeExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
24 | }
25 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Products/CategoryUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Products;
10 |
11 | namespace Gnomeshade.Desktop.Views.Products;
12 |
13 | ///
14 | public sealed partial class CategoryUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public CategoryUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Links/LinkUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Links;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Links;
12 |
13 | ///
14 | public sealed partial class LinkUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public LinkUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/Configuration/Options/OAuthProviderOptions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.ComponentModel.DataAnnotations;
6 |
7 | using Microsoft.AspNetCore.Authentication.OAuth;
8 |
9 | namespace Gnomeshade.WebApi.Configuration.Options;
10 |
11 | /// Options for configuring an OAuth provider.
12 | public sealed class OAuthProviderOptions
13 | {
14 | internal const string ProviderSectionName = "OAuth";
15 |
16 | ///
17 | [Required]
18 | public string ClientId { get; init; } = null!;
19 |
20 | ///
21 | public string? ClientSecret { get; init; }
22 | }
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Entities/BalanceEntity.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | namespace Gnomeshade.Data.Entities;
8 |
9 | /// Account balance in a single currency.
10 | public sealed class BalanceEntity
11 | {
12 | /// Gets the id of the for which the balance was calculated for.
13 | public Guid AccountInCurrencyId { get; init; }
14 |
15 | /// Gets the total amount withdrawn from the account.
16 | public decimal SourceAmount { get; init; }
17 |
18 | /// Gets the total amount deposited to the account.
19 | public decimal TargetAmount { get; init; }
20 | }
21 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Importing/Iso20022Report.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.ComponentModel.DataAnnotations;
6 |
7 | using JetBrains.Annotations;
8 |
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace Gnomeshade.WebApi.Models.Importing;
12 |
13 | /// An ISO20022 report.
14 | [PublicAPI]
15 | public sealed record Iso20022Report
16 | {
17 | /// The ISO20022 report content.
18 | [Required]
19 | public IFormFile Report { get; set; } = null!;
20 |
21 | /// The timezone which will be assumed for all unspecified dates in the report.
22 | [Required]
23 | public string TimeZone { get; set; } = null!;
24 | }
25 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/Areas/Identity/Pages/Error.cshtml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Diagnostics;
6 |
7 | using Microsoft.AspNetCore.Authorization;
8 | using Microsoft.AspNetCore.Mvc;
9 | using Microsoft.AspNetCore.Mvc.RazorPages;
10 |
11 | namespace Gnomeshade.WebApi.Areas.Identity.Pages;
12 |
13 | [AllowAnonymous]
14 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
15 | public sealed class Error : PageModel
16 | {
17 | public string? RequestId { get; set; }
18 |
19 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
20 |
21 | public void OnGet() => RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
22 | }
23 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Data/Entities/UserEntity.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using Gnomeshade.Data.Entities.Abstractions;
8 |
9 | using NodaTime;
10 |
11 | namespace Gnomeshade.Data.Entities;
12 |
13 | /// A user within the context of this application.
14 | public sealed record UserEntity : Entity, IModifiableEntity
15 | {
16 | ///
17 | public Instant ModifiedAt { get; set; }
18 |
19 | ///
20 | public Guid ModifiedByUserId { get; set; }
21 |
22 | /// Gets or sets the id of the which represents this user in transactions.
23 | public Guid CounterpartyId { get; set; }
24 | }
25 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model Disable2Fa
3 | @{
4 | ViewData["Title"] = "Disable two-factor authentication (2FA)";
5 | ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
6 | }
7 |
8 |
9 |
@ViewData["Title"]
10 |
11 |
12 |
13 | This action only disables 2FA.
14 |
15 |
16 | Disabling 2FA does not change the keys used in authenticator apps. If you wish to change the key
17 | used in an authenticator app you should reset your authenticator keys.
18 |
19 |
20 |
21 |
22 |
25 |
26 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.AspNetCore.Mvc.RazorPages;
7 |
8 | namespace Gnomeshade.WebApi.Areas.Identity.Pages.Account.Manage;
9 |
10 | public sealed class ShowRecoveryCodes : PageModel
11 | {
12 | [TempData]
13 | public string[]? RecoveryCodes { get; set; }
14 |
15 | [TempData]
16 | public string? StatusMessage { get; set; }
17 |
18 | public IActionResult OnGet()
19 | {
20 | if (RecoveryCodes is null || RecoveryCodes.Length == 0)
21 | {
22 | return RedirectToPage("./TwoFactorAuthentication");
23 | }
24 |
25 | return Page();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/Configuration/Options/AdminOptions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.ComponentModel.DataAnnotations;
6 |
7 | namespace Gnomeshade.WebApi.Configuration.Options;
8 |
9 | /// Options for configuring the initial admin user.
10 | public sealed class AdminOptions
11 | {
12 | internal const string SectionName = "Admin";
13 |
14 | /// Gets or sets the name of the initial admin user. Defaults to 'Admin'.
15 | [Required]
16 | public string Username { get; set; } = "Admin";
17 |
18 | /// Gets or sets the password of the initial admin user.
19 | [Required]
20 | public string Password { get; set; } = null!;
21 | }
22 |
--------------------------------------------------------------------------------
/tests/Gnomeshade.WebApi.Tests/V1/Transactions/OptionalTimeRangeTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.ComponentModel.DataAnnotations;
6 |
7 | using Gnomeshade.WebApi.V1.Transactions;
8 |
9 | namespace Gnomeshade.WebApi.Tests.V1.Transactions;
10 |
11 | public class OptionalTimeRangeTests
12 | {
13 | [TestCaseSource(typeof(ValidateTestCaseSource))]
14 | public void Validate_ShouldReturnExpected(
15 | OptionalTimeRange optionalTimeRange,
16 | int expectedResultCount)
17 | {
18 | var validationContext = new ValidationContext(optionalTimeRange);
19 |
20 | optionalTimeRange
21 | .Validate(validationContext)
22 | .Should()
23 | .HaveCount(expectedResultCount);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Counterparties/CounterpartyMergeView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Counterparties;
10 |
11 | namespace Gnomeshade.Desktop.Views.Counterparties;
12 |
13 | ///
14 | public sealed partial class CounterpartyMergeView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public CounterpartyMergeView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Loans/LoanUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Loans;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Loans;
12 |
13 | ///
14 | public sealed partial class LoanUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public LoanUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/V1/Importing/Paperless/IPaperlessDocumentParser.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Collections.Generic;
6 |
7 | using VMelnalksnis.PaperlessDotNet.Documents;
8 |
9 | namespace Gnomeshade.WebApi.V1.Importing.Paperless;
10 |
11 | /// Parses information from Paperless s.
12 | public interface IPaperlessDocumentParser
13 | {
14 | /// Parses purchase texts from a paperless .
15 | /// The document from which to parse purchases.
16 | /// All purchases from .
17 | List ParsePurchases(Document document);
18 | }
19 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Controls/TransactionFilterView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Controls;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Controls;
12 |
13 | ///
14 | public sealed partial class TransactionFilterView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public TransactionFilterView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/Controls/TransactionSummaryView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions.Controls;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions.Controls;
12 |
13 | ///
14 | public sealed partial class TransactionSummaryView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public TransactionSummaryView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Configuration/ApplicationSettingsView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Configuration;
10 |
11 | namespace Gnomeshade.Desktop.Views.Configuration;
12 |
13 | ///
14 | public sealed partial class ApplicationSettingsView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ApplicationSettingsView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Configuration/ConfigurationWizardView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Configuration;
10 |
11 | namespace Gnomeshade.Desktop.Views.Configuration;
12 |
13 | ///
14 | public sealed partial class ConfigurationWizardView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public ConfigurationWizardView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Avalonia.Core/Authentication/IGnomeshadeProtocolHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace Gnomeshade.Avalonia.Core.Authentication;
9 |
10 | /// Handles requests made in the gnomeshade protocol.
11 | public interface IGnomeshadeProtocolHandler
12 | {
13 | /// Gets the content of a gnomeshade protocol request.
14 | /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
15 | /// The request content.
16 | Task GetRequestContent(CancellationToken cancellationToken = default);
17 | }
18 |
--------------------------------------------------------------------------------
/source/Gnomeshade.Desktop/Views/Transactions/TransactionUpsertionView.axaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using Avalonia.Controls;
6 | using Avalonia.Markup.Xaml;
7 |
8 | using Gnomeshade.Avalonia.Core;
9 | using Gnomeshade.Avalonia.Core.Transactions;
10 |
11 | namespace Gnomeshade.Desktop.Views.Transactions;
12 |
13 | ///
14 | public sealed partial class TransactionUpsertionView : UserControl, IView
15 | {
16 | /// Initializes a new instance of the class.
17 | public TransactionUpsertionView()
18 | {
19 | AvaloniaXamlLoader.Load(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Client/RefreshTokenChangedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | namespace Gnomeshade.WebApi.Client;
8 |
9 | /// for the event.
10 | public sealed class RefreshTokenChangedEventArgs : EventArgs
11 | {
12 | /// Initializes a new instance of the class.
13 | /// The new refresh token value.
14 | public RefreshTokenChangedEventArgs(string token)
15 | {
16 | Token = token;
17 | }
18 |
19 | /// Gets the new refresh token value.
20 | public string Token { get; }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi.Models/Owners/Ownership.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Valters Melnalksnis
2 | // Licensed under the GNU Affero General Public License v3.0 or later.
3 | // See LICENSE.txt file in the project root for full license information.
4 |
5 | using System;
6 |
7 | using JetBrains.Annotations;
8 |
9 | namespace Gnomeshade.WebApi.Models.Owners;
10 |
11 | /// Access rights for a user to a group of resources.
12 | [PublicAPI]
13 | public sealed record Ownership
14 | {
15 | /// The id of the ownership.
16 | public Guid Id { get; set; }
17 |
18 | /// The id of the owner.
19 | public Guid OwnerId { get; set; }
20 |
21 | /// The id of the user that has the access.
22 | public Guid UserId { get; set; }
23 |
24 | /// The id of the access level.
25 | public Guid AccessId { get; set; }
26 | }
27 |
--------------------------------------------------------------------------------
/source/Gnomeshade.WebApi/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model ShowRecoveryCodes
3 | @{
4 | ViewData["Title"] = "Recovery codes";
5 | ViewData["ActivePage"] = "TwoFactorAuthentication";
6 | }
7 |
8 |
9 |
@ViewData["Title"]
10 |
11 |
12 | Put these codes in a safe place.
13 |
14 |
15 | If you lose your device and don't have the recovery codes you will lose access to your account.
16 |