Page History
...
YFX files are actually archive (zip) files that can be decompressed. Within the YFX there will be a ExportListHierarchy.json file and a YFExport.xml file. The YFExport.xml file contains a readable version of the exported datasource.
Within the YFExport.xml file the database connection settings can be changed. If the process of creating tenant data sources for source substitution is to be automated, then the contents of the YFExport.xml file could be used as a template, with tokens added where connection specific data needs to be injected.
...
Once an export file has been automatically injected with tokens, it can be uploaded via the REST API using the POST /api/rpc/import-export/import-content end-point (https://developers.yellowfinbi.com/dev/api-docs/current/#operation/importContent ), Import Content.
This particular endpoint uses a form based submission paradigm. Two form bodies are required - one named “contentToProcess” with the YFX/XML file contents and another named “importOptions”, which contains the rules on how the import is processed. For this example, assuming the XML file contains a single datasource, this importOptions payload can be used:
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
Code Block | ||||||
| ||||||
Code Block | ||||||
| ||||||
Code Block | ||||||
| ||||||
Code Block | ||||||
| ||||||
Code Block | ||||||
|
Create a new datasource via the datasource service
A datasource can be created directly via the REST API using the POST /api/data-sources end-point, Create Data Source.
This takes a datasource model of this format:
Code Block |
---|
{
"sourceName": "Client Database",
"sourceDescription": "",
"sourceType": "POSTGRESQL",
"connectionType": "JDBC",
"connectionTypeCode": "GENERICUSER",
"connectionDriver": "org.postgresql.Driver",
"connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata",
"connectionTimeout": 180,
"userName": "postgres",
"minimumConnections": 1,
"maximumConnections": 5,
"refreshTime": 180,
"timezone": "AUSTRALIA/SYDNEY",
"accessLevelCode": "UNSECURE",
"maxRows": 10000,
"maxAnalysisRows": 0,
"inheritChildSourceFilters": false,
"sourceLogIndicator": false,
"sourceOptions": [
{
"optionKey": "ISOLATIONLEVEL",
"optionValue": "1.0",
"valueDataType": "1"
},
{
"optionKey": "USESCHEMA",
"optionValue": "true",
"valueDataType": "6"
},
{
"optionKey": "HOSTNAME",
"optionValue": "192.168.1.100",
"valueDataType": "2"
},
{
"optionKey": "PORT",
"optionValue": "5432",
"valueDataType": "1"
},
{
"optionKey": "DATABASE",
"optionValue": "testdata",
"valueDataType": "2"
},
{
"optionKey": "YF_DRIVER_SELECTION",
"optionValue": "org.postgresql.Driver",
"valueDataType": "2"
}
]
} |
The main body of the model is similar to the model returned by the GET /api/data-sources end-point. If creating a new source similar to the Primary Organization datasource, the data returned by GET /api/data-sources can be used as a template.
The sourceOptions in the creation model differ depending on the database type and are representative of the options that are exposed by the connection wizard when connecting to a new datasource.
It should be noted that although the connectionString is available in the model body, this is regenerated based on the source options when the datasource is created.
The following examples illustrate how to create a new datasource via the POST /api/data-sources end-point:
...
language | java |
---|---|
title | Java |
collapse | true |
...
language | c# |
---|---|
title | C# |
collapse | true |
...
title | Go |
---|---|
collapse | true |
...
language | js |
---|---|
title | JavaScript |
collapse | true |
...
language | php |
---|---|
title | PHP |
collapse | true |
...
language | py |
---|---|
title | Python |
collapse | true |
List Data Sources
A list of datasources can be retrieved with the GET /api/data-sources end-point (https://developers.yellowfinbi.com/dev/api-docs/current/#operation/getAllDataSources ). This will return a datasource model of the following form:
{
"sourceId": 132780,
"sourceName": "PostgreSQL Connection for NEWCLIENT",
"sourceDescription": "PostgreSQL Connection for NEWCLIENT",
"sourceType": "POSTGRESQL",
"connectionType": "JDBC",
"connectionTypeCode": "GENERICUSER",
"connectionDriver": "org.postgresql.Driver",
"connectionPath": "public",
"connectionString": "jdbc:postgresql://localhost:5432/testdata",
"connectionTimeout": 180,
"userName": "postgres",
"minimumConnections": 1,
"maximumConnections": 5,
"refreshTime": 180,
"timezone": "AUSTRALIA/LORD_HOWE",
"accessLevelCode": "UNSECURE",
"maxRows": 10000,
"maxAnalysisRows": 0,
"inheritChildSourceFilters": false,
"sourceLogIndicator": false
}
This service can be used to find the internal integer identifier for the datasource (sourceId) for a given data source name.
The following code examples illustrate how to retrieve a list of data sources from the system:
Java | C# | Go | JavaScript | PHP | Python
Attach a Client Datasource to a Primary Org Datasource for Source Substitution
A Client Datasource can be linked to a Primary Org Datasource (for use with Source Substitution) using the POST /api/data-sources/{primaryOrgSourceId}/client-data-sources/?clientSourceId={clientOrgSourceId} end-point (https://developers.yellowfinbi.com/dev/api-docs/current/#operation/addClientDataSource ).
Where {primaryOrgSourceId} is the integer identifier for the primary organization datasource, and {clientOrgSourceId} is the integer identifier for the client org datasource to link.
The following examples illustrate how to link a Client Datasource (identified by its name) to a Primary Org Datasource (identified by its name):
...
package rest.code.examples;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Random;
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Import a datasource for a client org using the Yellowfin REST API
*/
public class ImportDatasourceForClientOrg {
public static void main(String[] args) throws Exception {
System.out.print(""Import Datasource for Client"");
String host = ""http://localhost:8080/Yellowfin"";
String restUsername = ""admin@yellowfin.com.au"";
String restPassword = ""test"";
String tenantClientReferenceId = ""NEWCLIENT"";
String databaseUserName = ""postgres"";
String encryptedPassword = ""NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"";
String serverAddress = ""localhost"";
String databaseName = ""testdata"";
String token = generateTokenForTenant(host, restUsername, restPassword, tenantClientReferenceId);
Integer tenantId = retrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId);
System.out.println(""Tenant Id: "" + tenantId);
// Replace tokens with values
String modifiedFileContents = importFileContents;
modifiedFileContents = modifiedFileContents.replace(""[USERNAME]"", databaseUserName);
modifiedFileContents = modifiedFileContents.replace(""[TENANT_NAME]"", tenantClientReferenceId);
modifiedFileContents = modifiedFileContents.replace(""[ENCRYPTED_PASSWORD]"", encryptedPassword);
modifiedFileContents = modifiedFileContents.replace(""[SERVER_ADDRESS]"", serverAddress);
modifiedFileContents = modifiedFileContents.replace(""[DATABASE_NAME]"", databaseName);
HttpEntity multipartEntity = MultipartEntityBuilder
.create()
.setMode(HttpMultipartMode.LEGACY)
.setCharset(Charset.forName(""UTF-8""))
.addBinaryBody(""contentToProcess"", modifiedFileContents.getBytes(""UTF-8""), ContentType.DEFAULT_BINARY, ""YFExport.xml"")
.addTextBody(""importOptions"", ""[{ \""itemIndex\"": 0, \""optionKey\"": \""SKIP\"", \""optionValue\"": false }, { \""itemIndex\"": 0, \""optionKey\"": \""OPTION\"", \""optionValue\"": \""ADD\"" }]"", ContentType.APPLICATION_JSON)
.build();
System.out.println(""Content-Type: "" + multipartEntity.getContentType());
Content c = Request.post(host + ""/api/rpc/import-export/import-content"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", multipartEntity.getContentType())
.addHeader(""cache-control"", ""no-cache"")
.body(multipartEntity)
.execute()
.returnContent();
System.out.println(c.asString());
}
/*
* This function fetches a client organization's integer id for a given clientRefCode
*/
public static Integer retrieveTenantIpIdForTenantName(String host, String token, String tenantCode) throws IOException {
Content c = Request.get(host + ""/api/orgs"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.execute().returnContent();
JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
JsonElement groupList = jsonObject.get(""items"");
JsonArray groups = groupList.getAsJsonArray();
for (int i=0; i < groups.size(); i++ ) {
JsonObject group = groups.getAsJsonArray().get(i).getAsJsonObject();
if (!group.has(""clientRefId"")) continue;
if (tenantCode.equals(group.get(""clientRefId"").getAsString())) return group.get(""ipOrg"").getAsInt();
}
System.out.println(""Tenant could not be found for code:"" + tenantCode);
System.exit(-1);
return null;
}
/*
* This function generates an access token for a user that will grant them access to
* call REST API endpoints.
*/
public static String generateTokenForTenant(String host, String username, String password, String tenant) throws IOException {
Content c = Request.post(host + ""/api/refresh-tokens"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.bodyString(""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\"", \""clientOrgRef\"": \"""" + tenant + ""\""}"", null)
.execute().returnContent();
JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");
if (accessToken!=null) {
System.out.println(""Access Token: "" + accessToken);
} else {
System.out.println(""Token not retrieved successfully"");
System.exit(-1);
}
return accessToken.getAsString();
}
private static String importFileContents = ""<?xml version=\""1.0\"" encoding=\""UTF-8\""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --><data>\n""
+ "" <info>\n""
+ "" <exportversion>4</exportversion>\n""
+ "" <exportsubversion>54</exportsubversion>\n""
+ "" <transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>\n""
+ "" <appversion>9.11</appversion>\n""
+ "" <appsubversion>0.3</appsubversion>\n""
+ "" <buildversion>20240607</buildversion>\n""
+ "" <exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>\n""
+ "" <systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>\n""
+ "" </info>\n""
+ "" <source>\n""
+ "" <id>132641</id>\n""
+ "" <sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>\n""
+ "" <sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>\n""
+ "" <databasePath>public</databasePath>\n""
+ "" <userName>[USERNAME]</userName>\n""
+ "" <password>[ENCRYPTED_PASSWORD]</password>\n""
+ "" <connectionTypeCode>GENERICUSER</connectionTypeCode>\n""
+ "" <connectionMethodCode>JDBC</connectionMethodCode>\n""
+ "" <connectionDriver>org.postgresql.Driver</connectionDriver>\n""
+ "" <databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>\n""
+ "" <databaseTypeCode>POSTGRESQL</databaseTypeCode>\n""
+ "" <minConnections>1</minConnections>\n""
+ "" <maxConnections>5</maxConnections>\n""
+ "" <connectionRefreshTime>180</connectionRefreshTime>\n""
+ "" <connectionTimeOut>180</connectionTimeOut>\n""
+ "" <accessCode>UNSECURE</accessCode>\n""
+ "" <maxRowCount>10000</maxRowCount>\n""
+ "" <maxAnalysisRowCount>0</maxAnalysisRowCount>\n""
+ "" <broadcastPermitted>true</broadcastPermitted>\n""
+ "" <subscribePermitted>true</subscribePermitted>\n""
+ "" <dataProfileEnabled>true</dataProfileEnabled>\n""
+ "" <localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>\n""
+ "" <secondaryMinConnections>0</secondaryMinConnections>\n""
+ "" <secondaryMaxConnections>0</secondaryMaxConnections>\n""
+ "" <secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>\n""
+ "" <secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>\n""
+ "" <lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>\n""
+ "" <sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>\n""
+ "" <filterList/>\n""
+ "" <sourceParameterList>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>DATABASE</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue>[DATABASE_NAME]</parameterValue>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>true</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>HOSTNAME</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue>[SERVER_ADDRESS]</parameterValue>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>true</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>ISOLATIONLEVEL</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue/>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>true</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>PORT</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue>5432</parameterValue>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>true</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>SOURCECLASSNAME</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>false</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>USESCHEMA</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue>true</parameterValue>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>true</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" <sourceParameter>\n""
+ "" <id>0</id>\n""
+ "" <parameterTypeCode>TEXT</parameterTypeCode>\n""
+ "" <parameterKey>YF_DRIVER_SELECTION</parameterKey>\n""
+ "" <parameterIndex>0</parameterIndex>\n""
+ "" <parameterValue>org.postgresql.Driver</parameterValue>\n""
+ "" <documentId>0</documentId>\n""
+ "" <userVisible>true</userVisible>\n""
+ "" </sourceParameter>\n""
+ "" </sourceParameterList>\n""
+ "" </source>\n""
+ "" <translationDictionary/>\n""
+ "" <refCodeDictionary/>\n""
+ ""</data>"";
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace YellowfinAPIExamples
{
public class ImportDatasourceForClientOrg
{
static async Task Main(string[] args)
{
Console.WriteLine(""Import Datasource for Client"");
string host = ""http://localhost:8080/Yellowfin"";
string restUsername = ""admin@yellowfin.com.au"";
string restPassword = ""test"";
string tenantClientReferenceId = ""NEWCLIENT"";
string databaseUserName = ""postgres"";
string encryptedPassword = ""NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"";
string serverAddress = ""localhost"";
string databaseName = ""testdata"";
string token = await GenerateTokenForTenant(host, restUsername, restPassword, tenantClientReferenceId);
int tenantId = await RetrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId);
Console.WriteLine(""Tenant Id: "" + tenantId);
// Replace tokens with values
string modifiedFileContents = ImportFileContents;
modifiedFileContents = modifiedFileContents.Replace(""[USERNAME]"", databaseUserName)
.Replace(""[TENANT_NAME]"", tenantClientReferenceId)
.Replace(""[ENCRYPTED_PASSWORD]"", encryptedPassword)
.Replace(""[SERVER_ADDRESS]"", serverAddress)
.Replace(""[DATABASE_NAME]"", databaseName);
using (var httpClient = new HttpClient())
{
var content = new MultipartFormDataContent
{
{
new ByteArrayContent(Encoding.UTF8.GetBytes(modifiedFileContents)), ""contentToProcess"",
""YFExport.xml""
},
{
new StringContent(
""[{ \""itemIndex\"": 0, \""optionKey\"": \""SKIP\"", \""optionValue\"": false }, { \""itemIndex\"": 0, \""optionKey\"": \""OPTION\"", \""optionValue\"": \""ADD\"" }]"",
Encoding.UTF8, ""application/json""),
""importOptions""
}
};
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"",
""ts="" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + "" , nonce="" + new Random().NextInt64() +
"", token="" + token);
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
httpClient.DefaultRequestHeaders.Add(""cache-control"", ""no-cache"");
HttpResponseMessage response =
await httpClient.PostAsync(host + ""/api/rpc/import-export/import-content"", content);
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
private static async Task<int> RetrieveTenantIpIdForTenantName(string host, string token, string tenantCode)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"",
""ts="" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + "" , nonce="" + new Random().NextInt64() +
"", token="" + token);
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
HttpResponseMessage response = await httpClient.GetAsync(host + ""/api/orgs"");
string responseBody = await response.Content.ReadAsStringAsync();
JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseBody);
JArray groups = (JArray)jsonObject[""items""];
foreach (var group in groups)
{
if (group[""clientRefId""] != null && tenantCode == group[""clientRefId""].ToString())
{
return (int)group[""ipOrg""];
}
}
Console.WriteLine(""Tenant could not be found for code:"" + tenantCode);
Environment.Exit(-1);
return 0;
}
}
private static async Task<string> GenerateTokenForTenant(string host, string username, string password,
string tenant)
{
using (var client = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Post, host + ""/api/refresh-tokens"");
request.Headers.Add(""Authorization"",
""YELLOWFIN ts="" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + "", nonce="" +
new Random().NextInt64());
request.Headers.Add(""Accept"", ""application/vnd.yellowfin.api-v1+json"");
request.Content = new StringContent(
JsonConvert.SerializeObject(new
{ userName = username, password = password, clientOrgRef = tenant }),
Encoding.UTF8,
""application/json""
);
HttpResponseMessage response = await client.SendAsync(request);
string responseContent = await response.Content.ReadAsStringAsync();
JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent);
string accessToken = jsonObject[""_embedded""][""accessToken""][""securityToken""].ToString();
if (!string.IsNullOrEmpty(accessToken))
{
Console.WriteLine(""Access Token: "" + accessToken);
}
else
{
Console.WriteLine(""Token not retrieved"");
Environment.Exit(-1);
}
return accessToken;
}
}
private static readonly string ImportFileContents =
@""<?xml version=""""1.0"""" encoding=""""UTF-8""""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --><data>
<info>
<exportversion>4</exportversion>
<exportsubversion>54</exportsubversion>
<transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>
<appversion>9.11</appversion>
<appsubversion>0.3</appsubversion>
<buildversion>20240607</buildversion>
<exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>
<systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>
</info>
<source>
<id>132641</id>
<sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>
<sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>
<databasePath>public</databasePath>
<userName>[USERNAME]</userName>
<password>[ENCRYPTED_PASSWORD]</password>
<connectionTypeCode>GENERICUSER</connectionTypeCode>
<connectionMethodCode>JDBC</connectionMethodCode>
<connectionDriver>org.postgresql.Driver</connectionDriver>
<databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>
<databaseTypeCode>POSTGRESQL</databaseTypeCode>
<minConnections>1</minConnections>
<maxConnections>5</maxConnections>
<connectionRefreshTime>180</connectionRefreshTime>
<connectionTimeOut>180</connectionTimeOut>
<accessCode>UNSECURE</accessCode>
<maxRowCount>10000</maxRowCount>
<maxAnalysisRowCount>0</maxAnalysisRowCount>
<broadcastPermitted>true</broadcastPermitted>
<subscribePermitted>true</subscribePermitted>
<dataProfileEnabled>true</dataProfileEnabled>
<localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>
<secondaryMinConnections>0</secondaryMinConnections>
<secondaryMaxConnections>0</secondaryMaxConnections>
<secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>
<secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>
<lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>
<sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>
<filterList/>
<sourceParameterList>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>DATABASE</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[DATABASE_NAME]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>HOSTNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[SERVER_ADDRESS]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>ISOLATIONLEVEL</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue/>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>PORT</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>5432</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>SOURCECLASSNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>
<documentId>0</documentId>
<userVisible>false</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>USESCHEMA</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>true</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>YF_DRIVER_SELECTION</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>org.postgresql.Driver</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
</sourceParameterList>
</source>
<translationDictionary/>
<refCodeDictionary/>
</data>"";
}
} |
Code Block | ||||
---|---|---|---|---|
| ||||
package main
import (
""bytes""
""encoding/json""
""fmt""
""io/ioutil""
""math/rand""
""mime/multipart""
""net/http""
""strings""
""time""
)
func main() {
host := ""http://localhost:8080/Yellowfin""
restUsername := ""admin@yellowfin.com.au""
restPassword := ""test""
tenantClientReferenceId := ""NEWCLIENT""
databaseUserName := ""postgres""
encryptedPassword := ""NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw""
serverAddress := ""localhost""
databaseName := ""testdata""
token, err := generateToken(host, restUsername, restPassword, tenantClientReferenceId)
if err != nil {
fmt.Println(""Error generating token:"", err)
return
}
tenantId, err := retrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId)
if err != nil {
fmt.Println(""Error retrieving tenant ID:"", err)
return
}
fmt.Println(""Tenant Id:"", tenantId)
// Replace tokens with values
modifiedFileContents := strings.Replace(importFileContents, ""[USERNAME]"", databaseUserName, -1)
modifiedFileContents = strings.Replace(modifiedFileContents, ""[TENANT_NAME]"", tenantClientReferenceId, -1)
modifiedFileContents = strings.Replace(modifiedFileContents, ""[ENCRYPTED_PASSWORD]"", encryptedPassword, -1)
modifiedFileContents = strings.Replace(modifiedFileContents, ""[SERVER_ADDRESS]"", serverAddress, -1)
modifiedFileContents = strings.Replace(modifiedFileContents, ""[DATABASE_NAME]"", databaseName, -1)
bodyBuffer := &bytes.Buffer{}
writer := multipart.NewWriter(bodyBuffer)
// Add file content
part, err := writer.CreateFormFile(""contentToProcess"", ""YFExport.xml"")
if err != nil {
fmt.Println(""Error creating form file:"", err)
return
}
part.Write([]byte(modifiedFileContents))
// Add text body
err = writer.WriteField(""importOptions"", `[{""itemIndex"": 0, ""optionKey"": ""SKIP"", ""optionValue"": false}, {""itemIndex"": 0, ""optionKey"": ""OPTION"", ""optionValue"": ""ADD""}]`)
if err != nil {
fmt.Println(""Error writing field:"", err)
return
}
writer.Close()
client := &http.Client{}
req, err := http.NewRequest(""POST"", host+""/api/rpc/import-export/import-content"", bodyBuffer)
if err != nil {
fmt.Println(""Error creating request:"", err)
return
}
nonce := rand.Int63()
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d, token=%s"", time.Now().UnixMilli(), nonce, token))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", writer.FormDataContentType())
req.Header.Set(""cache-control"", ""no-cache"")
resp, err := client.Do(req)
if err != nil {
fmt.Println(""Error sending request:"", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return
}
fmt.Println(string(body))
}
func generateToken(host, restUsername, restPassword, tenant string) (string, error) {
nonce := rand.Int63()
requestBody, err := json.Marshal(map[string]string{
""userName"": restUsername,
""password"": restPassword,
""clientOrgRef"": tenant,
})
if err != nil {
fmt.Println(""Error marshaling request body:"", err)
return """", err
}
client := &http.Client{}
request, err := http.NewRequest(""POST"", host+""/api/refresh-tokens"", bytes.NewBuffer(requestBody))
if err != nil {
fmt.Println(""Error creating request:"", err)
return """", err
}
request.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d"", time.Now().UnixMilli(), nonce))
request.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
request.Header.Set(""Content-Type"", ""application/json"")
response, err := client.Do(request)
if err != nil {
fmt.Println(""Error sending request:"", err)
return """", err
}
defer response.Body.Close()
responseBody, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return """", err
}
var jsonResponse map[string]interface{}
err = json.Unmarshal(responseBody, &jsonResponse)
if err != nil {
fmt.Println(""Error parsing JSON response:"", err)
return """", err
}
accessToken, ok := jsonResponse[""_embedded""].(map[string]interface{})[""accessToken""].(map[string]interface{})[""securityToken""].(string)
if !ok {
fmt.Println(""Token not retrieved"")
return """", fmt.Errorf(""Token not retrieved successfully"")
}
return accessToken, nil
}
func retrieveTenantIpIdForTenantName(host, token, tenantCode string) (int, error) {
client := &http.Client{}
req, err := http.NewRequest(""GET"", host+""/api/orgs"", nil)
if err != nil {
return 0, err
}
nonce := rand.Int63()
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d, token=%s"", time.Now().UnixMilli(), nonce, token))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
return 0, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, err
}
var jsonResponse map[string]interface{}
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
return 0, err
}
items, ok := jsonResponse[""items""].([]interface{})
if !ok {
return 0, fmt.Errorf(""Invalid response format"")
}
for _, item := range items {
group, ok := item.(map[string]interface{})
if !ok {
continue
}
if group[""clientRefId""] == tenantCode {
return int(group[""ipOrg""].(float64)), nil
}
}
return 0, fmt.Errorf(""Tenant could not be found for code: %s"", tenantCode)
}
const importFileContents = `<?xml version=""1.0"" encoding=""UTF-8""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) --><data>
<info>
<exportversion>4</exportversion>
<exportsubversion>54</exportsubversion>
<transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>
<appversion>9.11</appversion>
<appsubversion>0.3</appsubversion>
<buildversion>20240607</buildversion>
<exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>
<systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>
</info>
<source>
<id>132641</id>
<sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>
<sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>
<databasePath>public</databasePath>
<userName>[USERNAME]</userName>
<password>[ENCRYPTED_PASSWORD]</password>
<connectionTypeCode>GENERICUSER</connectionTypeCode>
<connectionMethodCode>JDBC</connectionMethodCode>
<connectionDriver>org.postgresql.Driver</connectionDriver>
<databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>
<databaseTypeCode>POSTGRESQL</databaseTypeCode>
<minConnections>1</minConnections>
<maxConnections>5</maxConnections>
<connectionRefreshTime>180</connectionRefreshTime>
<connectionTimeOut>180</connectionTimeOut>
<accessCode>UNSECURE</accessCode>
<maxRowCount>10000</maxRowCount>
<maxAnalysisRowCount>0</maxAnalysisRowCount>
<broadcastPermitted>true</broadcastPermitted>
<subscribePermitted>true</subscribePermitted>
<dataProfileEnabled>true</dataProfileEnabled>
<localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>
<secondaryMinConnections>0</secondaryMinConnections>
<secondaryMaxConnections>0</secondaryMaxConnections>
<secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>
<secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>
<lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>
<sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>
<filterList/>
<sourceParameterList>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>DATABASE</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[DATABASE_NAME]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>HOSTNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[SERVER_ADDRESS]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>ISOLATIONLEVEL</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue/>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>PORT</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>5432</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>SOURCECLASSNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>
<documentId>0</documentId>
<userVisible>false</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>USESCHEMA</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>true</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>YF_DRIVER_SELECTION</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>org.postgresql.Driver</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
</sourceParameterList>
</source>
<translationDictionary/>
<refCodeDictionary/>
</data>
` |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
const fetch = require(""node-fetch"");
const FormData = require(""form-data"");
const { Buffer } = require('buffer');
async function main() {
console.log(""Import Datasource for Client"");
const host = ""http://localhost:8080/Yellowfin"";
const restUsername = ""admin@yellowfin.com.au"";
const restPassword = ""test"";
const tenantClientReferenceId = ""NEWCLIENT"";
const databaseUserName = ""postgres"";
const encryptedPassword = ""NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"";
const serverAddress = ""localhost"";
const databaseName = ""testdata"";
const token = await generateTokenForTenant(host, restUsername, restPassword, tenantClientReferenceId);
if (!token) {
console.error(""Failed to retrieve access token"");
return;
}
const tenantId = await retrieveTenantIpIdForTenantName(host, token, tenantClientReferenceId);
console.log(""Tenant Id:"", tenantId);
// Replace tokens with values
let modifiedFileContents = importFileContents;
modifiedFileContents = modifiedFileContents.replace(""[USERNAME]"", databaseUserName);
modifiedFileContents = modifiedFileContents.replace(""[TENANT_NAME]"", tenantClientReferenceId);
modifiedFileContents = modifiedFileContents.replace(""[ENCRYPTED_PASSWORD]"", encryptedPassword);
modifiedFileContents = modifiedFileContents.replace(""[SERVER_ADDRESS]"", serverAddress);
modifiedFileContents = modifiedFileContents.replace(""[DATABASE_NAME]"", databaseName);
const formData = new FormData();
formData.append('contentToProcess', Buffer.from(modifiedFileContents), { filename: 'YFExport.xml' });
formData.append('importOptions', JSON.stringify([
{ itemIndex: 0, optionKey: ""SKIP"", optionValue: false },
{ itemIndex: 0, optionKey: ""OPTION"", optionValue: ""ADD"" }
]));
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'cache-control': 'no-cache'
};
try {
const response = await fetch(`${host}/api/rpc/import-export/import-content`, {
method: 'POST',
headers: headers,
body: formData
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const responseBody = await response.text();
console.log(responseBody);
} catch (error) {
console.error(""Error:"", error.message);
}
}
async function retrieveTenantIpIdForTenantName(host, token, tenantCode) {
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
try {
const response = await fetch(`${host}/api/orgs`, {
method: 'GET',
headers: headers
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const jsonResponse = await response.json();
const groups = jsonResponse.items;
for (const group of groups) {
if (group.clientRefId && tenantCode === group.clientRefId) {
return group.ipOrg;
}
}
console.log(""Tenant could not be found for code:"", tenantCode);
process.exit(-1);
} catch (error) {
console.error(""Error:"", error.message);
}
return null;
}
async function generateTokenForTenant(host, username, password, tenant) {
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
const body = JSON.stringify({
userName: username,
password: password,
clientOrgRef: tenant
});
try {
const response = await fetch(`${host}/api/refresh-tokens`, {
method: 'POST',
headers: headers,
body: body
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const jsonResponse = await response.json();
const accessToken = jsonResponse._embedded.accessToken.securityToken;
if (accessToken) {
console.log(`Access Token: ${accessToken}`);
return accessToken;
} else {
console.log(""Token not retrieved successfully"");
process.exit(-1);
}
} catch (error) {
console.error(""Error:"", error.message);
}
return null;
}
const importFileContents = `<?xml version=""1.0"" encoding=""UTF-8""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) -->
<data>
<info>
<exportversion>4</exportversion>
<exportsubversion>54</exportsubversion>
<transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>
<appversion>9.11</appversion>
<appsubversion>0.3</appsubversion>
<buildversion>20240607</buildversion>
<exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>
<systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>
</info>
<source>
<id>132641</id>
<sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>
<sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>
<databasePath>public</databasePath>
<userName>[USERNAME]</userName>
<password>[ENCRYPTED_PASSWORD]</password>
<connectionTypeCode>GENERICUSER</connectionTypeCode>
<connectionMethodCode>JDBC</connectionMethodCode>
<connectionDriver>org.postgresql.Driver</connectionDriver>
<databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>
<databaseTypeCode>POSTGRESQL</databaseTypeCode>
<minConnections>1</minConnections>
<maxConnections>5</maxConnections>
<connectionRefreshTime>180</connectionRefreshTime>
<connectionTimeOut>180</connectionTimeOut>
<accessCode>UNSECURE</accessCode>
<maxRowCount>10000</maxRowCount>
<maxAnalysisRowCount>0</maxAnalysisRowCount>
<broadcastPermitted>true</broadcastPermitted>
<subscribePermitted>true</subscribePermitted>
<dataProfileEnabled>true</dataProfileEnabled>
<localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>
<secondaryMinConnections>0</secondaryMinConnections>
<secondaryMaxConnections>0</secondaryMaxConnections>
<secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>
<secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>
<lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>
<sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>
<filterList/>
<sourceParameterList>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>DATABASE</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[DATABASE_NAME]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>HOSTNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[SERVER_ADDRESS]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>ISOLATIONLEVEL</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue/>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>PORT</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>5432</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>SOURCECLASSNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>
<documentId>0</documentId>
<userVisible>false</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>USESCHEMA</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>true</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>YF_DRIVER_SELECTION</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>org.postgresql.Driver</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
</sourceParameterList>
</source>
<translationDictionary/>
<refCodeDictionary/>
</data>
`;
main().catch(console.error); |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?php
function main($importFileContents) {
$host = ""http://localhost:8080/Yellowfin"";
$restUsername = ""admin@yellowfin.com.au"";
$restPassword = ""test"";
try {
$token = generateTokenForTenant($host, $restUsername, $restPassword, ""NEWCLIENT"");
$tenantClientReferenceId = ""NEWCLIENT"";
$databaseUserName = ""postgres"";
$encryptedPassword = ""NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw"";
$serverAddress = ""localhost"";
$databaseName = ""testdata"";
// Replace tokens with values
$modifiedFileContents = $importFileContents;
$modifiedFileContents = str_replace(""[USERNAME]"", $databaseUserName, $modifiedFileContents);
$modifiedFileContents = str_replace(""[TENANT_NAME]"", $tenantClientReferenceId, $modifiedFileContents);
$modifiedFileContents = str_replace(""[ENCRYPTED_PASSWORD]"", $encryptedPassword, $modifiedFileContents);
$modifiedFileContents = str_replace(""[SERVER_ADDRESS]"", $serverAddress, $modifiedFileContents);
$modifiedFileContents = str_replace(""[DATABASE_NAME]"", $databaseName, $modifiedFileContents);
// Build multipart entity
$multipartEntity = buildMultipartEntity($modifiedFileContents);
// Make HTTP request
$response = sendMultipartRequest($host, $token, $multipartEntity);
echo $response;
} catch (Exception $e) {
echo ""Error: "" . $e->getMessage();
}
}
function generateTokenForTenant($host, $username, $password, $tenant) {
// Generate nonce
$nonce = mt_rand();
// Create request body
$requestBody = json_encode(array(
""userName"" => $username,
""password"" => $password,
""clientOrgRef"" => $tenant
));
// Create request headers
$headers = array(
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
);
$response = httpRequest('POST', ""$host/api/refresh-tokens"", $headers, $requestBody);
// Parse JSON response
$jsonResponse = json_decode($response, true);
// Get access token from response
if (isset($jsonResponse[""_embedded""][""accessToken""][""securityToken""])) {
$accessToken = $jsonResponse[""_embedded""][""accessToken""][""securityToken""];
echo ""Access Token: "" . $accessToken;
return $accessToken;
} else {
throw new Exception(""Token not retrieved successfully"");
}
}
function buildMultipartEntity($fileContents) {
// Build multipart entity
$boundary = uniqid();
$multipartBody = ""--$boundary\r\n"";
$multipartBody .= 'Content-Disposition: form-data; name=""contentToProcess""; filename=""YFExport.xml""' . ""\r\n"";
$multipartBody .= ""Content-Type: application/xml\r\n\r\n"";
$multipartBody .= $fileContents . ""\r\n"";
$multipartBody .= ""--$boundary\r\n"";
$multipartBody .= 'Content-Disposition: form-data; name=""importOptions""' . ""\r\n"";
$multipartBody .= ""Content-Type: application/json\r\n\r\n"";
$multipartBody .= '[{ ""itemIndex"": 0, ""optionKey"": ""SKIP"", ""optionValue"": false }, { ""itemIndex"": 0, ""optionKey"": ""OPTION"", ""optionValue"": ""ADD"" }]' . ""\r\n"";
$multipartBody .= ""--$boundary--"";
return $multipartBody;
}
function sendMultipartRequest($host, $token, $multipartBody) {
$headers = array(
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . mt_rand() . ', token=' . $token,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: multipart/form-data; boundary=' . substr($multipartBody, 2, strpos($multipartBody, ""\r\n"") - 2),
'cache-control: no-cache'
);
try {
$response = httpRequest('POST', ""$host/api/rpc/import-export/import-content"", $headers, $multipartBody);
return $response;
} catch (Exception $e) {
throw new Exception(""Error sending request: "" . $e->getMessage());
}
}
function httpRequest($method, $url, $headers, $data = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception('Error: ' . curl_error($ch));
}
curl_close($ch);
return $response;
}
$importFileContents = ""<?xml version=\""1.0\"" encoding=\""UTF-8\""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) -->
<data>
<info>
<exportversion>4</exportversion>
<exportsubversion>54</exportsubversion>
<transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>
<appversion>9.11</appversion>
<appsubversion>0.3</appsubversion>
<buildversion>20240607</buildversion>
<exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>
<systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>
</info>
<source>
<id>132641</id>
<sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>
<sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>
<databasePath>public</databasePath>
<userName>[USERNAME]</userName>
<password>[ENCRYPTED_PASSWORD]</password>
<connectionTypeCode>GENERICUSER</connectionTypeCode>
<connectionMethodCode>JDBC</connectionMethodCode>
<connectionDriver>org.postgresql.Driver</connectionDriver>
<databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>
<databaseTypeCode>POSTGRESQL</databaseTypeCode>
<minConnections>1</minConnections>
<maxConnections>5</maxConnections>
<connectionRefreshTime>180</connectionRefreshTime>
<connectionTimeOut>180</connectionTimeOut>
<accessCode>UNSECURE</accessCode>
<maxRowCount>10000</maxRowCount>
<maxAnalysisRowCount>0</maxAnalysisRowCount>
<broadcastPermitted>true</broadcastPermitted>
<subscribePermitted>true</subscribePermitted>
<dataProfileEnabled>true</dataProfileEnabled>
<localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>
<secondaryMinConnections>0</secondaryMinConnections>
<secondaryMaxConnections>0</secondaryMaxConnections>
<secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>
<secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>
<lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>
<sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>
<filterList/>
<sourceParameterList>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>DATABASE</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[DATABASE_NAME]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>HOSTNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[SERVER_ADDRESS]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>ISOLATIONLEVEL</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue/>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>PORT</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>5432</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>SOURCECLASSNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>
<documentId>0</documentId>
<userVisible>false</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>USESCHEMA</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>true</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>YF_DRIVER_SELECTION</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>org.postgresql.Driver</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
</sourceParameterList>
</source>
<translationDictionary/>
<refCodeDictionary/>
</data>
"";
main($importFileContents);
?> |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
import json
import random
import time
import requests
from requests.exceptions import RequestException
def main():
host = ""http://localhost:8080/Yellowfin""
rest_username = ""admin@yellowfin.com.au""
rest_password = ""test""
tenant_client_reference_id = ""NEWCLIENT""
database_user_name = ""postgres""
encrypted_password = ""NDliYzg3NGItMDVjJVY8ywTSdIE3D1zdGplLLBUcEFqw""
server_address = ""localhost""
database_name = ""testdata""
try:
token = generate_token(host, rest_username, rest_password, tenant_client_reference_id)
tenant_id = retrieve_tenant_id_for_tenant_name(host, token, tenant_client_reference_id)
print(""Tenant Id:"", tenant_id)
# Replace tokens with values
modified_file_contents = import_file_contents.replace(""[USERNAME]"", database_user_name) \
.replace(""[TENANT_NAME]"", tenant_client_reference_id) \
.replace(""[ENCRYPTED_PASSWORD]"", encrypted_password) \
.replace(""[SERVER_ADDRESS]"", server_address) \
.replace(""[DATABASE_NAME]"", database_name)
multipart_entity = MultipartEncoder(
fields={
'contentToProcess': ('YFExport.xml', modified_file_contents, 'application/xml'),
'importOptions': json.dumps([
{""itemIndex"": 0, ""optionKey"": ""SKIP"", ""optionValue"": False},
{""itemIndex"": 0, ""optionKey"": ""OPTION"", ""optionValue"": ""ADD""}
])
}
)
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': multipart_entity.content_type,
'cache-control': 'no-cache'
}
response = requests.post(f'{host}/api/rpc/import-export/import-content', headers=headers, data=multipart_entity.to_string())
print(f""Content-Type: {multipart_entity.content_type}"")
print(response.text)
except RequestException as e:
print(f""Request Exception: {e}"")
def generate_token(host, username, password, tenant):
request_body = json.dumps({
""userName"": username,
""password"": password,
""clientOrgRef"": tenant
})
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
response = requests.post(f'{host}/api/refresh-tokens', headers=headers, data=request_body)
if response.status_code == 200:
json_response = response.json()
access_token = json_response[""_embedded""][""accessToken""][""securityToken""]
print(""Access Token:"", access_token)
return access_token
else:
raise Exception(""Token not retrieved successfully"")
def retrieve_tenant_id_for_tenant_name(host, token, tenant_code):
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
response = requests.get(f'{host}/api/orgs', headers=headers)
if response.status_code == 200:
json_data = response.json()
items = json_data.get('items', [])
for item in items:
if 'clientRefId' in item and item['clientRefId'] == tenant_code:
return item['ipOrg']
print(f""Tenant could not be found for code: {tenant_code}"")
exit(-1)
else:
raise RequestException(f""Failed to retrieve tenant id. Status code: {response.status_code}"")
class MultipartEncoder:
def __init__(self, fields):
self.boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
self.content_type = f'multipart/form-data; boundary={self.boundary}'
self.data = self.encode(fields)
def encode(self, fields):
lines = []
for key, value in fields.items():
lines.append(f'--{self.boundary}')
if isinstance(value, tuple): # file data
filename, data, content_type = value
lines.append(f'Content-Disposition: form-data; name=""{key}""; filename=""{filename}""')
lines.append(f'Content-Type: {content_type}')
lines.append('')
lines.append(data)
else: # regular form field
lines.append(f'Content-Disposition: form-data; name=""{key}""')
lines.append('')
lines.append(value)
lines.append(f'--{self.boundary}--')
lines.append('')
return '\r\n'.join(lines)
def to_string(self):
return self.data
import_file_contents = '''<?xml version=""1.0"" encoding=""UTF-8""?><!-- Yellowfin export file --><!-- Generated at 2024-06-07 12:56 AEST (+1000) -->
<data>
<info>
<exportversion>4</exportversion>
<exportsubversion>54</exportsubversion>
<transferHeaderUUID>c072afce-d02a-4b2c-ae06-c3b62c8d6ea8</transferHeaderUUID>
<appversion>9.11</appversion>
<appsubversion>0.3</appsubversion>
<buildversion>20240607</buildversion>
<exportdate>2024-06-07 12:56 AEST (+1000)</exportdate>
<systemid>9e/Rsd4Jf6UwZGq/5Q8Ej1Giviw=</systemid>
</info>
<source>
<id>132641</id>
<sourceName>PostgreSQL Connection for [TENANT_NAME]</sourceName>
<sourceDescription>PostgreSQL Connection for [TENANT_NAME]</sourceDescription>
<databasePath>public</databasePath>
<userName>[USERNAME]</userName>
<password>[ENCRYPTED_PASSWORD]</password>
<connectionTypeCode>GENERICUSER</connectionTypeCode>
<connectionMethodCode>JDBC</connectionMethodCode>
<connectionDriver>org.postgresql.Driver</connectionDriver>
<databaseURL>jdbc:postgresql://[SERVER_ADDRESS]:5432/[DATABASE_NAME]></databaseURL>
<databaseTypeCode>POSTGRESQL</databaseTypeCode>
<minConnections>1</minConnections>
<maxConnections>5</maxConnections>
<connectionRefreshTime>180</connectionRefreshTime>
<connectionTimeOut>180</connectionTimeOut>
<accessCode>UNSECURE</accessCode>
<maxRowCount>10000</maxRowCount>
<maxAnalysisRowCount>0</maxAnalysisRowCount>
<broadcastPermitted>true</broadcastPermitted>
<subscribePermitted>true</subscribePermitted>
<dataProfileEnabled>true</dataProfileEnabled>
<localTimezoneCode>AUSTRALIA/LORD_HOWE</localTimezoneCode>
<secondaryMinConnections>0</secondaryMinConnections>
<secondaryMaxConnections>0</secondaryMaxConnections>
<secondaryConnectionRefreshTime>0</secondaryConnectionRefreshTime>
<secondaryConnectionTimeOut>0</secondaryConnectionTimeOut>
<lastModifiedGMTDateTime>20240607025556.000000</lastModifiedGMTDateTime>
<sourceUUID>7d7543c0-e9c7-4a80-ab14-73181e4d0694</sourceUUID>
<filterList/>
<sourceParameterList>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>DATABASE</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[DATABASE_NAME]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>HOSTNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>[SERVER_ADDRESS]</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>ISOLATIONLEVEL</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue/>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>PORT</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>5432</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>SOURCECLASSNAME</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>com.hof.sources.JDBCSourcePlatformImplementation</parameterValue>
<documentId>0</documentId>
<userVisible>false</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>USESCHEMA</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>true</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
<sourceParameter>
<id>0</id>
<parameterTypeCode>TEXT</parameterTypeCode>
<parameterKey>YF_DRIVER_SELECTION</parameterKey>
<parameterIndex>0</parameterIndex>
<parameterValue>org.postgresql.Driver</parameterValue>
<documentId>0</documentId>
<userVisible>true</userVisible>
</sourceParameter>
</sourceParameterList>
</source>
<translationDictionary/>
<refCodeDictionary/>
</data>
'''
if __name__ == ""__main__"":
main() |
Create a new datasource via the datasource service
A datasource can be created directly via the REST API using the POST /api/data-sources end-point, Create Data Source.
This takes a datasource model of this format:
Code Block |
---|
{
"sourceName": "Client Database",
"sourceDescription": "",
"sourceType": "POSTGRESQL",
"connectionType": "JDBC",
"connectionTypeCode": "GENERICUSER",
"connectionDriver": "org.postgresql.Driver",
"connectionString": "jdbc:postgresql://192.168.1.100:5432/testdata",
"connectionTimeout": 180,
"userName": "postgres",
"minimumConnections": 1,
"maximumConnections": 5,
"refreshTime": 180,
"timezone": "AUSTRALIA/SYDNEY",
"accessLevelCode": "UNSECURE",
"maxRows": 10000,
"maxAnalysisRows": 0,
"inheritChildSourceFilters": false,
"sourceLogIndicator": false,
"sourceOptions": [
{
"optionKey": "ISOLATIONLEVEL",
"optionValue": "1.0",
"valueDataType": "1"
},
{
"optionKey": "USESCHEMA",
"optionValue": "true",
"valueDataType": "6"
},
{
"optionKey": "HOSTNAME",
"optionValue": "192.168.1.100",
"valueDataType": "2"
},
{
"optionKey": "PORT",
"optionValue": "5432",
"valueDataType": "1"
},
{
"optionKey": "DATABASE",
"optionValue": "testdata",
"valueDataType": "2"
},
{
"optionKey": "YF_DRIVER_SELECTION",
"optionValue": "org.postgresql.Driver",
"valueDataType": "2"
}
]
} |
The main body of the model is similar to the model returned by the GET /api/data-sources end-point. If creating a new source similar to the Primary Organization datasource, the data returned by GET /api/data-sources can be used as a template.
The sourceOptions in the creation model differ depending on the database type and are representative of the options that are exposed by the connection wizard when connecting to a new datasource.
It should be noted that although the connectionString is available in the model body, this is regenerated based on the source options when the datasource is created.
The following examples illustrate how to create a new datasource via the POST /api/data-sources end-point:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package rest.code.examples;
import java.io.IOException;
import java.util.Random;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Create a datasource using the Yellowfin REST API
*/
public class CreateADataSource {
public static void main(String[] args) throws Exception {
String host = ""http://localhost:8080/yellowfinHead"";
String restUsername = ""admin@yellowfin.com.au"";
String restPassword = ""test"";
String createDataSourcePayload = ""{\n""
+ "" \""sourceName\"": \""PostgreSQL Database Created Via Import\"",\n""
+ "" \""sourceDescription\"": \""\"",\n""
+ "" \""sourceType\"": \""POSTGRESQL\"",\n""
+ "" \""connectionType\"": \""JDBC\"",\n""
+ "" \""connectionTypeCode\"": \""GENERICUSER\"",\n""
+ "" \""connectionDriver\"": \""org.postgresql.Driver\"",\n""
+ "" \""connectionString\"": \""jdbc:postgresql://192.168.1.100:5432/testdata\"",\n""
+ "" \""connectionTimeout\"": 180,\n""
+ "" \""userName\"": \""postgres\"",\n""
+ "" \""minimumConnections\"": 1,\n""
+ "" \""maximumConnections\"": 5,\n""
+ "" \""refreshTime\"": 180,\n""
+ "" \""timezone\"": \""AUSTRALIA/SYDNEY\"",\n""
+ "" \""accessLevelCode\"": \""UNSECURE\"",\n""
+ "" \""maxRows\"": 10000,\n""
+ "" \""maxAnalysisRows\"": 0,\n""
+ "" \""inheritChildSourceFilters\"": false,\n""
+ "" \""sourceLogIndicator\"": false,\n""
+ "" \""sourceOptions\"": [\n""
+ ""{\n""
+ ""\""optionKey\"": \""ISOLATIONLEVEL\"",\n""
+ ""\""optionValue\"": \""1.0\"",\n""
+ ""\""valueDataType\"": \""1\""\n""
+ ""},\n""
+ ""{\n""
+ ""\""optionKey\"": \""USESCHEMA\"",\n""
+ ""\""optionValue\"": \""true\"",\n""
+ ""\""valueDataType\"": \""6\""\n""
+ ""},\n""
+ ""{\n""
+ ""\""optionKey\"": \""HOSTNAME\"",\n""
+ ""\""optionValue\"": \""192.168.1.100\"",\n""
+ ""\""valueDataType\"": \""2\""\n""
+ ""},\n""
+ ""{\n""
+ ""\""optionKey\"": \""PORT\"",\n""
+ ""\""optionValue\"": \""5432\"",\n""
+ ""\""valueDataType\"": \""1\""\n""
+ ""},\n""
+ ""{\n""
+ ""\""optionKey\"": \""DATABASE\"",\n""
+ ""\""optionValue\"": \""testdata\"",\n""
+ ""\""valueDataType\"": \""2\""\n""
+ ""},\n""
+ ""{\n""
+ ""\""optionKey\"": \""YF_DRIVER_SELECTION\"",\n""
+ ""\""optionValue\"": \""org.postgresql.Driver\"",\n""
+ ""\""valueDataType\"": \""2\""\n""
+ ""}\n""
+ "" ]\n""
+ ""}""
;
String token = generateToken(host, restUsername, restPassword);
System.out.println(""Payload: "" + createDataSourcePayload);
Content c = Request.post(host + ""/api/data-sources"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.bodyString(createDataSourcePayload, null)
.execute().returnContent();
System.out.print(c.asString());
}
public static String generateToken(String host, String username, String password) throws IOException {
Content c = Request.post(host + ""/api/refresh-tokens"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.bodyString(""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\""}"", null)
.execute().returnContent();
JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");
if (accessToken!=null) {
System.out.println(""Access Token: "" + accessToken);
} else {
System.out.println(""Token not retrieved successfully"");
System.exit(-1);
}
return accessToken.getAsString();
}
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace YellowfinAPIExamples
{
public class CreateADataSource
{
static async Task Main(string[] args)
{
string host = ""http://localhost:8080/Yellowfin"";
string restUsername = ""admin@yellowfin.com.au"";
string restPassword = ""test"";
string createDataSourcePayload = @""
{
""""sourceName"""": """"PostgreSQL Database Created Via Import"""",
""""sourceDescription"""": """""""",
""""sourceType"""": """"POSTGRESQL"""",
""""connectionType"""": """"JDBC"""",
""""connectionTypeCode"""": """"GENERICUSER"""",
""""connectionDriver"""": """"org.postgresql.Driver"""",
""""connectionString"""": """"jdbc:postgresql://192.168.1.100:5432/testdata"""",
""""connectionTimeout"""": 180,
""""userName"""": """"postgres"""",
""""minimumConnections"""": 1,
""""maximumConnections"""": 5,
""""refreshTime"""": 180,
""""timezone"""": """"AUSTRALIA/SYDNEY"""",
""""accessLevelCode"""": """"UNSECURE"""",
""""maxRows"""": 10000,
""""maxAnalysisRows"""": 0,
""""inheritChildSourceFilters"""": false,
""""sourceLogIndicator"""": false,
""""sourceOptions"""": [
{
""""optionKey"""": """"ISOLATIONLEVEL"""",
""""optionValue"""": """"1.0"""",
""""valueDataType"""": """"1""""
},
{
""""optionKey"""": """"USESCHEMA"""",
""""optionValue"""": """"true"""",
""""valueDataType"""": """"6""""
},
{
""""optionKey"""": """"HOSTNAME"""",
""""optionValue"""": """"192.168.1.100"""",
""""valueDataType"""": """"2""""
},
{
""""optionKey"""": """"PORT"""",
""""optionValue"""": """"5432"""",
""""valueDataType"""": """"1""""
},
{
""""optionKey"""": """"DATABASE"""",
""""optionValue"""": """"testdata"""",
""""valueDataType"""": """"2""""
},
{
""""optionKey"""": """"YF_DRIVER_SELECTION"""",
""""optionValue"""": """"org.postgresql.Driver"""",
""""valueDataType"""": """"2""""
}
]
}"";
string token = await GenerateToken(host, restUsername, restPassword);
Console.WriteLine(""Payload: "" + createDataSourcePayload);
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"", $""ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={new Random().NextInt64()}, token={token}"");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
var content = new StringContent(createDataSourcePayload, System.Text.Encoding.UTF8, ""application/json"");
HttpResponseMessage response = await httpClient.PostAsync($""{host}/api/data-sources"", content);
if (response.IsSuccessStatusCode)
{
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
else
{
Console.WriteLine(""Failed to create data source. Status code: "" + response.StatusCode);
}
}
}
static async Task<string> GenerateToken(string host, string restUsername, string restPassword)
{
using (var client = new HttpClient())
{
// Generate nonce
long nonce = new Random().NextInt64();
// Create HTTP request
var request = new HttpRequestMessage(HttpMethod.Post, $""{host}/api/refresh-tokens"");
request.Headers.Add(""Authorization"", $""YELLOWFIN ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}"");
request.Headers.Add(""Accept"", ""application/vnd.yellowfin.api-v1+json"");
request.Content = new StringContent(
JsonConvert.SerializeObject(new { userName = restUsername, password = restPassword }),
System.Text.Encoding.UTF8,
""application/json""
);
// Send request and get response
HttpResponseMessage response = await client.SendAsync(request);
string responseContent = await response.Content.ReadAsStringAsync();
// Parse JSON response
JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent);
string accessToken = jsonObject[""_embedded""][""accessToken""][""securityToken""].ToString();
if (!string.IsNullOrEmpty(accessToken))
{
Console.WriteLine(""Access Token: "" + accessToken);
}
else
{
Console.WriteLine(""Token not retrieved"");
Environment.Exit(-1);
}
return accessToken;
}
}
}
} |
Code Block | ||||
---|---|---|---|---|
| ||||
package main
import (
""bytes""
""encoding/json""
""fmt""
""io/ioutil""
""math/rand""
""net/http""
""time""
)
func main() {
host := ""http://localhost:8080/Yellowfin""
restUsername := ""admin@yellowfin.com.au""
restPassword := ""test""
createDataSourcePayload := `{
""sourceName"": ""PostgreSQL Database Created Via Import"",
""sourceDescription"": """",
""sourceType"": ""POSTGRESQL"",
""connectionType"": ""JDBC"",
""connectionTypeCode"": ""GENERICUSER"",
""connectionDriver"": ""org.postgresql.Driver"",
""connectionString"": ""jdbc:postgresql://192.168.1.100:5432/testdata"",
""connectionTimeout"": 180,
""userName"": ""postgres"",
""minimumConnections"": 1,
""maximumConnections"": 5,
""refreshTime"": 180,
""timezone"": ""AUSTRALIA/SYDNEY"",
""accessLevelCode"": ""UNSECURE"",
""maxRows"": 10000,
""maxAnalysisRows"": 0,
""inheritChildSourceFilters"": false,
""sourceLogIndicator"": false,
""sourceOptions"": [
{
""optionKey"": ""ISOLATIONLEVEL"",
""optionValue"": ""1.0"",
""valueDataType"": ""1""
},
{
""optionKey"": ""USESCHEMA"",
""optionValue"": ""true"",
""valueDataType"": ""6""
},
{
""optionKey"": ""HOSTNAME"",
""optionValue"": ""192.168.1.100"",
""valueDataType"": ""2""
},
{
""optionKey"": ""PORT"",
""optionValue"": ""5432"",
""valueDataType"": ""1""
},
{
""optionKey"": ""DATABASE"",
""optionValue"": ""testdata"",
""valueDataType"": ""2""
},
{
""optionKey"": ""YF_DRIVER_SELECTION"",
""optionValue"": ""org.postgresql.Driver"",
""valueDataType"": ""2""
}
]
}`
token, err := generateToken(host, restUsername, restPassword)
if err != nil {
fmt.Println(""Error generating token:"", err)
return
}
fmt.Println(""Payload:"", createDataSourcePayload)
client := &http.Client{}
req, err := http.NewRequest(""POST"", host+""/api/data-sources"", bytes.NewBuffer([]byte(createDataSourcePayload)))
if err != nil {
fmt.Println(""Error creating request:"", err)
return
}
nonce := rand.Int63()
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d, token=%s"", time.Now().UnixMilli(), nonce, token))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
fmt.Println(""Error sending request:"", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return
}
fmt.Println(string(body))
}
func generateToken(host, restUsername, restPassword string) (string, error) {
nonce := rand.Int63()
requestBody, err := json.Marshal(map[string]string{
""userName"": restUsername,
""password"": restPassword,
})
if err != nil {
fmt.Println(""Error marshaling request body:"", err)
return """", err
}
client := &http.Client{}
req, err := http.NewRequest(""POST"", host+""/api/refresh-tokens"", bytes.NewBuffer(requestBody))
if err != nil {
fmt.Println(""Error creating request:"", err)
return """", err
}
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d"", time.Now().UnixMilli(), nonce))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
fmt.Println(""Error sending request:"", err)
return """", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return """", err
}
var jsonResponse map[string]interface{}
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
fmt.Println(""Error parsing JSON response:"", err)
return """", err
}
accessToken, ok := jsonResponse[""_embedded""].(map[string]interface{})[""accessToken""].(map[string]interface{})[""securityToken""].(string)
if !ok {
fmt.Println(""Token not retrieved"")
return """", fmt.Errorf(""Token not retrieved successfully"")
}
return accessToken, nil
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
const fetch = require(""node-fetch"");
async function main() {
const host = ""http://localhost:8080/Yellowfin"";
const restUsername = ""admin@yellowfin.com.au"";
const restPassword = ""test"";
const createDataSourcePayload = `{
""sourceName"": ""PostgreSQL Database Created Via Import"",
""sourceDescription"": """",
""sourceType"": ""POSTGRESQL"",
""connectionType"": ""JDBC"",
""connectionTypeCode"": ""GENERICUSER"",
""connectionDriver"": ""org.postgresql.Driver"",
""connectionString"": ""jdbc:postgresql://192.168.1.100:5432/testdata"",
""connectionTimeout"": 180,
""userName"": ""postgres"",
""minimumConnections"": 1,
""maximumConnections"": 5,
""refreshTime"": 180,
""timezone"": ""AUSTRALIA/SYDNEY"",
""accessLevelCode"": ""UNSECURE"",
""maxRows"": 10000,
""maxAnalysisRows"": 0,
""inheritChildSourceFilters"": false,
""sourceLogIndicator"": false,
""sourceOptions"": [
{
""optionKey"": ""ISOLATIONLEVEL"",
""optionValue"": ""1.0"",
""valueDataType"": ""1""
},
{
""optionKey"": ""USESCHEMA"",
""optionValue"": ""true"",
""valueDataType"": ""6""
},
{
""optionKey"": ""HOSTNAME"",
""optionValue"": ""192.168.1.100"",
""valueDataType"": ""2""
},
{
""optionKey"": ""PORT"",
""optionValue"": ""5432"",
""valueDataType"": ""1""
},
{
""optionKey"": ""DATABASE"",
""optionValue"": ""testdata"",
""valueDataType"": ""2""
},
{
""optionKey"": ""YF_DRIVER_SELECTION"",
""optionValue"": ""org.postgresql.Driver"",
""valueDataType"": ""2""
}
]
}`;
const token = await generateToken(host, restUsername, restPassword);
if (!token) {
console.error(""Failed to retrieve access token"");
return;
}
console.log(""Payload:"", createDataSourcePayload);
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
try {
const response = await fetch(`${host}/api/data-sources`, {
method: 'POST',
headers: headers,
body: createDataSourcePayload
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const responseBody = await response.text();
console.log(responseBody);
} catch (error) {
console.error(""Error:"", error.message);
}
}
async function generateToken(host, restUsername, restPassword) {
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
const body = JSON.stringify({
userName: restUsername,
password: restPassword
});
try {
const response = await fetch(`${host}/api/refresh-tokens`, {
method: 'POST',
headers: headers,
body: body
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const jsonResponse = await response.json();
const accessToken = jsonResponse._embedded.accessToken.securityToken;
if (accessToken) {
console.log(`Access Token: ${accessToken}`);
} else {
console.log(""Token not retrieved"");
}
return accessToken;
} catch (error) {
console.error(""Error:"", error.message);
}
return null;
}
main(); |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?php
function main() {
$host = ""http://localhost:8080/Yellowfin"";
$restUsername = ""admin@yellowfin.com.au"";
$restPassword = ""test"";
$createDataSourcePayload = '{
""sourceName"": ""PostgreSQL Database Created Via Import"",
""sourceDescription"": """",
""sourceType"": ""POSTGRESQL"",
""connectionType"": ""JDBC"",
""connectionTypeCode"": ""GENERICUSER"",
""connectionDriver"": ""org.postgresql.Driver"",
""connectionString"": ""jdbc:postgresql://192.168.1.100:5432/testdata"",
""connectionTimeout"": 180,
""userName"": ""postgres"",
""minimumConnections"": 1,
""maximumConnections"": 5,
""refreshTime"": 180,
""timezone"": ""AUSTRALIA/SYDNEY"",
""accessLevelCode"": ""UNSECURE"",
""maxRows"": 10000,
""maxAnalysisRows"": 0,
""inheritChildSourceFilters"": false,
""sourceLogIndicator"": false,
""sourceOptions"": [
{
""optionKey"": ""ISOLATIONLEVEL"",
""optionValue"": ""1.0"",
""valueDataType"": ""1""
},
{
""optionKey"": ""USESCHEMA"",
""optionValue"": ""true"",
""valueDataType"": ""6""
},
{
""optionKey"": ""HOSTNAME"",
""optionValue"": ""192.168.1.100"",
""valueDataType"": ""2""
},
{
""optionKey"": ""PORT"",
""optionValue"": ""5432"",
""valueDataType"": ""1""
},
{
""optionKey"": ""DATABASE"",
""optionValue"": ""testdata"",
""valueDataType"": ""2""
},
{
""optionKey"": ""YF_DRIVER_SELECTION"",
""optionValue"": ""org.postgresql.Driver"",
""valueDataType"": ""2""
}
]
}';
try {
$token = generateToken($host, $restUsername, $restPassword);
} catch (Exception $e) {
echo ""Error generating token: "" . $e->getMessage();
return;
}
echo ""Payload: "" . $createDataSourcePayload . ""\n"";
$nonce = mt_rand();
$headers = array(
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce . ', token=' . $token,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
);
try {
$response = httpRequest('POST', ""$host/api/data-sources"", $headers, $createDataSourcePayload);
echo $response;
} catch (Exception $e) {
echo ""Error sending request: "" . $e->getMessage();
}
}
function generateToken($host, $restUsername, $restPassword) {
// Generate nonce
$nonce = mt_rand();
// Create request body
$requestBody = json_encode(array(
""userName"" => $restUsername,
""password"" => $restPassword
));
// Create request headers
$headers = array(
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
);
$response = httpRequest('POST', ""$host/api/refresh-tokens"", $headers, $requestBody);
// Parse JSON response
$jsonResponse = json_decode($response, true);
// Get access token from response
if (isset($jsonResponse[""_embedded""][""accessToken""][""securityToken""])) {
$accessToken = $jsonResponse[""_embedded""][""accessToken""][""securityToken""];
echo ""Access Token: "" . $accessToken;
return $accessToken;
} else {
throw new Exception(""Token not retrieved successfully"");
}
}
function httpRequest($method, $url, $headers, $data = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception('Error: ' . curl_error($ch));
}
curl_close($ch);
return $response;
}
main();
?> |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
import json
import random
import time
import requests
def main():
host = ""http://localhost:8080/Yellowfin""
rest_username = ""admin@yellowfin.com.au""
rest_password = ""test""
create_data_source_payload = '''
{
""sourceName"": ""PostgreSQL Database Created Via Import"",
""sourceDescription"": """",
""sourceType"": ""POSTGRESQL"",
""connectionType"": ""JDBC"",
""connectionTypeCode"": ""GENERICUSER"",
""connectionDriver"": ""org.postgresql.Driver"",
""connectionString"": ""jdbc:postgresql://192.168.1.100:5432/testdata"",
""connectionTimeout"": 180,
""userName"": ""postgres"",
""minimumConnections"": 1,
""maximumConnections"": 5,
""refreshTime"": 180,
""timezone"": ""AUSTRALIA/SYDNEY"",
""accessLevelCode"": ""UNSECURE"",
""maxRows"": 10000,
""maxAnalysisRows"": 0,
""inheritChildSourceFilters"": false,
""sourceLogIndicator"": false,
""sourceOptions"": [
{
""optionKey"": ""ISOLATIONLEVEL"",
""optionValue"": ""1.0"",
""valueDataType"": ""1""
},
{
""optionKey"": ""USESCHEMA"",
""optionValue"": ""true"",
""valueDataType"": ""6""
},
{
""optionKey"": ""HOSTNAME"",
""optionValue"": ""192.168.1.100"",
""valueDataType"": ""2""
},
{
""optionKey"": ""PORT"",
""optionValue"": ""5432"",
""valueDataType"": ""1""
},
{
""optionKey"": ""DATABASE"",
""optionValue"": ""testdata"",
""valueDataType"": ""2""
},
{
""optionKey"": ""YF_DRIVER_SELECTION"",
""optionValue"": ""org.postgresql.Driver"",
""valueDataType"": ""2""
}
]
}
'''
try:
token = generate_token(host, rest_username, rest_password)
except Exception as e:
print(f""Error generating token: {e}"")
return
print(""Payload:"", create_data_source_payload)
nonce = random.randint(0, 2**63 - 1)
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={nonce}, token={token}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
try:
response = requests.post(f""{host}/api/data-sources"", headers=headers, data=create_data_source_payload)
response.raise_for_status()
print(response.text)
except requests.RequestException as e:
print(f""Error sending request: {e}"")
def generate_token(host, rest_username, rest_password):
nonce = random.randint(0, 2**63 - 1)
# Create request body
request_body = json.dumps({
""userName"": rest_username,
""password"": rest_password
})
# Create request headers
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={nonce}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
try:
response = requests.post(f""{host}/api/refresh-tokens"", headers=headers, data=request_body)
response.raise_for_status()
json_response = response.json()
access_token = json_response[""_embedded""][""accessToken""][""securityToken""]
print(""Access Token:"", access_token)
return access_token
except requests.RequestException as e:
raise Exception(""Token not retrieved successfully"") from e
if __name__ == ""__main__"":
main() |
List Data Sources
A list of datasources can be retrieved with the GET /api/data-sources end-point, Get All Data Sources. This will return a datasource model of the following form:
Code Block |
---|
{
"sourceId": 132780,
"sourceName": "PostgreSQL Connection for NEWCLIENT",
"sourceDescription": "PostgreSQL Connection for NEWCLIENT",
"sourceType": "POSTGRESQL",
"connectionType": "JDBC",
"connectionTypeCode": "GENERICUSER",
"connectionDriver": "org.postgresql.Driver",
"connectionPath": "public",
"connectionString": "jdbc:postgresql://localhost:5432/testdata",
"connectionTimeout": 180,
"userName": "postgres",
"minimumConnections": 1,
"maximumConnections": 5,
"refreshTime": 180,
"timezone": "AUSTRALIA/LORD_HOWE",
"accessLevelCode": "UNSECURE",
"maxRows": 10000,
"maxAnalysisRows": 0,
"inheritChildSourceFilters": false,
"sourceLogIndicator": false
} |
This service can be used to find the internal integer identifier for the datasource (sourceId) for a given data source name.
The following code examples illustrate how to retrieve a list of data sources from the system:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package rest.code.examples;
import java.io.IOException;
import java.util.Random;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* List DataSources using the Yellowfin REST API
*/
public class ListDataSources {
public static void main(String[] args) throws Exception {
System.out.print(""List Datasources"");
String host = ""http://localhost:8080/Yellowfin"";
String restUsername = ""admin@yellowfin.com.au"";
String restPassword = ""test"";
String token = generateToken(host, restUsername, restPassword);
Content c = Request.get(host + ""/api/data-sources"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.execute().returnContent();
System.out.print(c.asString());
}
/*
* This function generates an access token for a user that will grant them access to
* call REST API endpoints.
*/
public static String generateToken(String host, String username, String password) throws IOException {
Content c = Request.post(host + ""/api/refresh-tokens"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.bodyString(""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\""}"", null)
.execute().returnContent();
JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");
if (accessToken!=null) {
System.out.println(""Access Token: "" + accessToken);
} else {
System.out.println(""Token not retrieved successfully"");
System.exit(-1);
}
return accessToken.getAsString();
}
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace YellowfinAPIExamples
{
public class ListDataSources
{
static async Task Main(string[] args)
{
string host = ""http://localhost:8080/Yellowfin"";
string restUsername = ""admin@yellowfin.com.au"";
string restPassword = ""test"";
string token = await GenerateToken(host, restUsername, restPassword);
Console.WriteLine(""List Datasources"");
using (var httpClient = new HttpClient())
{
long nonce = new Random().NextInt64();
// Setup request headers
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"", $""ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}, token={token}"");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
// Make GET request to retrieve data sources
HttpResponseMessage response = await httpClient.GetAsync($""{host}/api/data-sources"");
if (response.IsSuccessStatusCode)
{
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
else
{
Console.WriteLine($""Failed to retrieve data sources. Status code: {response.StatusCode}"");
}
}
}
static async Task<string> GenerateToken(string host, string username, string password)
{
using (var client = new HttpClient())
{
// Generate nonce
long nonce = new Random().NextInt64();
// Create HTTP request
var request = new HttpRequestMessage(HttpMethod.Post, $""{host}/api/refresh-tokens"");
request.Headers.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"", $""ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}"");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
request.Content = new StringContent(
JsonConvert.SerializeObject(new { userName = username, password = password }),
System.Text.Encoding.UTF8,
""application/json""
);
// Send request and get response
HttpResponseMessage response = await client.SendAsync(request);
string responseContent = await response.Content.ReadAsStringAsync();
// Parse JSON response
JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent);
string accessToken = jsonObject[""_embedded""][""accessToken""][""securityToken""].ToString();
if (!string.IsNullOrEmpty(accessToken))
{
Console.WriteLine(""Access Token: "" + accessToken);
}
else
{
Console.WriteLine(""Token not retrieved successfully"");
Environment.Exit(-1);
}
return accessToken;
}
}
}
} |
Code Block | ||||
---|---|---|---|---|
| ||||
package main
import (
""bytes""
""encoding/json""
""fmt""
""io/ioutil""
""math/rand""
""net/http""
""time""
)
func main() {
host := ""http://localhost:8080/Yellowfin""
restUsername := ""admin@yellowfin.com.au""
restPassword := ""test""
token, err := generateToken(host, restUsername, restPassword)
if err != nil {
fmt.Println(""Error generating token:"", err)
return
}
fmt.Println(""List Datasources"")
client := &http.Client{}
req, err := http.NewRequest(""GET"", host+""/api/data-sources"", nil)
if err != nil {
fmt.Println(""Error creating request:"", err)
return
}
nonce := rand.Int63()
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d, token=%s"", time.Now().UnixMilli(), nonce, token))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
fmt.Println(""Error sending request:"", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return
}
fmt.Println(string(body))
}
func generateToken(host, username, password string) (string, error) {
// Generate nonce
nonce := rand.Int63()
// Create request body
requestBody, err := json.Marshal(map[string]string{
""userName"": username,
""password"": password,
})
if err != nil {
fmt.Println(""Error marshaling request body:"", err)
return """", err
}
// Create HTTP client
client := &http.Client{}
// Create HTTP request
request, err := http.NewRequest(""POST"", host+""/api/refresh-tokens"", bytes.NewBuffer(requestBody))
if err != nil {
fmt.Println(""Error creating request:"", err)
return """", err
}
// Add request headers
request.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d"", time.Now().UnixMilli(), nonce))
request.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
request.Header.Set(""Content-Type"", ""application/json"")
// Send HTTP request
response, err := client.Do(request)
if err != nil {
fmt.Println(""Error sending request:"", err)
return """", err
}
defer response.Body.Close()
// Read response body
responseBody, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return """", err
}
// Parse JSON response
var jsonResponse map[string]interface{}
err = json.Unmarshal(responseBody, &jsonResponse)
if err != nil {
fmt.Println(""Error parsing JSON response:"", err)
return """", err
}
// Get access token from response
accessToken, ok := jsonResponse[""_embedded""].(map[string]interface{})[""accessToken""].(map[string]interface{})[""securityToken""].(string)
if !ok {
fmt.Println(""Token not retrieved"")
return """", fmt.Errorf(""Token not retrieved successfully"")
}
return accessToken, nil
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
const fetch = require(""node-fetch"");
async function main() {
const host = ""http://localhost:8080/Yellowfin"";
const restUsername = ""admin@yellowfin.com.au"";
const restPassword = ""test"";
const createUserPayload = JSON.stringify([{
userId: ""user1"",
emailAddress: ""user1@yellowfin.com.au"",
roleCode: ""Consumer & Collaborator"",
password: ""test"",
firstName: ""User"",
lastName: ""One"",
languageCode: ""EN"",
timeZoneCode: ""AUSTRALIA/SYDNEY""
}]);
const token = await generateToken(host, restUsername, restPassword);
if (!token) {
console.error(""Failed to retrieve access token"");
return;
}
console.log(""Payload:"", createUserPayload);
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
try {
const response = await fetch(`${host}/api/data-sources`, {
method: 'GET',
headers: headers
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const responseBody = await response.text();
console.log(responseBody);
} catch (error) {
console.error(""Error:"", error.message);
}
}
async function generateToken(host, restUsername, restPassword) {
// Generate nonce
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
// Create request headers
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
// Create request body
const body = JSON.stringify({
userName: restUsername,
password: restPassword
});
try {
// Make POST request
const response = await fetch(`${host}/api/refresh-tokens`, {
method: 'POST',
headers: headers,
body: body
});
// Check if request was successful
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
// Parse JSON response
const jsonResponse = await response.json();
const accessToken = jsonResponse._embedded.accessToken.securityToken;
if (accessToken) {
console.log(`Access Token: ${accessToken}`);
} else {
console.log(""Token not retrieved"");
}
return accessToken;
} catch (error) {
console.error(""Error:"", error.message);
}
return null;
}
main(); |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?php
function main() {
$host = ""http://localhost:8080/Yellowfin"";
$restUsername = ""admin@yellowfin.com.au"";
$restPassword = ""test"";
$createUserPayload = json_encode(array(
array(
""userId"" => ""user1"",
""emailAddress"" => ""user1@yellowfin.com.au"",
""roleCode"" => ""Consumer & Collaborator"",
""password"" => ""test"",
""firstName"" => ""User"",
""lastName"" => ""One"",
""languageCode"" => ""EN"",
""timeZoneCode"" => ""AUSTRALIA/SYDNEY""
)
));
try {
$token = generateToken($host, $restUsername, $restPassword);
} catch (Exception $e) {
echo ""Error generating token: "" . $e->getMessage();
return;
}
echo ""Payload: "" . $createUserPayload . ""\n"";
$nonce = mt_rand();
$headers = array(
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce . ', token=' . $token,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
);
try {
$response = httpRequest('GET', ""$host/api/data-sources"", $headers);
echo $response;
} catch (Exception $e) {
echo ""Error listing data sources: "" . $e->getMessage();
}
}
function generateToken($host, $restUsername, $restPassword) {
// Generate nonce
$nonce = mt_rand();
// Create request body
$requestBody = json_encode(array(
""userName"" => $restUsername,
""password"" => $restPassword
));
// Create request headers
$headers = array(
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
);
$response = httpRequest('POST', ""$host/api/refresh-tokens"", $headers, $requestBody);
// Parse JSON response
$jsonResponse = json_decode($response, true);
// Get access token from response
if (isset($jsonResponse[""_embedded""][""accessToken""][""securityToken""])) {
$accessToken = $jsonResponse[""_embedded""][""accessToken""][""securityToken""];
echo ""Access Token: "" . $accessToken;
return $accessToken;
} else {
throw new Exception(""Token not retrieved successfully"");
}
}
function httpRequest($method, $url, $headers, $data = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception('Error: ' . curl_error($ch));
}
curl_close($ch);
return $response;
}
main();
?> |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
import json
import random
import time
import requests
def main():
host = ""http://localhost:8080/Yellowfin""
rest_username = ""admin@yellowfin.com.au""
rest_password = ""test""
try:
token = generate_token(host, rest_username, rest_password)
list_data_sources(host, token)
except Exception as e:
print(f""Error: {e}"")
def list_data_sources(host, token):
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
try:
response = requests.get(f'{host}/api/data-sources', headers=headers)
response.raise_for_status()
print(response.text)
except requests.RequestException as e:
print(f""Error listing data sources: {e}"")
def generate_token(host, username, password):
nonce = random.randint(0, 2 ** 63 - 1)
request_body = json.dumps({
""userName"": username,
""password"": password
})
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={nonce}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
try:
response = requests.post(f'{host}/api/refresh-tokens', headers=headers, data=request_body)
response.raise_for_status()
json_response = response.json()
access_token = json_response[""_embedded""][""accessToken""][""securityToken""]
print(""Access Token:"", access_token)
return access_token
except requests.RequestException as e:
print(f""Token retrieval error: {e}"")
raise Exception(""Token not retrieved successfully"")
if __name__ == ""__main__"":
main() |
Attach a Client Datasource to a Primary Org Datasource for Source Substitution
A Client Datasource can be linked to a Primary Org Datasource (for use with Source Substitution) using the POST /api/data-sources/{primaryOrgSourceId}/client-data-sources/?clientSourceId={clientOrgSourceId} end-point, Add Client Data Source.
Where {primaryOrgSourceId} is the integer identifier for the primary organization datasource, and {clientOrgSourceId} is the integer identifier for the client org datasource to link.
The following examples illustrate how to link a Client Datasource (identified by its name) to a Primary Org Datasource (identified by its name):
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package rest.code.examples;
import java.io.IOException;
import java.util.Random;
import org.apache.hc.client5.http.fluent.Content;
import org.apache.hc.client5.http.fluent.Request;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Attach a Client Datasource to Primary Org Source for Source Substitution using the Yellowfin REST API
*/
public class AttachClientDatasourceToPrimarySource {
public static void main(String[] args) throws Exception {
System.out.print(""Attach a Tenant Source to Primary Org Source for Source Substitution"");
String host = ""http://localhost:8080/Yellowfin"";
String restUsername = ""admin@yellowfin.com.au"";
String restPassword = ""test"";
String primarySourceName = ""PostgreSQL Connection at Primary Org"";
String clientSourceName = ""PostgreSQL Connection for NEWCLIENT"";
String clientOrgReference = ""NEWCLIENT"";
String clientToken = generateToken(host, restUsername, restPassword, clientOrgReference);
Integer clientOrgSourceId = findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName);
System.out.println(""Client Org Source Id: "" + clientOrgSourceId);
String primaryToken = generateToken(host, restUsername, restPassword, null);
Integer primaryOrgSourceId = findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName);
System.out.println(""Primary Org Source Id: "" + clientOrgSourceId);
Content c = Request.get(host + ""/api/data-sources/"" + primaryOrgSourceId + ""/client-data-sources/?clientSourceId="" + clientOrgSourceId)
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + primaryToken)
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.execute().returnContent();
System.out.print(c.asString());
}
/*
* This function finds a datasource for a given datasource name
* call REST API endpoints.
*/
private static Integer findDataSourceForSourceNameAtClient(String host, String token, String sourceName) throws IOException {
Content c = Request.get(host + ""/api/data-sources"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong() + "", token="" + token)
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.execute().returnContent();
JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
JsonElement sourceList = jsonObject.get(""items"");
JsonArray sources = sourceList.getAsJsonArray();
for (int i=0; i < sources.size(); i++ ) {
JsonObject source = sources.getAsJsonArray().get(i).getAsJsonObject();
if (sourceName.equals(source.get(""sourceName"").getAsString())) return source.get(""sourceId"").getAsInt();
}
System.out.println(""Data Source could not be found for name:"" + sourceName);
System.exit(-1);
return null;
}
/*
* This function generates an access token for a user that will grant them access to
* call REST API endpoints.
*/
public static String generateToken(String host, String username, String password, String tenantClientOrgRefId) throws IOException {
String tokenBody = ""{ \""userName\"": \""""+ username + ""\"",\""password\"": \""""+ password + ""\"""";
if (tenantClientOrgRefId!=null) {
tokenBody = tokenBody + "",\""clientOrgRef\"": \""""+ tenantClientOrgRefId + ""\"""";
}
tokenBody = tokenBody + ""}"";
Content c = Request.post(host + ""/api/refresh-tokens"")
.addHeader(""Authorization"", ""YELLOWFIN ts="" + System.currentTimeMillis() + "" , nonce="" + new Random().nextLong())
.addHeader(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
.addHeader(""Content-Type"", ""application/json"")
.bodyString(tokenBody, null)
.execute().returnContent();
JsonObject jsonObject = new JsonParser().parse(c.asString()).getAsJsonObject();
JsonElement accessToken = jsonObject.getAsJsonObject(""_embedded"").getAsJsonObject(""accessToken"").get(""securityToken"");
if (accessToken!=null) {
System.out.println(""Access Token: "" + accessToken);
} else {
System.out.println(""Token not retrieved successfully"");
System.exit(-1);
}
return accessToken.getAsString();
}
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace YellowfinAPIExamples
{
public class AttachClientDatasourceToPrimarySource
{
static async Task Main(string[] args)
{
Console.WriteLine(""Attach a Tenant Source to Primary Org Source for Source Substitution"");
string host = ""http://localhost:8080/Yellowfin"";
string restUsername = ""admin@yellowfin.com.au"";
string restPassword = ""test"";
string primarySourceName = ""PostgreSQL Connection at Primary Org"";
string clientSourceName = ""PostgreSQL Connection for NEWCLIENT"";
string clientOrgReference = ""NEWCLIENT"";
string clientToken = await GenerateToken(host, restUsername, restPassword, clientOrgReference);
int clientOrgSourceId = await FindDataSourceForSourceNameAtClient(host, clientToken, clientSourceName);
Console.WriteLine(""Client Org Source Id: "" + clientOrgSourceId);
string primaryToken = await GenerateToken(host, restUsername, restPassword, null);
int primaryOrgSourceId = await FindDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName);
Console.WriteLine(""Primary Org Source Id: "" + primaryOrgSourceId);
using (var httpClient = new HttpClient())
{
long nonce = new Random().NextInt64();
// Setup request headers
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"", $""ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}, token={primaryToken}"");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
// Make GET request to attach client datasource to primary org source
HttpResponseMessage response = await httpClient.GetAsync($""{host}/api/data-sources/{primaryOrgSourceId}/client-data-sources/?clientSourceId={clientOrgSourceId}"");
if (response.IsSuccessStatusCode)
{
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
else
{
Console.WriteLine($""Failed to attach client datasource. Status code: {response.StatusCode}"");
}
}
}
static async Task<int> FindDataSourceForSourceNameAtClient(string host, string token, string sourceName)
{
using (var httpClient = new HttpClient())
{
// Setup request headers
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(""YELLOWFIN"", $""ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={new Random().NextInt64()}, token={token}"");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(""application/vnd.yellowfin.api-v1+json""));
// Make GET request to fetch data sources
HttpResponseMessage response = await httpClient.GetAsync($""{host}/api/data-sources"");
if (response.IsSuccessStatusCode)
{
string responseBody = await response.Content.ReadAsStringAsync();
// Parse JSON response
JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseBody);
JArray sources = jsonObject[""items""].ToObject<JArray>();
// Iterate through sources to find the correct one
foreach (JObject source in sources)
{
if (sourceName.Equals(source[""sourceName""].ToString(), StringComparison.OrdinalIgnoreCase))
{
return source[""sourceId""].ToObject<int>();
}
}
}
Console.WriteLine($""Data Source could not be found for name: {sourceName}"");
Environment.Exit(-1);
return -1; // Ideally unreachable, since Environment.Exit should terminate the process
}
}
static async Task<string> GenerateToken(string host, string username, string password, string tenantClientOrgRefId)
{
using (var client = new HttpClient())
{
// Generate nonce
long nonce = new Random().NextInt64();
// Create HTTP request
var request = new HttpRequestMessage(HttpMethod.Post, $""{host}/api/refresh-tokens"");
request.Headers.Add(""Authorization"", $""YELLOWFIN ts={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}, nonce={nonce}"");
request.Headers.Add(""Accept"", ""application/vnd.yellowfin.api-v1+json"");
request.Content = new StringContent(
JsonConvert.SerializeObject(new { userName = username, password = password, clientOrgRef = tenantClientOrgRefId }),
System.Text.Encoding.UTF8,
""application/json""
);
// Send request and get response
HttpResponseMessage response = await client.SendAsync(request);
string responseContent = await response.Content.ReadAsStringAsync();
// Parse JSON response
JObject jsonObject = JsonConvert.DeserializeObject<JObject>(responseContent);
string accessToken = jsonObject[""_embedded""][""accessToken""][""securityToken""].ToString();
if (!string.IsNullOrEmpty(accessToken))
{
Console.WriteLine(""Access Token: "" + accessToken);
}
else
{
Console.WriteLine(""Token not retrieved successfully"");
Environment.Exit(-1);
}
return accessToken;
}
}
}
} |
Code Block | ||||
---|---|---|---|---|
| ||||
package main
import (
""bytes""
""encoding/json""
""fmt""
""io/ioutil""
""math/rand""
""net/http""
""time""
)
func main() {
fmt.Println(""Attach a Tenant Source to Primary Org Source for Source Substitution"")
host := ""http://localhost:8080/Yellowfin""
restUsername := ""admin@yellowfin.com.au""
restPassword := ""test""
primarySourceName := ""PostgreSQL Connection at Primary Org""
clientSourceName := ""PostgreSQL Connection for NEWCLIENT""
clientOrgReference := ""NEWCLIENT""
clientToken, err := generateToken(host, restUsername, restPassword, clientOrgReference)
if err != nil {
fmt.Println(""Error generating client token:"", err)
return
}
clientOrgSourceId, err := findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName)
if err != nil {
fmt.Println(""Error finding client data source:"", err)
return
}
fmt.Println(""Client Org Source Id:"", clientOrgSourceId)
primaryToken, err := generateToken(host, restUsername, restPassword, """")
if err != nil {
fmt.Println(""Error generating primary token:"", err)
return
}
primaryOrgSourceId, err := findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName)
if err != nil {
fmt.Println(""Error finding primary data source:"", err)
return
}
fmt.Println(""Primary Org Source Id:"", primaryOrgSourceId)
client := &http.Client{}
nonce := rand.Int63()
req, err := http.NewRequest(""GET"", fmt.Sprintf(""%s/api/data-sources/%d/client-data-sources/?clientSourceId=%d"", host, primaryOrgSourceId, clientOrgSourceId), nil)
if err != nil {
fmt.Println(""Error creating request:"", err)
return
}
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d, token=%s"", time.Now().UnixMilli(), nonce, primaryToken))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
fmt.Println(""Error sending request:"", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(""Error reading response body:"", err)
return
}
fmt.Println(string(body))
}
func findDataSourceForSourceNameAtClient(host, token, sourceName string) (int, error) {
client := &http.Client{}
nonce := rand.Int63()
req, err := http.NewRequest(""GET"", fmt.Sprintf(""%s/api/data-sources"", host), nil)
if err != nil {
return 0, fmt.Errorf(""Error creating request: %v"", err)
}
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d, token=%s"", time.Now().UnixMilli(), nonce, token))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
return 0, fmt.Errorf(""Error sending request: %v"", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return 0, fmt.Errorf(""Error reading response body: %v"", err)
}
var jsonResponse map[string]interface{}
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
return 0, fmt.Errorf(""Error parsing JSON response: %v"", err)
}
items := jsonResponse[""items""].([]interface{})
for _, item := range items {
source := item.(map[string]interface{})
if sourceName == source[""sourceName""].(string) {
sourceId := int(source[""sourceId""].(float64))
return sourceId, nil
}
}
return 0, fmt.Errorf(""Data Source could not be found for name: %s"", sourceName)
}
func generateToken(host, username, password, tenantClientOrgRefId string) (string, error) {
nonce := rand.Int63()
tokenBody := map[string]string{
""userName"": username,
""password"": password,
}
if tenantClientOrgRefId != """" {
tokenBody[""clientOrgRef""] = tenantClientOrgRefId
}
requestBody, err := json.Marshal(tokenBody)
if err != nil {
return """", fmt.Errorf(""Error marshaling request body: %v"", err)
}
client := &http.Client{}
req, err := http.NewRequest(""POST"", fmt.Sprintf(""%s/api/refresh-tokens"", host), bytes.NewBuffer(requestBody))
if err != nil {
return """", fmt.Errorf(""Error creating request: %v"", err)
}
req.Header.Set(""Authorization"", fmt.Sprintf(""YELLOWFIN ts=%d, nonce=%d"", time.Now().UnixMilli(), nonce))
req.Header.Set(""Accept"", ""application/vnd.yellowfin.api-v1+json"")
req.Header.Set(""Content-Type"", ""application/json"")
resp, err := client.Do(req)
if err != nil {
return """", fmt.Errorf(""Error sending request: %v"", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return """", fmt.Errorf(""Error reading response body: %v"", err)
}
var jsonResponse map[string]interface{}
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
return """", fmt.Errorf(""Error parsing JSON response: %v"", err)
}
embedded := jsonResponse[""_embedded""].(map[string]interface{})
accessToken := embedded[""accessToken""].(map[string]interface{})[""securityToken""].(string)
if accessToken == """" {
return """", fmt.Errorf(""Token not retrieved successfully"")
}
fmt.Println(""Access Token:"", accessToken)
return accessToken, nil
} |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
const fetch = require(""node-fetch"");
async function main() {
console.log(""Attach a Tenant Source to Primary Org Source for Source Substitution"");
const host = ""http://localhost:8080/Yellowfin"";
const restUsername = ""admin@yellowfin.com.au"";
const restPassword = ""test"";
const primarySourceName = ""PostgreSQL Connection at Primary Org"";
const clientSourceName = ""PostgreSQL Connection for NEWCLIENT"";
const clientOrgReference = ""NEWCLIENT"";
const clientToken = await generateToken(host, restUsername, restPassword, clientOrgReference);
const clientOrgSourceId = await findDataSourceForSourceNameAtClient(host, clientToken, clientSourceName);
console.log(""Client Org Source Id:"", clientOrgSourceId);
const primaryToken = await generateToken(host, restUsername, restPassword, null);
const primaryOrgSourceId = await findDataSourceForSourceNameAtClient(host, primaryToken, primarySourceName);
console.log(""Primary Org Source Id:"", primaryOrgSourceId);
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${primaryToken}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
try {
const response = await fetch(`${host}/api/data-sources/${primaryOrgSourceId}/client-data-sources/?clientSourceId=${clientOrgSourceId}`, {
method: 'GET',
headers: headers
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const responseBody = await response.text();
console.log(responseBody);
} catch (error) {
console.error(""Error:"", error.message);
}
}
async function findDataSourceForSourceNameAtClient(host, token, sourceName) {
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}, token=${token}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
try {
const response = await fetch(`${host}/api/data-sources`, {
method: 'GET',
headers: headers
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const jsonResponse = await response.json();
const sources = jsonResponse.items;
for (let i = 0; i < sources.length; i++) {
const source = sources[i];
if (sourceName === source.sourceName) {
return source.sourceId;
}
}
console.log(""Data Source could not be found for name:"", sourceName);
process.exit(-1); // Exit if data source not found
} catch (error) {
console.error(""Error:"", error.message);
process.exit(-1); // Exit on error
}
}
async function generateToken(host, username, password, tenantClientOrgRefId) {
const nonce = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const headers = {
'Authorization': `YELLOWFIN ts=${Date.now()}, nonce=${nonce}`,
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
};
const requestBody = {
userName: username,
password: password
};
if (tenantClientOrgRefId !== null) {
requestBody.clientOrgRef = tenantClientOrgRefId;
}
try {
const response = await fetch(`${host}/api/refresh-tokens`, {
method: 'POST',
headers: headers,
body: JSON.stringify(requestBody)
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const jsonResponse = await response.json();
const accessToken = jsonResponse._embedded.accessToken.securityToken;
if (accessToken) {
console.log(`Access Token: ${accessToken}`);
} else {
console.log(""Token not retrieved successfully"");
process.exit(-1); // Exit if token not retrieved
}
return accessToken;
} catch (error) {
console.error(""Error:"", error.message);
process.exit(-1); // Exit on error
}
}
main(); |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?php
function main() {
$host = ""http://localhost:8080/Yellowfin"";
$restUsername = ""admin@yellowfin.com.au"";
$restPassword = ""test"";
echo ""Attach a Tenant Source to Primary Org Source for Source Substitution\n"";
$primarySourceName = ""PostgreSQL Connection at Primary Org"";
$clientSourceName = ""PostgreSQL Connection for NEWCLIENT"";
$clientOrgReference = ""NEWCLIENT"";
try {
$clientToken = generateToken($host, $restUsername, $restPassword, $clientOrgReference);
$clientOrgSourceId = findDataSourceForSourceNameAtClient($host, $clientToken, $clientSourceName);
echo ""Client Org Source Id: $clientOrgSourceId\n"";
$primaryToken = generateToken($host, $restUsername, $restPassword, null);
$primaryOrgSourceId = findDataSourceForSourceNameAtClient($host, $primaryToken, $primarySourceName);
echo ""Primary Org Source Id: $primaryOrgSourceId\n"";
$headers = [
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . mt_rand() . ', token=' . $primaryToken,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
];
$url = ""$host/api/data-sources/$primaryOrgSourceId/client-data-sources/?clientSourceId=$clientOrgSourceId"";
$response = httpRequest('GET', $url, $headers);
echo $response;
} catch (Exception $e) {
echo ""Error: "" . $e->getMessage();
}
}
function generateToken($host, $restUsername, $restPassword, $tenantClientOrgRefId = null) {
$nonce = mt_rand();
$tokenBody = ""{ \""userName\"": \""$restUsername\"", \""password\"": \""$restPassword\"""";
if ($tenantClientOrgRefId !== null) {
$tokenBody .= "", \""clientOrgRef\"": \""$tenantClientOrgRefId\"""";
}
$tokenBody .= ""}"";
$headers = [
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . $nonce,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
];
$response = httpRequest('POST', ""$host/api/refresh-tokens"", $headers, $tokenBody);
$jsonResponse = json_decode($response, true);
if (isset($jsonResponse[""_embedded""][""accessToken""][""securityToken""])) {
return $jsonResponse[""_embedded""][""accessToken""][""securityToken""];
} else {
throw new Exception(""Token not retrieved successfully"");
}
}
function findDataSourceForSourceNameAtClient($host, $token, $sourceName) {
$headers = [
'Authorization: YELLOWFIN ts=' . intval(microtime(true) * 1000) . ', nonce=' . mt_rand() . ', token=' . $token,
'Accept: application/vnd.yellowfin.api-v1+json',
'Content-Type: application/json'
];
$response = httpRequest('GET', ""$host/api/data-sources"", $headers);
$jsonObject = json_decode($response);
if (isset($jsonObject->items)) {
foreach ($jsonObject->items as $source) {
if ($source->sourceName === $sourceName) {
return $source->sourceId;
}
}
}
echo ""Data Source could not be found for name: $sourceName\n"";
exit(-1);
}
function httpRequest($method, $url, $headers, $data = null) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$response = curl_exec($ch);
if (curl_errno($ch)) {
throw new Exception('Error: ' . curl_error($ch));
}
curl_close($ch);
return $response;
}
main();
?> |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
import random
import time
import requests
def main():
print(""Attach a Tenant Source to Primary Org Source for Source Substitution"")
host = ""http://localhost:8080/Yellowfin""
rest_username = ""admin@yellowfin.com.au""
rest_password = ""test""
primary_source_name = ""PostgreSQL Connection at Primary Org""
client_source_name = ""PostgreSQL Connection for NEWCLIENT""
client_org_reference = ""NEWCLIENT""
try:
client_token = generate_token(host, rest_username, rest_password, client_org_reference)
client_org_source_id = find_data_source_for_source_name_at_client(host, client_token, client_source_name)
print(""Client Org Source Id:"", client_org_source_id)
primary_token = generate_token(host, rest_username, rest_password, None)
primary_org_source_id = find_data_source_for_source_name_at_client(host, primary_token, primary_source_name)
print(""Primary Org Source Id:"", primary_org_source_id)
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={primary_token}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
url = f'{host}/api/data-sources/{primary_org_source_id}/client-data-sources/?clientSourceId={client_org_source_id}'
response = requests.get(url, headers=headers)
response.raise_for_status()
print(response.text)
except Exception as e:
print(f""Error: {e}"")
def find_data_source_for_source_name_at_client(host, token, source_name):
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}, token={token}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
url = f'{host}/api/data-sources'
response = requests.get(url, headers=headers)
response.raise_for_status()
json_data = response.json()
items = json_data.get('items', [])
for source in items:
if source['sourceName'] == source_name:
return source['sourceId']
raise Exception(f""Data Source could not be found for name: {source_name}"")
def generate_token(host, username, password, tenant_client_org_ref_id):
body = {
""userName"": username,
""password"": password
}
if tenant_client_org_ref_id:
body['clientOrgRef'] = tenant_client_org_ref_id
headers = {
'Authorization': f'YELLOWFIN ts={int(time.time() * 1000)}, nonce={random.randint(0, 2**63 - 1)}',
'Accept': 'application/vnd.yellowfin.api-v1+json',
'Content-Type': 'application/json'
}
response = requests.post(f'{host}/api/refresh-tokens', headers=headers, json=body)
response.raise_for_status()
json_response = response.json()
access_token = json_response[""_embedded""][""accessToken""][""securityToken""]
print(""Access Token:"", access_token)
return access_token
if __name__ == ""__main__"":
main() |