Sample code
The following sections provide some sample code to help you get started in creating Test, Metadata and Query functions for your Microservice so that you can test and deploy a Custom Connector in Kianda, allowing you to connect forms and use data from any data source.
Encryption and Decryption sample code
public static string HashWithHMACSHA256(string key, string value)
{
using (var hash = new HMACSHA256(Convert.FromBase64String(key)))
{
var hashedByte = hash.ComputeHash(Encoding.UTF8.GetBytes(value));
var hashed = Convert.ToBase64String(hashedByte);
return hashed;
}
}
public static string AESEncrypt(string key, string plainData, out byte[] iv)
{
var _key = Convert.FromBase64String(key);
using (Aes aes = Aes.Create())
{
aes.GenerateIV();
aes.Mode = CipherMode.CBC;
iv = aes.IV;
aes.KeySize = 256;
aes.Key = _key;
using (var encryptor = aes.CreateEncryptor())
{
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
sw.Write(plainData);
}
return Convert.ToBase64String(ms.ToArray());
}
}
}
}
public static string AESDecrypt(string key, string encryptedData, byte[] iv)
{
var buffer = Convert.FromBase64String(encryptedData);
var _key = Convert.FromBase64String(key);
using (Aes aes = Aes.Create())
{
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.Key = _key;
aes.IV = iv;
using (var decryptor = aes.CreateDecryptor())
{
using (MemoryStream ms = new MemoryStream(buffer))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sw = new StreamReader(cs))
return sw.ReadToEnd();
}
}
}
}
public static string GenerateAESKey()
{
using (Aes aes = Aes.Create())
{
aes.KeySize = 256;
aes.GenerateKey();
return Convert.ToBase64String(aes.Key);
}
}
private static string GetSecretKey()
{
return "{secret key generated from Kianda}"; //REPLACE ME
}
To return to Microservice development, click on the Microservice link.
Test sample code
[FunctionName("connectorTest")]
public static async Task<CustomConnectorResponse> connectorTest(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)][FromForm] HttpRequest req,
ILogger log)
{
string SECRET_KEY = GetSecretKey();
string signature = string.Empty;
CustomConnectorResponse response = new CustomConnectorResponse();
response.queryResult = new QueryResult();
try
{
string testBody = await new StreamReader(req.Body).ReadToEndAsync();
CustomConnectorRequest data = JsonConvert.DeserializeObject<CustomConnectorRequest>(testBody);
var settings = JsonConvert.DeserializeObject<JObject>(AESDecrypt(SECRET_KEY, data.encryptedSettingsPropertyBag, data.iv));
var accessCode = settings["accessCode"];
var clientID = settings["client_key"];
JObject tokenRequestObj = new JObject
{
["grant_type"] = "authorization_code",
["client_id"] = clientID,
["redirect_uri"] = "https://app.kianda.com/index.html",
["code"] = accessCode
};
signature = HashWithHMACSHA256(SECRET_KEY, data.requestId);
byte[] iv;
var encryptedSettings = JsonConvert.SerializeObject(settings);
var settingsobj = AESEncrypt(SECRET_KEY, encryptedSettings, out iv); //encrypt the settings
response.encryptedSettingsPropertyBag = settingsobj;
response.iv = iv;
response.signature = signature;
response.queryResult.success = true;
response.queryResult.message = "Test completed successfully";
}
catch (Exception ex)
{
log.LogError(ex.Message);
CustomConnectorResponse result1 = new CustomConnectorResponse();
return result1;
}
return response;
}
To return to Microservice development, click on the Microservice link.
Metadata sample code
[FunctionName("connectorMetadata")]
public static async Task<CustomConnectorResponse> connectorTree(//metadata
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
ILogger log)
{
string SECRET_KEY = GetSecretKey();
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
CustomConnectorRequest data = JsonConvert.DeserializeObject<CustomConnectorRequest>(requestBody);
// Do Request for token and update settings object
var settings = JsonConvert.DeserializeObject<JObject>(AESDecrypt(SECRET_KEY, data.encryptedSettingsPropertyBag, data.iv));
JObject tokenRequestObj = new JObject
{
["grant_type"] = "authorization_code",
//["client_id"] = clientID,
["redirect_uri"] = "https://app.kianda.com/index.html"
//["code"] = accessCode
};
//settings = GetToken(tokenRequestObj, settings);
//create the Queryresult
CustomConnectorResponse result = new CustomConnectorResponse();
QueryResult resultQuery = new QueryResult();
result.queryResult = resultQuery;
//create the return Tree
string signature = string.Empty;
List<JObject> CityFields = new List<JObject> { };
CityFields.Add(new JObject { ["name"] = "cityName", ["title"] = "City Name", ["text"] = "City Name", ["icon"] = "", ["type"] = "string", ["desc"] = "", });
CityFields.Add(new JObject { ["name"] = "ISOCode", ["title"] = "ISO Country Code", ["text"] = "ISO Country Code", ["icon"] = "", ["type"] = "string", ["desc"] = "" });
List<JObject> CountryFields = new List<JObject> { };
CountryFields.Add(new JObject { ["name"] = "countryName", ["text"] = "Country Name", ["title"] = "Country Name", ["icon"] = "", ["type"] = "string", ["desc"] = "", });
CountryFields.Add(new JObject { ["name"] = "ISOCode", ["text"] = "ISO Country Code", ["title"] = "ISO Country Code", ["icon"] = "", ["type"] = "string", ["desc"] = "" });
List<JObject> nodes = new List<JObject> { };
nodes.Add(new JObject { ["name"] = "Countries", ["text"] = "Countries", ["icon"] = "fa fa-globe", ["type"] = "STRUCTURE", ["nodes"] = new JArray { CountryFields }, ["fields"] = new JArray { CountryFields }, ["selectable"] = true });
nodes.Add(new JObject { ["name"] = "Cities", ["text"] = "Cities", ["icon"] = "fa fa-globe", ["type"] = "STRUCTURE", ["nodes"] = new JArray { CityFields }, ["fields"] = new JArray { CityFields }, ["selectable"] = true });
//create the tree root to be returned
List<JObject> root = new List<JObject> { };
root.Add(new JObject
{
["text"] = "Countries and Cities",
["name"] = "CountriesAndCities",
["icon"] = "fa fa-database",
["selectable"] = false,
["nodes"] = new JArray { nodes }
});
try
{
result.queryResult.items = root;
result.signature = HashWithHMACSHA256(SECRET_KEY, data.requestId);
result.queryResult.success = true;
result.queryResult.message = "Metadata Action Completed";
byte[] iv;
var encryptedSettings = JsonConvert.SerializeObject(settings);
var settingsobj = AESEncrypt(SECRET_KEY, encryptedSettings, out iv); //encrypt the settings
result.iv = iv;
result.encryptedSettingsPropertyBag = settingsobj;
}
catch (Exception ex)
{
CustomConnectorResponse resultExc = new CustomConnectorResponse();
QueryResult resultQueryExc = new QueryResult();
result.queryResult = resultQuery;
resultExc.queryResult.success = false;
resultExc.queryResult.message = "Exception occured; " + ex.Message;
resultExc.signature = signature;
return resultExc;
}
return result;
}
To return to Microservice development, click on the Microservice link.
Query sample code
[FunctionName("connectorQuery")]
public static async Task<CustomConnectorResponse> connectorQuery(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
ILogger log)
{
string SECRET_KEY = GetSecretKey();
CustomConnectorResponse result = new CustomConnectorResponse();
QueryResult resultQuery = new QueryResult();
result.queryResult = resultQuery;
string signature = string.Empty;
var myresponsestring = string.Empty;
try
{
string testBody = await new StreamReader(req.Body).ReadToEndAsync();
CustomConnectorRequest data = JsonConvert.DeserializeObject<CustomConnectorRequest>(testBody);
Query query = data.query;
var settings = JsonConvert.DeserializeObject<JObject>(AESDecrypt(SECRET_KEY, data.encryptedSettingsPropertyBag, data.iv));
//demo object list creation
result.queryResult.items = new List<JObject>();
if (query.info.Value<string>("text") == "Countries")
{
List<JObject> CountriesList = new List<JObject>();
var country1 = new JObject { ["countryName"] = "England", ["ISOCode"] = 123 };
var country2 = new JObject { ["countryName"] = "Ireland", ["ISOCode"] = 124 };
CountriesList.Add(country1);
CountriesList.Add(country2);
result.queryResult.items = CountriesList;
}
else
{
List<JObject> CitysList = new List<JObject>(); //create a list of jobjects
var city1 = new JObject { ["countryName"] = "England", ["cityName"] = "London" };
var city2 = new JObject { ["countryName"] = "England", ["cityName"] = "Liverpool" };
var city3 = new JObject { ["countryName"] = "Ireland", ["cityName"] = "Dublin" };
var city4 = new JObject { ["countryName"] = "Ireland", ["cityName"] = "Cork" };
CitysList.Add(city1);
CitysList.Add(city2);
CitysList.Add(city3);
CitysList.Add(city4);
//check for conditions then return accordingly
if (query != null && !string.IsNullOrEmpty(query.filter))
{
//filtering the city list depending on the filter
var j = CitysList.Where(x => x.GetValue("countryName").Value<string>() == query.filter).ToList();
result.queryResult.items = j;
}
else
{
// if no filter return the full list of citys
result.queryResult.items = CitysList;
}
}
byte[] iv;
var settingsobj = AESEncrypt(SECRET_KEY, JsonConvert.SerializeObject(settings), out iv); //encrypt the settings
result.iv = iv;
result.encryptedSettingsPropertyBag = settingsobj;
result.signature = HashWithHMACSHA256(SECRET_KEY, data.requestId);
result.queryResult.success = true;
}
catch (Exception ex)
{
CustomConnectorResponse resultExc = new CustomConnectorResponse();
QueryResult resultQueryExc = new QueryResult();
resultExc.queryResult.success = false;
resultExc.queryResult.message = "Exception occured; " + ex.Message;
resultExc.signature = signature;
return resultExc;
}
return result;
}
To return to Microservice development, click on the Microservice link.
What’s next
To learn how to create a custom connector view the steps to create a custom connector.