- Created by YUKA SAITO on Jul 25, 2024
You are viewing an old version of this page. View the current version.
Compare with Current View Version History
Version 1 Next »
クライアントソース置換は、プライマリー組織からの共有コンテンツを閲覧する際に、各クライアント組織に個別のデータソースを使用するためのメカニズムです。これにより、最小限の構成で、レポートやダッシュボードの単一のコピーを、各クライアントがそれぞれのデータで使用できます。
一般的なシナリオは、新しいテナントがYellowfin インスタンスにオンボーディングされ、そのテナントのデータに対するレポートを有効にする必要がある場合です。このプロセスには、いくつかの手順が含まれます。
- データソースをクライアント組織で作成する必要があります。
- 新しいクライアントデータソースは、すべての共有コンテンツが作成されたプライマリー組織にリンクされている必要があります。
クライアント組織で新しいデータソースを作成するには、2つの方法があります。既存のデータソースのコピーをインポートすることで、クライアントのデータソースを作成することができます。データソースを直接作成するエンドポイントもあります。
データソースが作成されると、クライアントデータソースをプライマリー組織のデータソースに関連付けるためのエンドポイントが1つ用意されます。
複製したインポートからデータソースを作成
新しいクライアント組織に新しいデータソースを作成する1つの方法は、既存のデータソースを複製し、新しい接続のために接続詳細を変更することです。これは、既存のデータソースをエクスポートし、エクスポートファイル自体を変更して、Yellowfinに再インポートすることで実現できます。
ソース置換を使用する場合、プライマリー組織に既にプレースホルダーデータソースがあり、そこにすべてのレポートコンテンツが存在している必要があります。このデータソースは、Yellowfin内のエクスポートUIを使用してエクスポートできます。これにより、YellowfinからYFX形式のファイルがエクスポートされます。
YFXファイルは、解凍可能なアーカイブ (zip) ファイルです。YFXファイル内には、ExportListHierarchy.json ファイルと、YFExport.xml ファイルがあります。YFExport.xml ファイルには、エクスポートされたデータソースの読み取り可能なバージョンが含まれています。
YFExport.xml ファイル内では、データベース接続設定を変更できます。ソース置換用のテナントデータソースの作成プロセスを自動化する場合は、YFExport.xml ファイルのコンテンツをテンプレートとして使用し、接続固有のデータを注入する必要がある場所にトークンを追加します。
以下のYFExport.xml ファイルの抜粋は、クライアントソース置換で使用するデータソースを自動生成するプロセスでトークンを置き換える箇所を赤で示しています。
<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>
エクスポートファイルを自動的にトークンに挿入したら、POST /api/rpc/import-export/import-content エンドポイント Import Content を使用してREST API経由でアップロードできます。
この特定のエンドポイントは、フォームベースの送信パラダイムを使用します。2つのフォーム本体が必要であり、1つはYFX/XML ファイルコンテンツを含む「contentToProcess」という名前で、もう1つは、インポート処理に関するルールを含む「importOptions」という名前です。こちらの例では、XMLファイルに単一のデータソースが含まれていると仮定して、この importOptions ペイロードを使用できます。
[ { "itemIndex": 0, "optionKey": "SKIP", "optionValue": false }, { "itemIndex": 0, "optionKey": "OPTION\", "optionValue": "ADD" } ]
以下のコード例では、事前にエクスポートされたデータベースXMLテンプレートを使用して、データベースホスト、データベース名、データベースユーザーとパスワードの置換値をファイルに挿入します。その後、(クライアント参照IDで指定された) テナントにインポートされます。
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>""; }
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>""; } }
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> `
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);
<?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); ?>
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()
データソースサービス経由で新しいデータソースを作成
データソースは、POST /api/data-sources エンドポイント Create Data Source を使用して、REST API経由で直接作成することができます。
これは、こちらの形式のデータソースモデルを取ります。
{ "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" } ] }
モデルの本体は、GET /api/data-sources エンドポイントによって返されるモデルと似ています。プライマリー組織のデータソースと似た新しいソースを作成する場合は、GET /api/data-sources により返されるデータをテンプレートとして使用できます。
作成モデル内のsourceOptionsは、データベースの種類によって異なり、新しいデータソースに接続する際に接続ウィザードによって公開されるオプションの代表的なものです。
connectionString はモデル本体で使用できますが、データソースの作成時にソースオプションに基づいて再生成されることに注意してください。
以下の例では、POST /api/data-sources エンドポイントを使用して新しいデータソースを作成する方法を示しています。
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(); } }
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; } } } }
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 }
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();
<?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(); ?>
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()
データソースの一覧化
データソースの一覧は、GET /api/data-sources エンドポイント Get All Data Sources を使用することで取得できます。これは、以下の形式のデータソースモデルを返します。
{ "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 }
こちらのサービスを使用して、指定されたデータソース名のデータソースの内部整数識別子 (sourceId) を検索できます。
以下のコード例は、システムからデータソースの一覧を取得する方法を示しています。
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(); } }
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; } } } }
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 }
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();
<?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(); ?>
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()
ソース置換のためのクライアントデータソースのプライマリー組織データソースへの添付
クライアントデータソースは、POST /api/data-sources/{primaryOrgSourceId}/client-data-sources/?clientSourceId={clientOrgSourceId} エンドポイント Add Client Data Source を使用して、(ソース置換で使用するために) プライマリー組織データソースにリンクできます。
ここで、{primaryOrgSourceId} は、プライマリー組織データソースの整数識別子であり、{clientOrgSourceId} は、リンクするクライアント組織データソースの整数識別子です。
以下の例では、(名前で識別された) クライアントデータソースを、(名前で識別された) プライマリー組織データソースにリンクする方法を示しています。
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(); } }
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; } } } }
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 }
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();
<?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(); ?>
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()
- No labels