Skip to content

Commit

Permalink
Need to rethink my account-account group relation based on account cl…
Browse files Browse the repository at this point in the history
…assification addition => next time think before !
  • Loading branch information
fdonnet committed Oct 19, 2023
1 parent 531ea7d commit 6d783f9
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Ubik.ApiService.Common.Exceptions;
using static Ubik.Accounting.Api.Features.AccountGroups.Queries.GetAllAccountGroups;
using static Ubik.Accounting.Api.Features.AccountGroups.Queries.GetAccountGroup;
using static Ubik.Accounting.Api.Features.Accounts.Commands.AddAccount;

namespace Ubik.Accounting.Api.Features.AccountGroups
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class AccountGroupsController : ControllerBase
{
private readonly IMediator _mediator;

public AccountGroupsController(IMediator mediator)
{
_mediator = mediator;
}

[Authorize(Roles = "ubik_accounting_accountgroup_read")]
[HttpGet]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<IEnumerable<GetAllAccountGroupsResult>>> GetAll()
{
var results = await _mediator.Send(new GetAllAccountGroupsQuery());
return Ok(results);
}

[Authorize(Roles = "ubik_accounting_accountgroup_read")]
[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(CustomProblemDetails), 400)]
[ProducesResponseType(typeof(CustomProblemDetails), 404)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<GetAccountGroupResult>> Get(Guid id)
{
var result = await _mediator.Send(new GetAccountGroupQuery() { Id = id });
return Ok(result);
}

[Authorize(Roles = "ubik_accounting_accountgroup_write")]
[HttpPost]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(CustomProblemDetails), 400)]
[ProducesResponseType(typeof(CustomProblemDetails), 409)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<AddAccountResult>> Add(AddAccountCommand addAccountCommand)
{
var result = await _mediator.Send(addAccountCommand);
return CreatedAtAction(nameof(Get), new { id = result.Id }, result);
}

}
}
14 changes: 8 additions & 6 deletions src/Ubik.Accounting.Api/Features/Accounts/AccountsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public AccountsController(IMediator mediator)
[HttpGet]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<IEnumerable<GetAllAccountsResult>>> GetAccounts()
public async Task<ActionResult<IEnumerable<GetAllAccountsResult>>> GetAll()
{
var results = await _mediator.Send(new GetAllAccountsQuery());
return Ok(results);
Expand All @@ -35,9 +35,10 @@ public async Task<ActionResult<IEnumerable<GetAllAccountsResult>>> GetAccounts()
[Authorize(Roles = "ubik_accounting_account_read")]
[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(CustomProblemDetails), 400)]
[ProducesResponseType(typeof(CustomProblemDetails), 404)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<GetAccountResult>> GetAccount(Guid id)
public async Task<ActionResult<GetAccountResult>> Get(Guid id)
{
var result = await _mediator.Send(new GetAccountQuery() { Id = id });
return Ok(result);
Expand All @@ -47,12 +48,13 @@ public async Task<ActionResult<GetAccountResult>> GetAccount(Guid id)
[HttpPost]
[ProducesResponseType(201)]
[ProducesResponseType(typeof(CustomProblemDetails), 400)]
[ProducesResponseType(typeof(CustomProblemDetails), 404)]
[ProducesResponseType(typeof(CustomProblemDetails), 409)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<AddAccountResult>> AddAccount(AddAccountCommand addAccountCommand)
public async Task<ActionResult<AddAccountResult>> Add(AddAccountCommand addAccountCommand)
{
var result = await _mediator.Send(addAccountCommand);
return CreatedAtAction(nameof(GetAccount), new { id = result.Id }, result);
return CreatedAtAction(nameof(Get), new { id = result.Id }, result);
}

[Authorize(Roles = "ubik_accounting_account_write")]
Expand All @@ -62,7 +64,7 @@ public async Task<ActionResult<AddAccountResult>> AddAccount(AddAccountCommand a
[ProducesResponseType(typeof(CustomProblemDetails), 404)]
[ProducesResponseType(typeof(CustomProblemDetails), 409)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<UpdateAccountResult>> UpdateAccount(Guid id, UpdateAccountCommand updateAccountCommand)
public async Task<ActionResult<UpdateAccountResult>> Update(Guid id, UpdateAccountCommand updateAccountCommand)
{
updateAccountCommand.Id = id;
var accountResult = await _mediator.Send(updateAccountCommand);
Expand All @@ -75,7 +77,7 @@ public async Task<ActionResult<UpdateAccountResult>> UpdateAccount(Guid id, Upda
[ProducesResponseType(typeof(CustomProblemDetails), 400)]
[ProducesResponseType(typeof(CustomProblemDetails), 404)]
[ProducesResponseType(typeof(CustomProblemDetails), 500)]
public async Task<ActionResult<UpdateAccountResult>> UpdateAccount(Guid id)
public async Task<ActionResult<UpdateAccountResult>> Update(Guid id)
{
await _mediator.Send(new DeleteAccountCommand() { Id = id});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using FluentAssertions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Ubik.Accounting.Api.Data.Init;
using static Ubik.Accounting.Api.Features.Accounts.Queries.GetAllAccounts;
using Ubik.Accounting.Api.Tests.Integration.Auth;
using static Ubik.Accounting.Api.Features.AccountGroups.Queries.GetAllAccountGroups;

namespace Ubik.Accounting.Api.Tests.Integration.Features.AccountGroups
{
public class AccountGroupsController_Test : BaseIntegrationTest
{
private readonly BaseValuesForAccounts _testValuesForAccounts;
private readonly BaseValuesForAccountGroups _testValuesForAccountGroups;

public AccountGroupsController_Test(IntegrationTestWebAppFactory factory) : base(factory)
{
_testValuesForAccounts = new BaseValuesForAccounts();
_testValuesForAccountGroups = new BaseValuesForAccountGroups();
}

[Fact]
public async Task GetAll_AccountGroups_Ok()
{
//Arrange
var httpClient = Factory.CreateDefaultClient();

var accessToken = await AuthHelper.GetAccessTokenReadOnly();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

//Act
var response = await httpClient.GetAsync("/AccountGroups");
var result = await response.Content.ReadFromJsonAsync<IEnumerable<GetAllAccountGroupsResult>>();

//Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
result.Should()
.NotBeNull()
.And.AllBeOfType<GetAllAccountGroupsResult>(); ;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

namespace Ubik.Accounting.Api.Tests.Integration.Features.Accounts
{
public class AccountController_Test : BaseIntegrationTest
public class AccountsController_Test : BaseIntegrationTest
{
private readonly BaseValuesForAccounts _testValuesForAccounts;
private readonly BaseValuesForAccountGroups _testValuesForAccountGroups;

public AccountController_Test(IntegrationTestWebAppFactory factory) : base(factory)
public AccountsController_Test(IntegrationTestWebAppFactory factory) : base(factory)
{
_testValuesForAccounts = new BaseValuesForAccounts();
_testValuesForAccountGroups = new BaseValuesForAccountGroups();
Expand Down Expand Up @@ -212,6 +212,34 @@ public async Task Post_ProblemDetails_AccountCodeExist()
.And.Match<CustomProblemDetails>(x => x.Errors.First().Code == "ACCOUNT_ALREADY_EXISTS");
}

[Fact]
public async Task Post_ProblemDetails_AccountGroupNotFound()
{
//Arrange
var httpClient = Factory.CreateDefaultClient();

var accessToken = await AuthHelper.GetAccessTokenReadWrite();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

//Act
var fakeAc = FakeGenerator.GenerateAccounts(1, _testValuesForAccountGroups.AccountGroupId1).First();
var fake = fakeAc.ToAddAccountResult();
fake.AccountGroupId = Guid.NewGuid();

var postAccountJson = JsonSerializer.Serialize(fake);
var content = new StringContent(postAccountJson.ToString(), Encoding.UTF8, "application/json");

var response = await httpClient.PostAsync($"/Accounts", content);
var result = await response.Content.ReadFromJsonAsync<CustomProblemDetails>();

//Assert
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
result.Should()
.NotBeNull()
.And.BeOfType<CustomProblemDetails>()
.And.Match<CustomProblemDetails>(x => x.Errors.First().Code == "ACCOUNTGROUP_NOT_FOUND_FOR_ACCOUNT");
}

[Fact]
public async Task Post_ProblemDetails_AccountEmptyFields()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
docker exec -it eebb44610817976b605687339482236d9daa75655a6643405c6851b1e8a9e8e3 bash
/opt/keycloak/bin/kc.sh export --dir /opt/keycloak/data/import --realm ubik --users realm_file
docker cp fb9f41b9b5cf1c19cbd0b31ebc117ffe33f31f5fd92991be96012f2068444fb7:/opt/keycloak/data/import/ubik-realm.json ./ubik-realm.json
docker cp 8c57e0eaf44969057329d9e87823ca3b1e3d62f4d1b55219911c307085b01550:/opt/keycloak/data/import/ubik-realm.json ./ubik-realm.json

docker cp ./ubik-realm.json eebb44610817976b605687339482236d9daa75655a6643405c6851b1e8a9e8e3:/opt/keycloak/data/import/ubik-realm.json

Expand Down
51 changes: 37 additions & 14 deletions tests/Ubik.Accounting.Api.Tests.Integration/import/ubik-realm.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"defaultSignatureAlgorithm" : "RS256",
"revokeRefreshToken" : false,
"refreshTokenMaxReuse" : 0,
"accessTokenLifespan" : 172800,
"accessTokenLifespanForImplicitFlow" : 172800,
"accessTokenLifespan" : 300,
"accessTokenLifespanForImplicitFlow" : 900,
"ssoSessionIdleTimeout" : 1800,
"ssoSessionMaxLifespan" : 36000,
"ssoSessionIdleTimeoutRememberMe" : 0,
Expand Down Expand Up @@ -52,6 +52,14 @@
"clientRole" : false,
"containerId" : "2ae66de8-e60f-4e29-9bfc-cbb79647c432",
"attributes" : { }
}, {
"id" : "24bf1016-7f21-406d-88a3-3d6af89ca534",
"name" : "ubik_accounting_accountgroup_read",
"description" : "",
"composite" : false,
"clientRole" : false,
"containerId" : "2ae66de8-e60f-4e29-9bfc-cbb79647c432",
"attributes" : { }
}, {
"id" : "9668e628-8052-41e0-8d38-06d7576bf452",
"name" : "ubik_accounting_account_read",
Expand Down Expand Up @@ -90,6 +98,14 @@
"clientRole" : false,
"containerId" : "2ae66de8-e60f-4e29-9bfc-cbb79647c432",
"attributes" : { }
}, {
"id" : "4abcbfef-3156-4489-8f9c-df2c32a27455",
"name" : "ubik_accounting_accountgroup_write",
"description" : "",
"composite" : false,
"clientRole" : false,
"containerId" : "2ae66de8-e60f-4e29-9bfc-cbb79647c432",
"attributes" : { }
} ],
"client" : {
"realm-management" : [ {
Expand Down Expand Up @@ -362,23 +378,23 @@
"name" : "ubik_accounting_read",
"path" : "/ubik_accounting_read",
"attributes" : { },
"realmRoles" : [ "ubik_accounting_account_read" ],
"realmRoles" : [ "ubik_accounting_accountgroup_read", "ubik_accounting_account_read" ],
"clientRoles" : { },
"subGroups" : [ ]
}, {
"id" : "37c3fbdf-65ee-47f3-9bad-8b2241547a0d",
"name" : "ubik_accounting_readwrite",
"path" : "/ubik_accounting_readwrite",
"attributes" : { },
"realmRoles" : [ "ubik_accounting_account_read", "ubik_accounting_account_write" ],
"realmRoles" : [ "ubik_accounting_accountgroup_read", "ubik_accounting_account_read", "ubik_accounting_account_write", "ubik_accounting_accountgroup_write" ],
"clientRoles" : { },
"subGroups" : [ ]
}, {
"id" : "bb907963-d332-4284-97a8-3bdd3dff9328",
"name" : "ubik_accounting_write",
"path" : "/ubik_accounting_write",
"attributes" : { },
"realmRoles" : [ "ubik_accounting_account_write" ],
"realmRoles" : [ "ubik_accounting_account_write", "ubik_accounting_accountgroup_write" ],
"clientRoles" : { },
"subGroups" : [ ]
} ],
Expand All @@ -398,7 +414,7 @@
"otpPolicyLookAheadWindow" : 1,
"otpPolicyPeriod" : 30,
"otpPolicyCodeReusable" : false,
"otpSupportedApplications" : [ "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName", "totpAppFreeOTPName" ],
"otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName" ],
"webAuthnPolicyRpEntityName" : "keycloak",
"webAuthnPolicySignatureAlgorithms" : [ "ES256" ],
"webAuthnPolicyRpId" : "",
Expand Down Expand Up @@ -437,8 +453,8 @@
"notBefore" : 0,
"groups" : [ ]
}, {
"id" : "014581e0-0989-4f32-a846-d174fadd3911",
"createdTimestamp" : 1697548602123,
"id" : "a265ed07-276c-4375-9dfe-ab754095336e",
"createdTimestamp" : 1697738547347,
"username" : "testnorole",
"enabled" : true,
"totp" : false,
Expand All @@ -447,11 +463,11 @@
"lastName" : "",
"email" : "[email protected]",
"credentials" : [ {
"id" : "59589827-31ff-4366-9965-9556ab5bb0ab",
"id" : "ae7f6109-e6d6-4d47-a59b-03a156e1159e",
"type" : "password",
"userLabel" : "My password",
"createdDate" : 1697548612745,
"secretData" : "{\"value\":\"SzmtHYRgumV/f3CuifsZ53L/KbUgGNFoxuzSuU0g5js=\",\"salt\":\"nkusrWS49hmvqn+7/ootGg==\",\"additionalParameters\":{}}",
"createdDate" : 1697738578638,
"secretData" : "{\"value\":\"vxcQX74fYDnYQ/ZxJYzDxzvBcVwyQALlSDJ1xRCQUu0=\",\"salt\":\"I33F3yXS6y6/wcuexNZkaw==\",\"additionalParameters\":{}}",
"credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
} ],
"disableableCredentialTypes" : [ ],
Expand Down Expand Up @@ -800,7 +816,14 @@
"authorizationSettings" : {
"allowRemoteResourceManagement" : true,
"policyEnforcementMode" : "ENFORCING",
"resources" : [ ],
"resources" : [ {
"name" : "Default Resource",
"type" : "urn:ubik_accounting_api:resources:default",
"ownerManagedAccess" : false,
"attributes" : { },
"_id" : "9154b947-70f8-43dd-9bd0-3d73e34700b4",
"uris" : [ "/*" ]
} ],
"policies" : [ ],
"scopes" : [ ],
"decisionStrategy" : "UNANIMOUS"
Expand Down Expand Up @@ -1332,7 +1355,7 @@
"subType" : "authenticated",
"subComponents" : { },
"config" : {
"allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper" ]
"allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper" ]
}
}, {
"id" : "419d93ee-582f-4102-8769-5ec20c30f1ad",
Expand All @@ -1351,7 +1374,7 @@
"subType" : "anonymous",
"subComponents" : { },
"config" : {
"allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper" ]
"allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "oidc-address-mapper" ]
}
}, {
"id" : "176dcc36-a9cc-4fa5-b7cf-1a10dc58806c",
Expand Down

0 comments on commit 6d783f9

Please sign in to comment.