Power BI query Connecting to API that uses HMAC Authentication - powerbi
I am new to power bi, I need to connect to the web API using HMAC authentication. How I can send HMAC auth headers through web request?
Or How to do HMAC encryption in the PowerBi query
Thanks in advance
It took me forever to realise that the following can be done and is a lot of out of the box thinking.
Create a function that generates a html document and have power query's built in rudimentary web browser execute JavaScript snippetes.
If your JS code references packages, you need to load them or create links to CDN and change all double quotes to single quotes (I did in text edit with find/replace then copy/paste in code below between double quotes)
The following code will do HMAC-SHA512 with secret key (2 args).
New Blank Query and paste below code.
It took me 2 years since I first tried to do it until it clicked.
You're welcome!!!
(secret as text, payload as text) =>
let
Source = Web.Page(
"
<script>
//the following are CDN's from https://cdnjs.com/libraries/crypto-js and all double quotes replaced with single quotes
//core
!function(t,n){'object'==typeof exports?module.exports=exports=n():'function'==typeof define&&define.amd?define([],n):t.CryptoJS=n()}(this,function(){return function(f){var i;if('undefined'!=typeof window&&window.crypto&&(i=window.crypto),'undefined'!=typeof self&&self.crypto&&(i=self.crypto),!(i=!(i=!(i='undefined'!=typeof globalThis&&globalThis.crypto?globalThis.crypto:i)&&'undefined'!=typeof window&&window.msCrypto?window.msCrypto:i)&&'undefined'!=typeof global&&global.crypto?global.crypto:i)&&'function'==typeof require)try{i=require('crypto')}catch(t){}var e=Object.create||function(t){return n.prototype=t,t=new n,n.prototype=null,t};function n(){}var t={},r=t.lib={},o=r.Base={extend:function(t){var n=e(this);return t&&n.mixIn(t),n.hasOwnProperty('init')&&this.init!==n.init||(n.init=function(){n.$super.init.apply(this,arguments)}),(n.init.prototype=n).$super=this,n},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var n in t)t.hasOwnProperty(n)&&(this[n]=t[n]);t.hasOwnProperty('toString')&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},u=r.WordArray=o.extend({init:function(t,n){t=this.words=t||[],this.sigBytes=null!=n?n:4*t.length},toString:function(t){return(t||a).stringify(this)},concat:function(t){var n=this.words,e=t.words,i=this.sigBytes,r=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o<r;o++){var s=e[o>>>2]>>>24-o%4*8&255;n[i+o>>>2]|=s<<24-(i+o)%4*8}else for(var a=0;a<r;a+=4)n[i+a>>>2]=e[a>>>2];return this.sigBytes+=r,this},clamp:function(){var t=this.words,n=this.sigBytes;t[n>>>2]&=4294967295<<32-n%4*8,t.length=f.ceil(n/4)},clone:function(){var t=o.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var n=[],e=0;e<t;e+=4)n.push(function(){if(i){if('function'==typeof i.getRandomValues)try{return i.getRandomValues(new Uint32Array(1))[0]}catch(t){}if('function'==typeof i.randomBytes)try{return i.randomBytes(4).readInt32LE()}catch(t){}}throw new Error('Native crypto module could not be used to get secure random number.')}());return new u.init(n,t)}}),s=t.enc={},a=s.Hex={stringify:function(t){for(var n=t.words,e=t.sigBytes,i=[],r=0;r<e;r++){var o=n[r>>>2]>>>24-r%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join('')},parse:function(t){for(var n=t.length,e=[],i=0;i<n;i+=2)e[i>>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new u.init(e,n/2)}},c=s.Latin1={stringify:function(t){for(var n=t.words,e=t.sigBytes,i=[],r=0;r<e;r++){var o=n[r>>>2]>>>24-r%4*8&255;i.push(String.fromCharCode(o))}return i.join('')},parse:function(t){for(var n=t.length,e=[],i=0;i<n;i++)e[i>>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new u.init(e,n)}},p=s.Utf8={stringify:function(t){try{return decodeURIComponent(escape(c.stringify(t)))}catch(t){throw new Error('Malformed UTF-8 data')}},parse:function(t){return c.parse(unescape(encodeURIComponent(t)))}},d=r.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new u.init,this._nDataBytes=0},_append:function(t){'string'==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(t){var n,e=this._data,i=e.words,r=e.sigBytes,o=this.blockSize,s=r/(4*o),a=(s=t?f.ceil(s):f.max((0|s)-this._minBufferSize,0))*o,r=f.min(4*a,r);if(a){for(var c=0;c<a;c+=o)this._doProcessBlock(i,c);n=i.splice(0,a),e.sigBytes-=r}return new u.init(n,r)},clone:function(){var t=o.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),h=(r.Hasher=d.extend({cfg:o.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){d.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){return t&&this._append(t),this._doFinalize()},blockSize:16,_createHelper:function(e){return function(t,n){return new e.init(n).finalize(t)}},_createHmacHelper:function(e){return function(t,n){return new h.HMAC.init(e,n).finalize(t)}}}),t.algo={});return t}(Math)});
//x64-core
!function(t,e){'object'==typeof exports?module.exports=exports=e(require('./core')):'function'==typeof define&&define.amd?define(['./core'],e):e(t.CryptoJS)}(this,function(t){var e,o,n,i;return o=(e=t).lib,n=o.Base,i=o.WordArray,(e=e.x64={}).Word=n.extend({init:function(t,e){this.high=t,this.low=e}}),e.WordArray=n.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:8*t.length},toX32:function(){for(var t=this.words,e=t.length,o=[],r=0;r<e;r++){var n=t[r];o.push(n.high),o.push(n.low)}return i.create(o,this.sigBytes)},clone:function(){for(var t=n.clone.call(this),e=t.words=this.words.slice(0),o=e.length,r=0;r<o;r++)e[r]=e[r].clone();return t}}),t});
//sha512
!function(i,h){'object'==typeof exports?module.exports=exports=h(require('./core'),require('./x64-core')):'function'==typeof define&&define.amd?define(['./core','./x64-core'],h):h(i.CryptoJS)}(this,function(r){return function(){var i=r,h=i.lib.Hasher,o=i.x64,e=o.Word,n=o.WordArray,o=i.algo;function t(){return e.create.apply(e,arguments)}var i1=[t(1116352408,3609767458),t(1899447441,602891725),t(3049323471,3964484399),t(3921009573,2173295548),t(961987163,4081628472),t(1508970993,3053834265),t(2453635748,2937671579),t(2870763221,3664609560),t(3624381080,2734883394),t(310598401,1164996542),t(607225278,1323610764),t(1426881987,3590304994),t(1925078388,4068182383),t(2162078206,991336113),t(2614888103,633803317),t(3248222580,3479774868),t(3835390401,2666613458),t(4022224774,944711139),t(264347078,2341262773),t(604807628,2007800933),t(770255983,1495990901),t(1249150122,1856431235),t(1555081692,3175218132),t(1996064986,2198950837),t(2554220882,3999719339),t(2821834349,766784016),t(2952996808,2566594879),t(3210313671,3203337956),t(3336571891,1034457026),t(3584528711,2466948901),t(113926993,3758326383),t(338241895,168717936),t(666307205,1188179964),t(773529912,1546045734),t(1294757372,1522805485),t(1396182291,2643833823),t(1695183700,2343527390),t(1986661051,1014477480),t(2177026350,1206759142),t(2456956037,344077627),t(2730485921,1290863460),t(2820302411,3158454273),t(3259730800,3505952657),t(3345764771,106217008),t(3516065817,3606008344),t(3600352804,1432725776),t(4094571909,1467031594),t(275423344,851169720),t(430227734,3100823752),t(506948616,1363258195),t(659060556,3750685593),t(883997877,3785050280),t(958139571,3318307427),t(1322822218,3812723403),t(1537002063,2003034995),t(1747873779,3602036899),t(1955562222,1575990012),t(2024104815,1125592928),t(2227730452,2716904306),t(2361852424,442776044),t(2428436474,593698344),t(2756734187,3733110249),t(3204031479,2999351573),t(3329325298,3815920427),t(3391569614,3928383900),t(3515267271,566280711),t(3940187606,3454069534),t(4118630271,4000239992),t(116418474,1914138554),t(174292421,2731055270),t(289380356,3203993006),t(460393269,320620315),t(685471733,587496836),t(852142971,1086792851),t(1017036298,365543100),t(1126000580,2618297676),t(1288033470,3409855158),t(1501505948,4234509866),t(1607167915,987167468),t(1816402316,1246189591)],h1=[];!function(){for(var i=0;i<80;i++)h1[i]=t()}();o=o.SHA512=h.extend({_doReset:function(){this._hash=new n.init([new e.init(1779033703,4089235720),new e.init(3144134277,2227873595),new e.init(1013904242,4271175723),new e.init(2773480762,1595750129),new e.init(1359893119,2917565137),new e.init(2600822924,725511199),new e.init(528734635,4215389547),new e.init(1541459225,327033209)])},_doProcessBlock:function(i,h){for(var o=this._hash.words,e=o[0],n=o[1],t=o[2],r=o[3],l=o[4],w=o[5],a=o[6],s=o[7],c=e.high,g=e.low,f=n.high,u=n.low,d=t.high,_=t.low,p=r.high,H=r.low,v=l.high,y=l.low,x=w.high,S=w.low,A=a.high,m=a.low,B=s.high,o=s.low,b=c,k=g,q=f,z=u,W=d,j=_,C=p,D=H,F=v,J=y,M=x,P=S,R=A,X=m,E=B,G=o,I=0;I<80;I++){var K,L,N=h1[I];I<16?(L=N.high=0|i[h+2*I],K=N.low=0|i[h+2*I+1]):($=(O=h1[I-15]).high,V=O.low,U=(Y=h1[I-2]).high,T=Y.low,Q=(Z=h1[I-7]).high,O=Z.low,Z=(Y=h1[I-16]).high,L=(L=(($>>>1|V<<31)^($>>>8|V<<24)^$>>>7)+Q+((K=(Q=(V>>>1|$<<31)^(V>>>8|$<<24)^(V>>>7|$<<25))+O)>>>0<Q>>>0?1:0))+((U>>>19|T<<13)^(U<<3|T>>>29)^U>>>6)+((K+=V=(T>>>19|U<<13)^(T<<3|U>>>29)^(T>>>6|U<<26))>>>0<V>>>0?1:0),K+=$=Y.low,N.high=L=L+Z+(K>>>0<$>>>0?1:0),N.low=K);var O=F&M^~F&R,Q=J&P^~J&X,T=b&q^b&W^q&W,U=(k>>>28|b<<4)^(k<<30|b>>>2)^(k<<25|b>>>7),V=i1[I],Y=V.high,Z=V.low,$=G+((J>>>14|F<<18)^(J>>>18|F<<14)^(J<<23|F>>>9)),N=E+((F>>>14|J<<18)^(F>>>18|J<<14)^(F<<23|J>>>9))+($>>>0<G>>>0?1:0),V=U+(k&z^k&j^z&j),E=R,G=X,R=M,X=P,M=F,P=J,F=C+(N=(N=(N=N+O+(($=$+Q)>>>0<Q>>>0?1:0))+Y+(($=$+Z)>>>0<Z>>>0?1:0))+L+(($=$+K)>>>0<K>>>0?1:0))+((J=D+$|0)>>>0<D>>>0?1:0)|0,C=W,D=j,W=q,j=z,q=b,z=k,b=N+(((b>>>28|k<<4)^(b<<30|k>>>2)^(b<<25|k>>>7))+T+(V>>>0<U>>>0?1:0))+((k=$+V|0)>>>0<$>>>0?1:0)|0}g=e.low=g+k,e.high=c+b+(g>>>0<k>>>0?1:0),u=n.low=u+z,n.high=f+q+(u>>>0<z>>>0?1:0),_=t.low=_+j,t.high=d+W+(_>>>0<j>>>0?1:0),H=r.low=H+D,r.high=p+C+(H>>>0<D>>>0?1:0),y=l.low=y+J,l.high=v+F+(y>>>0<J>>>0?1:0),S=w.low=S+P,w.high=x+M+(S>>>0<P>>>0?1:0),m=a.low=m+X,a.high=A+R+(m>>>0<X>>>0?1:0),o=s.low=o+G,s.high=B+E+(o>>>0<G>>>0?1:0)},_doFinalize:function(){var i=this._data,h=i.words,o=8*this._nDataBytes,e=8*i.sigBytes;return h[e>>>5]|=128<<24-e%32,h[30+(128+e>>>10<<5)]=Math.floor(o/4294967296),h[31+(128+e>>>10<<5)]=o,i.sigBytes=4*h.length,this._process(),this._hash.toX32()},clone:function(){var i=h.clone.call(this);return i._hash=this._hash.clone(),i},blockSize:32});i.SHA512=h._createHelper(o),i.HmacSHA512=h._createHmacHelper(o)}(),r.SHA512});
//hmac
!function(e,t){'object'==typeof exports?module.exports=exports=t(require('./core')):'function'==typeof define&&define.amd?define(['./core'],t):t(e.CryptoJS)}(this,function(e){var t,a;t=e.lib.Base,a=e.enc.Utf8,e.algo.HMAC=t.extend({init:function(e,t){e=this._hasher=new e.init,'string'==typeof t&&(t=a.parse(t));var i=e.blockSize,n=4*i;(t=t.sigBytes>n?e.finalize(t):t).clamp();for(var e=this._oKey=t.clone(),t=this._iKey=t.clone(),s=e.words,r=t.words,o=0;o<i;o++)s[o]^=1549556828,r[o]^=909522486;e.sigBytes=t.sigBytes=n,this.reset()},reset:function(){var e=this._hasher;e.reset(),e.update(this._iKey)},update:function(e){return this._hasher.update(e),this},finalize:function(e){var t=this._hasher,e=t.finalize(e);return t.reset(),t.finalize(this._oKey.clone().concat(e))}})});
!function(e,r){'object'==typeof exports?module.exports=exports=r(require('./core'),require('./x64-core'),require('./sha512'),require('./hmac')):'function'==typeof define&&define.amd?define(['./core','./x64-core','./sha512','./hmac'],r):r(e.CryptoJS)}(this,function(e){return e.HmacSHA512});
</script>
<script>
z= CryptoJS.HmacSHA512( """&payload&""", """&secret&""" );
document.write(z);
</script>
"),
Data = Source{0}[Data],
Children = Data{0}[Children],
Children1 = Children{1}[Children],
Text = Children1{0}[Text]
in
Text
Recently I have collected data for clients using oAuth2 API. You can connect to any API using Power/M Query. Following is the sample code for my case, where in the first part I have collected the access_token and in second step, I have collected data using that access token. hope this will give you some idea on connecting to any API using Power Query.
let
url = "your_authentication_url_here",
body = "{ ""client_id"": ""****"", ""client_secret"": ""****"", ""grant_type"": ""****"", ""audience"":""****""}",
tokenResponse = Json.Document(Web.Contents(url,[Headers = [#"Content-Type"="application/json"], Content = Text.ToBinary(body) ] )),
AccessToken = tokenResponse[access_token],
AccessTokenHeader = "Bearer " & AccessToken,
data_url = "your_main_url_here",
data_body = "{
""authorization"": """& AccessTokenHeader & """,
""content-type"": ""application/json""
}",
GetGroups = Json.Document(
Web.Contents(
data_url,
[
Headers = Json.Document(data_body)
]
)
),
categories = GetGroups[categories], --Category here will be changed as per your retrned data
#"Converted to Table" = Table.FromList(categories, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn
(
#"Converted to Table", "Column1",
{"ext_id", "shared", "report", "query", "_id", "description"}, --This is column returned from your data set
{"ext_id", "shared", "report", "query", "_id", "description"} -- Rename columns accordingly
)
in
#"Expanded Column1"
Use the Power BI Connector through that you can use Crypto.CreateHmac function and create HMAC auth headers
https://www.sqlgene.com/2019/02/19/create-a-power-query-custom-data-connector-in-10-minutes
Related
How to connect jira to power BI service and visualize
I'm using power BI service inside an virtual machine. I want to connect to jira and whatever changes are made on any tickets, I need to capture in my power BI and visualize this. Is this achievable? how to achieve the same?
If you need this to Power BI Service, use Dataflow, blank query, and enter this. However, it's gonna work from anywhere. So even Power BI Desktop Power Query. Change things that are unique for your case such as BaseUrl, JQL or Authentication let // Define the connection, JQL BaseUrl = "https://jira.yoursite.com", RelativePath = "/rest/api/2/search?", JQL = "jql=project=XXX", maxResults = "&maxResults=40", startAt = "&startAt=", // Save the records through paging initialRequest = (Web.Contents(BaseUrl, [RelativePath = RelativePath&JQL, // For authorization, generate JIRA token for your profile and place it into parameter called "token", in order to make this work, or simple replace the token with the string Headers=[Authorization="Bearer "& token]])), LoadJson = Json.Document(initialRequest), totalResults = LoadJson[total], IssuesThroughPaging = List.Generate( () => 0, each _ <= totalResults, each _ + 40, each let Request = (Web.Contents(BaseUrl, [RelativePath = RelativePath&JQL&maxResults&startAt&Text.From(_), Headers=[Authorization="Bearer "& token]])), GetJson = Json.Document(Request), RetrieveIssues = GetJson[issues] in RetrieveIssues ), // Expand your lists ExpandResult = List.Combine(List.Combine({IssuesThroughPaging})), // Expand Key Column GetKey = (ListOfIssues as list) => let Keys = List.Transform(ListOfIssues, each Record.Field(_, "key")) in Keys, // Expand Fields GetFields = (ListOfIssues as list) => let Fields = List.Transform(ListOfIssues, each Record.Field(_, "fields")) in Fields, // Call Key and Field functions AllKeys = GetKey(ExpandResult), AllFields = GetFields(ExpandResult), // Put Keys and Fields together CreateTable = Table.FromColumns({AllKeys, AllFields}, {"key", "Records"}), // Expand Needed Records ExpandFields = Table.ExpandRecordColumn(CreateTable, "Records", {"resolution", "lastViewed", "labels", "issuelinks", "assignee", "subtasks", "reporter", "issuetype", "project", "resolutiondate", "updated", "description", "summary", "duedate", "priority", "status", "creator", "created"}, {"resolution", "lastViewed", "labels", "issuelinks", "assignee", "subtasks", "reporter", "issuetype", "project", "resolutiondate", "updated", "description", "summary", "duedate", "priority", "status", "creator", "created"}) in ExpandFields The paging is needed because JIRA returns only 50 rows per response, that's why there's function to gather the responses iteratively.
Thank you, Vojtěch. It works. Only one error was with "Authorization". But replacing it with "Prefer" fix it. corrected parameter
Data from web - DataSource.Error - unable to retrieve contents of page
I'm trying to get a table from a webpage, but I cannot seem to get PowerBI to correctly load that page. The url is https://www.argentorshop.be/verkoop-uw-edelmetaal-aan-argentorshop/verkoop-uw-goudstaven-en-of-gouden-munten-aan-argentor/ The table I'm trying to import is the GOLD KOERSEN table, highlighted in yellow in this screenshot. However, after entering the url, I get Followed by DataSource.Error We were unable to retrieve the contents of the web page. I already tried adding HTTP request headers and Command timeout but nothing seems to work. I also tried to first use a different (working) webpage, and modify the url in the Source step Source = Web.BrowserContents("https://www.w3schools.com/html/html_tables.asp") changed to Source = Web.BrowserContents("https://www.argentorshop.be/verkoop-uw-edelmetaal-aan-argentorshop/verkoop-uw-goudstaven-en-of-gouden-munten-aan-argentor/") but it yields the same error. Also, trying to wait for a specific Selector in the options of Web.BrowserContents(url,options) by using [WaitFor = [Selector = "#verkopen > div.bootstrap-table"]] doesn't do the trick. Does anyone know of a way to correctly import that table in PowerBI?
Try this. let Source = Web.Contents( "http://www.argentorshop.be/nl/graphql", [ Headers=[ #"Method"="POST", #"Content-Type"="application/json" ], Content=Text.ToBinary("{""query"": ""{sellMetalsGrid (metals: [GOLD]){products {entity_id,name,purchasing_price,buying_premium,spread_percentage,spread_currency,selling_premium,price,image,short_description,product_type,fine_metal_content,metal,url,stock_status}}}""}") ] ), #"JSON" = Json.Document(Source), data = JSON[data], sellMetalsGrid = data[sellMetalsGrid], products = sellMetalsGrid[products], #"Converted to Table" = Table.FromList(products, Splitter.SplitByNothing(), null, null, ExtraValues.Error), #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"entity_id", "name", "purchasing_price", "buying_premium", "spread_percentage", "spread_currency", "selling_premium", "price", "image", "short_description", "product_type", "fine_metal_content", "metal", "url", "stock_status"}, {"Column1.entity_id", "Column1.name", "Column1.purchasing_price", "Column1.buying_premium", "Column1.spread_percentage", "Column1.spread_currency", "Column1.selling_premium", "Column1.price", "Column1.image", "Column1.short_description", "Column1.product_type", "Column1.fine_metal_content", "Column1.metal", "Column1.url", "Column1.stock_status"}) in #"Expanded Column1"
IBM Watson Alchemy news iOS SDK Swift
The IBM Watson iOS SDK using the Alchemy News service on Bluemix returns a string result which requires parsing to pull out the fields like url and cleaned title. ref: https://github.com/watson-developer-cloud/swift-sdk I pull the string into an array and parse it in swift3 using some string methods but this is pretty ordinary and can produce unpredictable results Is there a more elegant approach where I can access specific fields, like the url and cleaned title which I am passing to a UITableViewCell to select and segue to the url link. sample code: let alchemyDataNews = AlchemyDataNews(apiKey: apiKey) let failure = { (error: Error) in print(error) } let start = "now-14d" // 7 day ago let end = "now" // today let query = ["count": "15", "dedup": "true", "q.enriched.url.title": "[IBM]", "return": "enriched.url.url,enriched.url.title" "enriched.url.title,enriched.url.entities.entity.text,enriched.url.entities.entity.type"] Also I have noticed the search string [IBM] has a prefix of 0, i.e. 0[IBM] and have also seen an "A". What do these prefixes mean and where are they documented
Here is one way you can access the fields from a returned payload. alchemyDataNews.getNews(from: "now-4d", to: "now", query: queryDict, failure: failWithError) { news in for doc in (news.result?.docs)! { var cleanedTitle = doc.source?.enriched?.url?.cleanedTitle var author = doc.source?.enriched?.url?.author var title = doc.source?.enriched?.url?.title }} Also, here is a nice API reference link for alchemy data which contains all of the request parameters and filters. https://www.ibm.com/watson/developercloud/alchemydata-news/api/v1/
Power BI connect to CRM 2016 Web API
I'm trying to use Power BI Desktop to connect to a CRM Online (2016 Spring Wave 1) instance using CRM's new Web API methods. When I put my api into a browser like Chrome I get results back. For example if I use https://xxx.crm.dynamics.com/api/data/v8.0/my_records?$select=my_recordid I can see all the results being listed (in batches of 5000) However, when I try the same thing in PowerBI I get an error telling me that a field already exists (see screenshot) I've seen some approaches where the URL is wrapped = Json.Document(Web.Contents("<same url as above>") but this doesn't seem like a good approach, and I don't know how to use this approach with paging. So has anyone managed to get Power BI working with the new Web API calls?
I created a new CRM Online Trial instance and retried using the WebAPI URL (https://xxx.crm.dynamics.com/api/data/v8.0/my_records?$select=my_recordid) in Power BI and this time it worked. It must be something to do with the customisations that I have in place. Also, I noticed that even though I included a $select=my_recordid filter in my WebAPI request, that PowerBI still loaded all columns names; however, only the column specified in my filter had values. This would explain why the error occurs even when I specify a single attribute in the $select
I'm rather late to this question, but I've had good success with the "Json.Document(Web.Contents())" method. The trick to the paging issue was wrapping the call in a recursive function. For convenience, I've wrapped that recursive function such that I can pass in the name of a Saved View/Advanced find and get the results of that query. As a Gist: https://gist.github.com/d4hines/b5d9900fc1ea9d26311d2145505837cb (OrgUrl as text, QueryName as text, UserView as logical) => let GetQueryByName = //https://mycrm.mydomain.com/MYORG (OrgUrl as text, QueryName as text, UserView as logical) => let QueryType = if UserView then "user" else "saved" ,return = OData.Feed( OrgUrl & "/api/data/v8.0/" & QueryType & "queries?$select="& QueryType & "queryid&$filter=name eq '" & QueryName & "'" )[userqueryid]{0} in return, QueryAll = (nextURL, prev) => let prevList = if prev <> null then prev else {}, responseData = Json.Document(Web.Contents(nextURL, [Headers=[Prefer="odata.include-annotations=""OData.Community.Display.V1.FormattedValue"""]])), return = if responseData[#"#odata.nextLink"]? <> null then #QueryAll(responseData[#"#odata.nextLink"], prevList & responseData[value]) else responseData[value] & prevList in return, NamedQuery = OrgUrl & "/api/data/v8.0/contacts?userQuery=" & GetQueryByName(OrgUrl, QueryName, UserView), return = Table.FromList(QueryAll(NamedQuery, null), Splitter.SplitByNothing(), null, null, ExtraValues.Error) in return There are a bit more instructions on the gist if that helps. Hope it helps someone!
Zend_Auth: Join Query Issue
I'm a new guy for zendframework. i am facing zend auth join query issue.. Here I attach my zend_auth login sample code. My login information's are stored in two tables. I mean email address in separate table and password separate. Here I was try to join my table, but I am getting Following error... Message: The supplied parameters to Zend_Auth_Adapter_DbTable failed to produce a valid sql statement, please check table and column names for validity. Please advise me. My code is here... $authAdapter = new Zend_Auth_Adapter_DbTable(Zend_Db_Table::getDefaultAdapter()); $authAdapter->setTableName(array('users','details')) ->setIdentityColumn('name') ->setCredentialColumn('pwd'); $name = 'test'; $pwd = '123'; $authAdapter->setIdentity($name) ->setCredential($pwd); $select = $authAdapter->getDbSelect(); $select->where('pwd = 123') ->joinLeft( array('d' => 'details'),'d.id = users.id'); $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($authAdapter);