power-bi 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90d415a89ed5860c82824f7e152e4c58d42054bc293f5534f6669774682a1ffe
4
- data.tar.gz: 536d4c7cea48c859c7b780db751da15375b060a45c59946a2335887d8e948494
3
+ metadata.gz: a22ca0a37fc03e4fd19214f0ecb71c8fedf820fabbbc9e7a7e5add198e0ab25a
4
+ data.tar.gz: 61fc121ec95aa7cc815b7ee4e84a9fe28facbb2c5177dbe91e519e17ebcfae19
5
5
  SHA512:
6
- metadata.gz: d31db71feb4b03d7810d5805b3d48016e89ead1782bfae66269aa2a0c55340e6cf21031525ffa6d5b917cdc36041670ef52c1ccff499ebdfc7d0051d8005b6a8
7
- data.tar.gz: 1ea49ae1a15e45b16c21b9da86c8ac20abb9e96a6eb63e6a0ed9a7dfcbca25dfff8431896703f2d55736a148668cf4b85ac591eb20c68bf1b2d9f6baee455e3a
6
+ metadata.gz: 1c69b92f3b68c19b67a417ba7deb402b4bcc8130ebf074260e97b36c62f773ac27e3720d4fa3946060ad1d8d062bbcf95768c436f7be207e773f849a818a633f
7
+ data.tar.gz: 9454fcb89c9de930616e8ea944fb9aba73f5cfa558e2bef1e755c4f16ec66164dff386154532242ebd55242bc6ccd6ecbcc59fce3f64bf5e8fca554ed309ee59
data/README.md CHANGED
@@ -112,6 +112,10 @@ Note 2: to limit the number of API calls, it is best to directly use the _getter
112
112
  * Delete the dataset: `dataset.delete`
113
113
  * Bind dataset to a gateway datasource: `dataset.bind_to_gateway(gateway, gateway_datasource)`
114
114
 
115
+ ## Datasources
116
+
117
+ * Update credentials of a datasource: `datasource.update_credentials(username, password)`
118
+
115
119
  ## Gateways
116
120
 
117
121
  * List gateways: `pbi.gateways`
@@ -0,0 +1,80 @@
1
+ module PowerBI
2
+ class Admin
3
+
4
+ def initialize(tenant)
5
+ @tenant = tenant
6
+ end
7
+
8
+ def get_user_artifact_access(user_id, artifact_types: nil)
9
+ if artifact_types
10
+ params = {artifactTypes: artifact_types.join(',')}
11
+ else
12
+ params = {}
13
+ end
14
+
15
+ url = "/admin/users/#{user_id}/artifactAccess"
16
+
17
+ resp = @tenant.get(url, params)
18
+ data = resp[:ArtifactAccessEntities]
19
+
20
+ continuation_token = resp[:continuationToken]
21
+
22
+ while continuation_token
23
+ params = {continuationToken: "'#{continuation_token}'"}
24
+ resp = @tenant.get(url, params)
25
+ data += resp[:ArtifactAccessEntities]
26
+ continuation_token = resp[:continuationToken] ? URI::decode_uri_component(resp[:continuationToken]) : nil
27
+ end
28
+
29
+ data
30
+ end
31
+
32
+ def get_workspaces(filter: nil, expand: nil)
33
+ params = {}
34
+ params[:$filter] = filter if filter
35
+ params[:$expand] = expand if expand
36
+
37
+ url = '/admin/groups'
38
+
39
+ nr_records = 5000
40
+ count = 0
41
+
42
+ data = []
43
+
44
+ loop do
45
+ params[:$top] = nr_records
46
+ params[:$skip] = count
47
+ resp = @tenant.get(url, params)
48
+ data += resp[:value]
49
+ batch_count = resp[:value].size
50
+ count += batch_count
51
+ break if batch_count < nr_records
52
+ end
53
+
54
+ data
55
+ end
56
+
57
+ def force_delete_workspace_by_workspace_name(user_email, workspace_name)
58
+ workspace = get_workspaces(filter: "name eq '#{workspace_name}' and state eq 'Active'").first
59
+ add_user(user_email, workspace[:id], access_right: "Admin")
60
+ @tenant.workspace(workspace[:id]).delete
61
+ end
62
+
63
+ def force_delete_workspace_by_workspace_id(user_email, workspace_id)
64
+ add_user(user_email, workspace_id, access_right: "Admin")
65
+ @tenant.workspace(workspace_id).delete
66
+ end
67
+
68
+ private
69
+
70
+ def add_user(user_email, workspace_id, access_right: "Admin")
71
+ @tenant.post("/admin/groups/#{workspace_id}/users") do |req|
72
+ req.body = {
73
+ emailAddress: user_email,
74
+ groupUserAccessRight: access_right,
75
+ }.to_json
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -1,6 +1,6 @@
1
1
  module PowerBI
