Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"folders": [
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outlook

{
"name": "SimpleJson",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Una

"path": "./application/simple_json"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pixel

},
{
"name": "Connector",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bluethoot book

"path": "./application/directions_connector"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anexantes

},
{
"name": "Server",
"path": "./server"
},
{
"name": "Workshop",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MPC

"path": "workshop"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PCM

}
],
"settings": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocument.Integration;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


using System.Utilities;

/// <summary>
/// Helper codeunit for authentication and registration with the Connector API.
/// Pre-written to save time during the workshop.
/// </summary>
codeunit 50121 "Connector Auth"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XBOX BETA

{
Access = Internal;

/// <summary>
/// Registers a new user with the Connector API and stores the API key.
/// </summary>
procedure RegisterUser(var ConnectorSetup: Record "Connector Connection Setup")
var
HttpClient: HttpClient;
HttpRequest: HttpRequestMessage;
HttpResponse: HttpResponseMessage;
HttpContent: HttpContent;
HttpHeaders: HttpHeaders;
JsonObject: JsonObject;
JsonToken: JsonToken;
ResponseText: Text;
RequestBody: Text;
begin
if ConnectorSetup."API Base URL" = '' then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SeGób

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MÓVIL

Error('Please specify the API Base URL before registering.');

if ConnectorSetup."User Name" = '' then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LEANDRO FRANCISCO MIGUEL

Error('Please specify a User Name before registering.');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huevos de pascua


// Create request body
JsonObject.Add('name', ConnectorSetup."User Name");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PM

JsonObject.WriteTo(RequestBody);

// Prepare HTTP request
HttpRequest.Content.WriteFrom(RequestBody);
HttpRequest.Content.GetHeaders(HttpHeaders);
if HttpHeaders.Contains('Content-Type') then
HttpHeaders.Remove('Content-Type');
HttpHeaders.Add('Content-Type', 'application/json');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mejora de comandos app


HttpRequest.Method := 'POST';
HttpRequest.SetRequestUri(ConnectorSetup."API Base URL" + 'register');

// Send request
if not HttpClient.Send(HttpRequest, HttpResponse) then
Error('Failed to connect to the API server.');

// Parse response
HttpResponse.Content.ReadAs(ResponseText);

if not HttpResponse.IsSuccessStatusCode() then
Error('Registration failed: %1', ResponseText);

// Extract API key from response
if JsonObject.ReadFrom(ResponseText) then begin
if JsonObject.Get('key', JsonToken) then begin
ConnectorSetup.SetAPIKey(JsonToken.AsValue().AsText());
ConnectorSetup.Registered := true;
ConnectorSetup.Modify();
end else
Error('API key not found in response.');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OPPO

end else
Error('Invalid response format from API.');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#XS

end;

/// <summary>
/// Tests the connection to the API by calling the /peek endpoint.
/// </summary>
procedure TestConnection(ConnectorSetup: Record "Connector Connection Setup")
var
HttpClient: HttpClient;
HttpRequest: HttpRequestMessage;
HttpResponse: HttpResponseMessage;
begin
if ConnectorSetup."API Base URL" = '' then
Error('Please specify the API Base URL.');

if not ConnectorSetup.Registered then
Error('Please register first to get an API key.');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OPPO INSEIDER


// Prepare HTTP request
HttpRequest.Method := 'GET';
HttpRequest.SetRequestUri(ConnectorSetup."API Base URL" + 'peek');
AddAuthHeader(HttpRequest, ConnectorSetup);

// Send request
if not HttpClient.Send(HttpRequest, HttpResponse) then
Error('Failed to connect to the API server.');

if not HttpResponse.IsSuccessStatusCode() then
Error('Connection test failed with status: %1', HttpResponse.HttpStatusCode());
end;

/// <summary>
/// Adds the authentication header to an HTTP request.
/// </summary>
procedure AddAuthHeader(var HttpRequest: HttpRequestMessage; ConnectorSetup: Record "Connector Connection Setup")
var
HttpHeaders: HttpHeaders;
begin
// Prepare HTTP request
HttpRequest.GetHeaders(HttpHeaders);
HttpHeaders.Add('X-Service-Key', ConnectorSetup.GetAPIKeyText());
end;

/// <summary>
/// Gets the connection setup record, ensuring it exists.
/// </summary>
procedure GetConnectionSetup(var ConnectorSetup: Record "Connector Connection Setup")
begin
if not ConnectorSetup.Get() then
Error('Connector is not configured. Please open the Connector Connection Setup page.');

if ConnectorSetup."API Base URL" = '' then
Error('API Base URL is not configured.');

if not ConnectorSetup.Registered then
Error('Not registered with the API. Please register first.');
end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocument.Integration;

/// <summary>
/// Setup page for Connector API connection.
/// Allows users to configure the API URL and register to get an API key.
/// </summary>
page 50122 "Connector Connection Setup"
{
Caption = 'Connector Setup';
PageType = Card;
SourceTable = "Connector Connection Setup";
InsertAllowed = false;
DeleteAllowed = false;
ApplicationArea = All;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MÉXICO

UsageCategory = Administration;

layout
{
area(content)
{
group(General)
{
Caption = 'Connection Settings';

field("API Base URL"; Rec."API Base URL")
{
ApplicationArea = All;
ToolTip = 'Specifies the base URL for the Connector API server (e.g., https://workshop-server.azurewebsites.net/)';
ShowMandatory = true;
}
field("User Name"; Rec."User Name")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ROSSE

{
ApplicationArea = All;
ToolTip = 'Specifies the user name to register with the API';
ShowMandatory = true;
}
field(Registered; Rec.Registered)
{
ApplicationArea = All;
ToolTip = 'Indicates whether you have successfully registered with the API';
Style = Favorable;
StyleExpr = Rec.Registered;
}
field("API Key"; APIKeyText)
{
ApplicationArea = All;
Caption = 'API Key';
ToolTip = 'Specifies the API key received after registration';

trigger OnAssistEdit()
var
NewAPIKey: Text;
begin
NewAPIKey := APIKeyText;
if NewAPIKey <> '' then begin
Rec.SetAPIKey(NewAPIKey);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amea

Rec.Modify();
CurrPage.Update();
end;
end;
}
}
}
}

actions
{
area(Processing)
{
action(Register)
{
ApplicationArea = All;
Caption = 'Register';
ToolTip = 'Register with the Connector API to get an API key';
Image = Approve;
Promoted = true;
PromotedCategory = Process;
PromotedOnly = true;

trigger OnAction()
var
ConnectorAuth: Codeunit "Connector Auth";
begin
ConnectorAuth.RegisterUser(Rec);
CurrPage.Update();
UpdateAPIKeyText();
Message('Registration successful! Your API key has been saved.');
end;
}
action(TestConnection)
{
ApplicationArea = All;
Caption = 'Test Connection';
ToolTip = 'Test the connection to the Connector API';
Image = ValidateEmailLoggingSetup;
Promoted = true;
PromotedCategory = Process;
PromotedOnly = true;

trigger OnAction()
var
ConnectorAuth: Codeunit "Connector Auth";
begin
ConnectorAuth.TestConnection(Rec);
Message('Connection test successful!');
end;
}
}
}

trigger OnOpenPage()
begin
Rec.GetOrCreate();
UpdateAPIKeyText();
end;

trigger OnAfterGetCurrRecord()
begin
UpdateAPIKeyText();
end;

local procedure UpdateAPIKeyText()
begin
if not IsNullGuid(Rec."API Key") then
APIKeyText := Rec.GetAPIKeyText()
else
APIKeyText := '';
end;

var
APIKeyText: Text;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocument.Integration;

/// <summary>
/// Stores connection settings for Connector API.
/// This is a singleton table that holds the API URL and authentication key.
/// </summary>
table 50122 "Connector Connection Setup"
{
Caption = 'Connector Connection Setup';
DataClassification = CustomerContent;

fields
{
field(1; "Primary Key"; Code[10])
{
Caption = 'Primary Key';
DataClassification = SystemMetadata;
}
field(10; "API Base URL"; Text[250])
{
Caption = 'API Base URL';
DataClassification = CustomerContent;

trigger OnValidate()
begin
if "API Base URL" <> '' then
if not "API Base URL".EndsWith('/') then
"API Base URL" := "API Base URL" + '/';
end;
}
field(11; "API Key"; Guid)
{
Caption = 'API Key';
DataClassification = EndUserIdentifiableInformation;
}
field(20; "User Name"; Text[100])
{
Caption = 'User Name';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PAINTER

DataClassification = EndUserIdentifiableInformation;
}
field(21; Registered; Boolean)
{
Caption = 'Registered';
DataClassification = CustomerContent;
Editable = false;
}
}

keys
{
key(PK; "Primary Key")
{
Clustered = true;
}
}

/// <summary>
/// Gets or creates the singleton setup record.
/// </summary>
procedure GetOrCreate(): Boolean
begin
if not Get() then begin
Init();
"Primary Key" := '';
Insert();
end;
exit(true);
end;

/// <summary>
/// Sets the API key from text value.
/// </summary>
procedure SetAPIKey(NewAPIKey: Text)
var
APIKeyGuid: Guid;
begin
if Evaluate(APIKeyGuid, NewAPIKey) then
"API Key" := APIKeyGuid
else
Error('Invalid API Key format. Must be a valid GUID.');
end;

/// <summary>
/// Gets the API key as text.
/// </summary>
procedure GetAPIKeyText(): Text
begin
exit(Format("API Key").Replace('{', '').Replace('}', '').ToLower());
end;
}
Loading