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
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