2
2
  class Dataset < Object
3
- attr_reader :workspace, :datasources, :parameters, :refresh_history
3
+ attr_reader :workspace, :datasources, :parameters
4
4
 
5
5
  def initialize(tenant, parent, id = nil)
6
6
  super(tenant, id)
@@ -38,6 +38,11 @@ module PowerBI
38
38
  true
39
39
  end
40
40
 
41
+ def refresh_history(entries_to_load = 1)
42
+ @refresh_history.entries_to_load = entries_to_load
43
+ @refresh_history
44
+ end
45
+
41
46
  def last_refresh
42
47
  @refresh_history.first
43
48
  end
@@ -16,6 +16,24 @@ module PowerBI
16
16
  }
17
17
  end
18
18
 
19
+ # only MySQL type is currently supported
20
+ def update_credentials(username, password)
21
+ @tenant.patch("/gateways/#{gateway_id}/datasources/#{datasource_id}") do |req|
22
+ req.body = {
23
+ credentialDetails: {
24
+ credentialType: "Basic",
25
+ credentials: "{\"credentialData\":[{\"name\":\"username\", \"value\":\"#{username}\"},{\"name\":\"password\", \"value\":\"#{password}\"}]}",
26
+ encryptedConnection: "Encrypted",
27
+ encryptionAlgorithm: "None",
28
+ privacyLevel: "None",
29
+ useCallerAADIdentity: false,
30
+ useEndUserOAuth2Credentials: false,
31
+ },
32
+ }.to_json
33
+ end
34
+ true
35
+ end
36
+
19
37
  end
20
38
 
21
39
  class DatasourceArray < Array
@@ -18,6 +18,14 @@ module PowerBI
18
18
  }
19
19
  end
20
20
 
21
+ # currently only implemented for users or service principals (not yet service principal profiles)
22
+ def delete
23
+ email_address_or_object_id = email_address || identifier
24
+ @tenant.delete("/gateways/#{@gateway_datasource.gateway.id}/datasources/#{@gateway_datasource.id}/users/#{email_address_or_object_id}", use_profile: false)
25
+ @gateway_datasource.gateway_datasource_users.reload
26
+ true
27
+ end
28
+
21
29
  end
22
30
 
23
31
  class GatewayDatasourceUserArray < Array
@@ -22,18 +22,27 @@ module PowerBI
22
22
  end
23
23
 
24
24
  class RefreshArray < Array
25
+ attr_reader :entries_to_load
25
26
 
26
27
  def initialize(tenant, dataset)
27
28
  super(tenant, dataset)
28
29
  @dataset = dataset
30
+ @entries_to_load = 1
29
31
  end
30
32
 
31
33
  def self.get_class
32
34
  Refresh
33
35
  end
34
36
 
37
+ def entries_to_load=(entries_to_load)
38
+ if entries_to_load > @entries_to_load
39
+ @entries_to_load = entries_to_load
40
+ reload
41
+ end
42
+ end
43
+
35
44
  def get_data
36
- @tenant.get("/groups/#{@dataset.workspace.id}/datasets/#{@dataset.id}/refreshes", {'$top': '1'})[:value]
45
+ @tenant.get("/groups/#{@dataset.workspace.id}/datasets/#{@dataset.id}/refreshes", {'$top': @entries_to_load.to_s})[:value]
37
46
  end
38
47
  end
39
48
  end
@@ -1,6 +1,6 @@
1
1
  module PowerBI
2
2
  class Tenant
3
- attr_reader :workspaces, :gateways, :capacities, :profiles, :profile_id
3
+ attr_reader :workspaces, :gateways, :capacities, :profiles, :profile_id, :admin
4
4
 
