Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#27057 EDocument Connector for Tietoevry #27233 #27626

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
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 @@
{"schemeids": "0002 0007 0009 0037 0060 0088 0096 0097 0106 0130 0135 0142 0147 0151 0170 0183 0184 0188 0190 0191 0192 0193 0194 0195 0196 0198 0199 0200 0201 0202 0203 0204 0205 0208 0209 0210 0211 0212 0213 0215 0216 0217 0218 0219 0220 0221 0225 0230 9901 9910 9913 9914 9915 9918 9919 9920 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9957 9959 AN AQ AS AU EM" }
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions Apps/W1/EDocumentConnectors/Tietoevry/app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"id": "3b3c094c-ae7f-43f2-9246-22111b688d2e",
"name": "E-Document Connector - Tietoevry",
"publisher": "Microsoft",
"brief": "E-Document Connector - Tietoevry",
"description": "E-Document Connector - Tietoevry",
"version": "26.0.0.0",
"privacyStatement": "https://go.microsoft.com/fwlink/?LinkId=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2204541",
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"logo": "ExtensionLogo.png",
"contextSensitiveHelpUrl": "https://go.microsoft.com/fwlink/?linkid=2206603",
"dependencies": [
{
"id": "e1d97edc-c239-46b4-8d84-6368bdf67c8b",
"name": "E-Document Core",
"publisher": "Microsoft",
"version": "26.0.0.0"
}
],
"internalsVisibleTo": [
{
"id": "985549ff-145a-4b5c-acd1-db6d425f6cbc",
"name": "E-Document Connector - Tietoevry Tests",
"publisher": "Microsoft"
}
],
"screenshots": [

],
"platform": "26.0.0.0",
"idRanges": [
{
"from": 6390,
"to": 6399
}
],
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile": true
},
"application": "26.0.0.0",
"target": "OnPrem",
"features": [
"TranslationFile"
],
"resourceFolders": [
".resources"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// ------------------------------------------------------------------------------------------------
// 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.EDocumentConnector.Tietoevry;

using System.Security.Authentication;
codeunit 6394 "Authenticator"
{
Access = Internal;
Permissions = tabledata "OAuth 2.0 Setup" = im,
tabledata "Connection Setup" = rim;

procedure CreateConnectionSetupRecord()
var
ConnectionSetup: Record "Connection Setup";
begin
if not ConnectionSetup.Get() then begin
Roglar01 marked this conversation as resolved.
Show resolved Hide resolved
ConnectionSetup."Authentication URL" := this.AuthURLTxt;
ConnectionSetup."API URL" := this.APIURLTxt;
ConnectionSetup."Sandbox Authentication URL" := this.SandboxAuthURLTxt;
ConnectionSetup."Sandbox API URL" := this.SandboxAPIURLTxt;
ConnectionSetup."Send Mode" := ConnectionSetup."Send Mode"::Test; //Sandbox
ConnectionSetup.Insert();
end;
end;

procedure SetClientId(var ClientIdKey: Guid; ClientID: SecretText)
begin
this.SetIsolatedStorageValue(ClientIdKey, ClientID, DataScope::Company);
end;

procedure SetClientSecret(var ClienSecretKey: Guid; ClientSecret: SecretText)
begin
this.SetIsolatedStorageValue(ClienSecretKey, ClientSecret, DataScope::Company);
end;

procedure GetAccessToken() Token: SecretText
var
ConnectionSetup: Record "Connection Setup";
Requests: Codeunit Requests;
ExpiresIn: Integer;
ClientId, ClientSecret, TokenTxt, Response : SecretText;
TokenKey: Guid;
begin
ConnectionSetup.Get();

// Reuse token if it lives longer than 1 min in future
if (ConnectionSetup."Token Expiry" > CurrentDateTime() + 60 * 1000) and (not IsNullGuid(ConnectionSetup."Token - Key")) then
if this.GetTokenValue(ConnectionSetup."Token - Key", Token, DataScope::Company) then
exit;

if not this.GetTokenValue(ConnectionSetup."Client ID - Key", ClientId, DataScope::Company) then
Error(this.TietoevryClientIdErr, ConnectionSetup.TableCaption);

if not this.GetTokenValue(ConnectionSetup."Client Secret - Key", ClientSecret, DataScope::Company) then
Error(this.TietoevryClientSecretErr, ConnectionSetup.TableCaption);

Requests.Init();
Requests.CreateAuthenticateRequest(ClientId, ClientSecret);
this.ExecuteResponse(Requests, Response);
if not this.ParseResponse(Response, TokenTxt, ExpiresIn) then
Error(this.TietoevryParseTokenErr);

// Save token for reuse
this.SetIsolatedStorageValue(TokenKey, TokenTxt, DataScope::Company);
// Read again as we want fresh record to modify
ConnectionSetup.Get();
ConnectionSetup."Token - Key" := TokenKey;
ConnectionSetup."Token Expiry" := CurrentDateTime() + ExpiresIn * 1000;
ConnectionSetup.Modify();
Commit();
exit(TokenTxt);
end;

[NonDebuggable]
local procedure ExecuteResponse(var Request: Codeunit Requests; var Response: SecretText)
var
HttpExecutor: Codeunit "Http Executor";
begin
Response := HttpExecutor.ExecuteHttpRequest(Request);
end;

[NonDebuggable]
[TryFunction]
local procedure ParseResponse(Response: SecretText; var Token: SecretText; var ExpiresIn: Integer)
var
ResponseJson: JsonObject;
TokenJson, ExpiryJson : JsonToken;
begin
ResponseJson.ReadFrom(Response.Unwrap());
ResponseJson.Get('access_token', TokenJson);
Token := TokenJson.AsValue().AsText();
ResponseJson.Get('expires_in', ExpiryJson);
ExpiresIn := ExpiryJson.AsValue().AsInteger();
end;

procedure IsClientCredsSet(var ClientId: Text; var ClientSecret: Text): Boolean
var
ConnectionSetup: Record "Connection Setup";
begin
ConnectionSetup.Get();

if this.HasToken(ConnectionSetup."Client ID - Key", DataScope::Company) then
ClientId := '*';
if this.HasToken(ConnectionSetup."Client Secret - Key", DataScope::Company) then
ClientSecret := '*';
end;

procedure SetIsolatedStorageValue(var ValueKey: Guid; Value: SecretText; TokenDataScope: DataScope)
begin
if IsNullGuid(ValueKey) then
ValueKey := CreateGuid();

IsolatedStorage.Set(ValueKey, Value, TokenDataScope);
end;

local procedure GetTokenValue(TokenKey: Text; var TokenValueAsSecret: SecretText; TokenDataScope: DataScope): Boolean
begin
if not this.HasToken(TokenKey, TokenDataScope) then
exit(false);

exit(IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValueAsSecret));
end;

local procedure HasToken(TokenKey: Text; TokenDataScope: DataScope): Boolean
begin
exit(IsolatedStorage.Contains(TokenKey, TokenDataScope));
end;

var
AuthURLTxt: Label 'https://auth.infotorg.no/auth/realms/fms-realm/protocol/openid-connect', Locked = true;
APIURLTxt: Label 'https://accesspoint-api.dataplatfor.ms', Locked = true;
SandboxAuthURLTxt: Label 'https://auth-qa.infotorg.no/auth/realms/fms-realm/protocol/openid-connect', Locked = true;
SandboxAPIURLTxt: Label 'https://accesspoint-api.qa.dataplatfor.ms', Locked = true;
TietoevryClientIdErr: Label 'Tietoevry Client Id is not set in %1', Comment = '%1 - Client id';
TietoevryClientSecretErr: Label 'Tietoevry Client Secret is not set in %1', Comment = '%1 - Client secret';
TietoevryParseTokenErr: Label 'Failed to parse response for Tietoevry Access token request';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// ------------------------------------------------------------------------------------------------
// 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.EDocumentConnector.Tietoevry;

using Microsoft.EServices.EDocumentConnector;

table 6392 "Connection Setup"
{
fields
{
field(1; Id; Code[10])
{
DataClassification = CustomerContent;
}
field(2; "Client Id - Key"; Guid)
{
Caption = 'Client Id';
DataClassification = EndUserIdentifiableInformation;
}
field(3; "Client Secret - Key"; Guid)
{
Caption = 'Client Secret';
DataClassification = EndUserIdentifiableInformation;
}
field(4; "Authentication URL"; Text[250])
{
Caption = 'Authentication URL';
DataClassification = CustomerContent;
ToolTip = 'Specifies the URL to connect to Tietoevry.';
Editable = false;
}
field(5; "API URL"; Text[250])
{
Caption = 'API URL';
DataClassification = CustomerContent;
ToolTip = 'Specifies the URL to connect to Tietoevry''s api.';
Editable = false;
}
field(6; "Sandbox Authentication URL"; Text[250])
{
Caption = 'Sandbox Authentication URL';
DataClassification = CustomerContent;
ToolTip = 'Specifies the URL to connect to Tietoevry''s sandbox.';
Editable = false;
}
field(7; "Sandbox API URL"; Text[250])
{
Caption = 'Sandbox Authentication URL';
DataClassification = CustomerContent;
ToolTip = 'Specifies the URL to connect to Tietoevry sandbox api.';
Editable = false;
}
field(8; "Token - Key"; Guid)
{
Caption = 'Token';
DataClassification = SystemMetadata;
}
field(9; "Token Expiry"; DateTime)
{
Caption = 'Token Expiry';
DataClassification = SystemMetadata;
}
field(10; "Company Id"; Text[250])
{
Caption = 'Company ID';
DataClassification = EndUserIdentifiableInformation;
ToolTip = 'Specifies the company ID.';

trigger OnValidate()
var
TietoevryProcessing: Codeunit Processing;
begin
if not TietoevryProcessing.IsValidSchemeId(Rec."Company Id") then
Error(this.NotAValidCompanyIdErr, Rec."Company Id", Rec.FieldCaption("Company Id"));
end;
}
field(13; "Send Mode"; Enum "E-Doc. Ext. Send Mode")
Roglar01 marked this conversation as resolved.
Show resolved Hide resolved
{
Caption = 'Send Mode';
DataClassification = CustomerContent;
ToolTip = 'Specifies the send mode.';
}
}

keys
{
key(Key1; Id)
{
Clustered = true;
}
}

var
NotAValidCompanyIdErr: Label '%1 is not a valid %2', Comment = '%1 = Company Id, %2 = fieldname';

}
Loading