Skip to content

Commit aae0379

Browse files
authored
[VAT Group Management] Optimize setup validation (#9029)
<!-- Thanks for contributing to BCApps! A few things before you hit "Create pull request": - Your PR must link to an approved issue. New here? See CONTRIBUTING.md. - You must have built and run your change yourself. CI is a safety net, not a substitute. - If you used AI or an agent to write this PR, you are still the author. Read the diff, build it, and try it before requesting review. Contributing guide: https://github.com/microsoft/BCApps/blob/main/CONTRIBUTING.md Local dev environment: https://github.com/microsoft/BCApps/blob/main/LOCAL_DEV_ENV.md --> ## What & why Improving the hostname check for VAT Group Management feature ## Linked work <!-- Required: link an approved GitHub issue using "Fixes #<number>". Microsoft contributors: also link the ADO work item with "AB#<number>" if you have one. --> Fixes [AB#641094](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/641094) ## How I validated this - [x] I read the full diff and it contains only changes I intended. - [ ] I built the affected app(s) locally with no new analyzer warnings. - [ ] I ran the change in Business Central and confirmed it behaves as expected. - [x] I added or updated tests for the new behavior, or explained below why none are needed. **What I tested and the outcome** *(required — be specific: scenarios, commands, screenshots for UI changes)* Added more automated tests <!-- Example: - Ran the new "Post and Send" action on a sales invoice in a fresh container; document posted and email queued (see screenshot). - New unit tests in MyFeatureTest.Codeunit.al pass locally; full module test suite green. - No tests added because change is comment-only / refactor with existing coverage. --> ## Risk & compatibility <!-- Anything reviewers should watch for: breaking changes, upgrade/data impact, permissions, telemetry, feature flags, follow-up work. Write "None" if there's nothing to call out. -->
1 parent 835e623 commit aae0379

3 files changed

Lines changed: 56 additions & 8 deletions

File tree

src/Apps/W1/VATGroupManagement/app/src/Codeunits/VATGroupCommunication.Codeunit.al

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ codeunit 4700 "VAT Group Communication"
1616
var
1717
VATReportSetup: Record "VAT Report Setup";
1818
NoVATSetupErr: Label 'The VAT Report Setup could not be found.';
19+
InvalidGroupRepresentativeURLErr: Label 'The Group Representative API URL is not a valid Microsoft Business Central endpoint.';
1920
BearerTokenFromCacheErr: Label 'The OAuth2 token could not be retrieved from cache. Choose the action Renew OAuth2 Token on the page %1 and log in to get a new token.', Comment = '%1 the caption of a page.';
2021
OAuthFailedNoErr: label 'Authorization has failed with an unexpected error.';
2122
OAuthFailedErr: Label 'Authorization has failed with the error %1', Comment = '%1 is the error description.';
@@ -66,17 +67,25 @@ codeunit 4700 "VAT Group Communication"
6667
[TryFunction]
6768
internal procedure Send(Method: Text; Endpoint: Text; Content: Text; var HttpResponseBodyText: Text; IsBatch: Boolean)
6869
var
70+
EnvironmentInformation: Codeunit "Environment Information";
6971
HttpClient: HttpClient;
7072
HttpRequestMessage: HttpRequestMessage;
7173
HttpResponseMessage: HttpResponseMessage;
74+
RequestUri: Text;
7275
begin
7376
CheckLoadVATReportSetup();
7477

75-
HttpRequestMessage.Method(Method);
7678
if IsBatch then
77-
HttpRequestMessage.SetRequestUri(PrepareBatchURI(Endpoint))
79+
RequestUri := PrepareBatchURI(Endpoint)
7880
else
79-
HttpRequestMessage.SetRequestUri(PrepareURI(Endpoint));
81+
RequestUri := PrepareURI(Endpoint);
82+
83+
if EnvironmentInformation.IsSaaSInfrastructure() then
84+
if not VATReportSetup.IsAllowedGroupRepresentativeAPIURL(RequestUri) then
85+
Error(InvalidGroupRepresentativeURLErr);
86+
87+
HttpRequestMessage.Method(Method);
88+
HttpRequestMessage.SetRequestUri(RequestUri);
8089
PrepareHeaders(HttpRequestMessage, IsBatch);
8190
PrepareContent(HttpRequestMessage, Content);
8291

src/Apps/W1/VATGroupManagement/app/src/Tables/VATReportSetupExtension.TableExt.al

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using Microsoft.Finance.GeneralLedger.Journal;
99
using Microsoft.Finance.VAT.Reporting;
1010
using System.Environment;
1111
using System.Telemetry;
12+
using System.Utilities;
1213

1314
tableextension 4701 "VAT Report Setup Extension" extends "VAT Report Setup"
1415
{
@@ -259,12 +260,23 @@ tableextension 4701 "VAT Report Setup Extension" extends "VAT Report Setup"
259260

260261
internal procedure ValidateGroupRepresentativeAPIURL(): Boolean
261262
begin
262-
if Rec."Group Representative API URL" <> '' then
263-
if not Lowercase(Rec."Group Representative API URL").StartsWith('https://api.businesscentral.dynamics.com') then
264-
if not Lowercase(Rec."Group Representative API URL").StartsWith('https://api.businesscentral.dynamics-tie.com') then
265-
exit(false);
263+
if Rec."Group Representative API URL" = '' then
264+
exit(true);
266265

267-
exit(true);
266+
exit(IsAllowedGroupRepresentativeAPIURL(Rec."Group Representative API URL"));
267+
end;
268+
269+
internal procedure IsAllowedGroupRepresentativeAPIURL(ApiUrl: Text): Boolean
270+
var
271+
Uri: Codeunit Uri;
272+
begin
273+
Uri.Init(ApiUrl);
274+
if LowerCase(Uri.GetScheme()) <> 'https' then
275+
exit(false);
276+
277+
exit(
278+
Uri.AreURIsHaveSameHost(ApiUrl, 'https://api.businesscentral.dynamics.com') or
279+
Uri.AreURIsHaveSameHost(ApiUrl, 'https://api.businesscentral.dynamics-tie.com'));
268280
end;
269281

270282
var

src/Apps/W1/VATGroupManagement/test/src/VATGroupHelperFunctTest.Codeunit.al

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,33 @@ codeunit 139520 "VAT Group Helper Funct Test"
871871
Assert.IsFalse(VATReportSetup.ValidateGroupRepresentativeAPIURL(), 'The invalid API URL should not be valid');
872872
end;
873873

874+
[Test]
875+
procedure ValidateURLWithSuffixHostIsRejected()
876+
var
877+
VATReportSetup: Record "VAT Report Setup";
878+
begin
879+
VATReportSetup."Group Representative API URL" := 'https://api.businesscentral.dynamics.com.attacker.com/api';
880+
Assert.IsFalse(VATReportSetup.ValidateGroupRepresentativeAPIURL(), 'A suffix-host URL should not be valid');
881+
end;
882+
883+
[Test]
884+
procedure ValidateURLWithUserInfoHostIsRejected()
885+
var
886+
VATReportSetup: Record "VAT Report Setup";
887+
begin
888+
VATReportSetup."Group Representative API URL" := 'https://api.businesscentral.dynamics.com@attacker.com/api';
889+
Assert.IsFalse(VATReportSetup.ValidateGroupRepresentativeAPIURL(), 'A userinfo-host URL should not be valid');
890+
end;
891+
892+
[Test]
893+
procedure ValidateURLWithNonHttpsSchemeIsRejected()
894+
var
895+
VATReportSetup: Record "VAT Report Setup";
896+
begin
897+
VATReportSetup."Group Representative API URL" := 'http://api.businesscentral.dynamics.com/api';
898+
Assert.IsFalse(VATReportSetup.ValidateGroupRepresentativeAPIURL(), 'A non-https URL should not be valid');
899+
end;
900+
874901
local procedure Initialize()
875902
begin
876903
LibraryVATGroup.EnableDefaultVATMemberSetup();

0 commit comments

Comments
 (0)