5
5
  def initialize(token_generator, retries: 5, logger: nil)
6
6
  @token_generator = token_generator
@@ -10,6 +10,7 @@ module PowerBI
10
10
  @profiles = ProfileArray.new(self)
11
11
  @logger = logger
12
12
  @profile_id = nil
13
+ @admin = Admin.new(self)
13
14
 
14
15
  ## WHY RETRIES? ##
15
16
  # It is noticed that once in a while (~0.1% API calls), the Power BI server returns a 500 (internal server error) without apparent reason, just retrying works :-)
@@ -73,7 +74,7 @@ module PowerBI
73
74
  unless [200, 202].include? response.status
74
75
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
75
76
  end
76
- log "Calling (GET) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
77
+ log "Calling (GET) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms - status: #{response.status}"
77
78
  unless response.body.empty?
78
79
  JSON.parse(response.body, symbolize_names: true)
79
80
  end
@@ -92,7 +93,7 @@ module PowerBI
92
93
  end
93
94
  yield req if block_given?
94
95
  end
95
- log "Calling (GET - raw) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
96
+ log "Calling (GET - raw) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms - status: #{response.status}"
96
97
  unless [200, 202].include? response.status
97
98
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
98
99
  end
@@ -114,7 +115,7 @@ module PowerBI
114
115
  end
115
116
  yield req if block_given?
116
117
  end
117
- log "Calling (POST) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
118
+ log "Calling (POST) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms - status: #{response.status}"
118
119
  unless [200, 201, 202].include? response.status
119
120
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
120
121
  end
@@ -138,7 +139,7 @@ module PowerBI
138
139
  end
139
140
  yield req if block_given?
140
141
  end
141
- log "Calling (PATCH) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
142
+ log "Calling (PATCH) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms - status: #{response.status}"
142
143
  unless [200, 202].include? response.status
143
144
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
144
145
  end
@@ -161,7 +162,7 @@ module PowerBI
161
162
  end
162
163
  yield req if block_given?
163
164
  end
164
- log "Calling (DELETE) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
165
+ log "Calling (DELETE) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms - status: #{response.status}"
165
166
  if [400, 401, 404].include? response.status
166
167
  raise NotFoundError
167
168
  end
@@ -190,7 +191,7 @@ module PowerBI
190
191
  req.body = {value: Faraday::UploadIO.new(file, 'application/octet-stream')}
191
192
  req.options.timeout = 120 # default is 60 seconds Net::ReadTimeout
192
193
  end
193
- log "Calling (POST - file) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
194
+ log "Calling (POST - file) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms - status: #{response.status}"
194
195
  if response.status != 202
195
196
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
196
197
  end
data/lib/power-bi.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'pry' # TODO remove in final product
2
1
  require 'faraday'
3
2
  require 'json'
4
3
  require 'date'
@@ -26,4 +25,5 @@ require_relative "power-bi/gateway_datasource_user"
26
25
  require_relative "power-bi/page"
27
26
  require_relative "power-bi/user"
28
27
  require_relative "power-bi/capacity"
29
- require_relative "power-bi/profile"
28
+ require_relative "power-bi/profile"
29
+ require_relative "power-bi/admin"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power-bi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lode Cools
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-21 00:00:00.000000000 Z
11
+ date: 2025-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -89,6 +89,7 @@ files:
89
89
  - LICENSE
90
90
  - README.md
91
91
  - lib/power-bi.rb
92
+ - lib/power-bi/admin.rb
92
93
  - lib/power-bi/array.rb
93
94
  - lib/power-bi/capacity.rb
94
95
  - lib/power-bi/dataset.rb
@@ -109,7 +110,7 @@ homepage: https://github.com/piloos/power-bi
109
110
  licenses:
110
111
  - MIT
111
112
  metadata: {}
112
- post_install_message:
113
+ post_install_message:
113
114
  rdoc_options: []
114
115
  require_paths:
115
116
  - lib
@@ -125,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
126
  version: '0'
126
127
  requirements: []
127
128
  rubygems_version: 3.4.6
128
- signing_key:
129
+ signing_key:
129
130
  specification_version: 4
130
131
  summary: Ruby wrapper for the Power BI API
131
132
  test_files: []