superset 0.1.6
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 +7 -0
- data/.buildkite/pipeline.yml +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +48 -0
- data/Dockerfile +17 -0
- data/LICENSE +21 -0
- data/README.md +205 -0
- data/Rakefile +12 -0
- data/doc/duplicate_dashboards.md +214 -0
- data/doc/setting_up_personal_api_credentials.md +127 -0
- data/docker-compose.override.yml +10 -0
- data/docker-compose.yml +8 -0
- data/env.sample +9 -0
- data/lib/loggers/duplicate_dashboard_logger.rb +15 -0
- data/lib/superset/authenticator.rb +55 -0
- data/lib/superset/chart/bulk_delete.rb +40 -0
- data/lib/superset/chart/delete.rb +30 -0
- data/lib/superset/chart/get.rb +56 -0
- data/lib/superset/chart/list.rb +59 -0
- data/lib/superset/chart/update_dataset.rb +90 -0
- data/lib/superset/client.rb +53 -0
- data/lib/superset/credential/api_user.rb +25 -0
- data/lib/superset/credential/embedded_user.rb +25 -0
- data/lib/superset/dashboard/bulk_delete.rb +42 -0
- data/lib/superset/dashboard/bulk_delete_cascade.rb +52 -0
- data/lib/superset/dashboard/charts/list.rb +47 -0
- data/lib/superset/dashboard/compare.rb +94 -0
- data/lib/superset/dashboard/copy.rb +78 -0
- data/lib/superset/dashboard/datasets/list.rb +74 -0
- data/lib/superset/dashboard/delete.rb +42 -0
- data/lib/superset/dashboard/embedded/get.rb +56 -0
- data/lib/superset/dashboard/embedded/put.rb +35 -0
- data/lib/superset/dashboard/export.rb +98 -0
- data/lib/superset/dashboard/get.rb +51 -0
- data/lib/superset/dashboard/info.rb +17 -0
- data/lib/superset/dashboard/list.rb +99 -0
- data/lib/superset/dashboard/put.rb +37 -0
- data/lib/superset/dashboard/warm_up_cache.rb +42 -0
- data/lib/superset/database/get.rb +30 -0
- data/lib/superset/database/get_schemas.rb +25 -0
- data/lib/superset/database/list.rb +51 -0
- data/lib/superset/dataset/bulk_delete.rb +41 -0
- data/lib/superset/dataset/create.rb +62 -0
- data/lib/superset/dataset/delete.rb +30 -0
- data/lib/superset/dataset/duplicate.rb +62 -0
- data/lib/superset/dataset/get.rb +56 -0
- data/lib/superset/dataset/list.rb +41 -0
- data/lib/superset/dataset/update_query.rb +56 -0
- data/lib/superset/dataset/update_schema.rb +120 -0
- data/lib/superset/dataset/warm_up_cache.rb +41 -0
- data/lib/superset/display.rb +42 -0
- data/lib/superset/enumerations/object_type.rb +11 -0
- data/lib/superset/file_utilities.rb +19 -0
- data/lib/superset/guest_token.rb +69 -0
- data/lib/superset/logger.rb +20 -0
- data/lib/superset/request.rb +62 -0
- data/lib/superset/route_info.rb +34 -0
- data/lib/superset/security/permissions_resources/list.rb +22 -0
- data/lib/superset/security/role/create.rb +25 -0
- data/lib/superset/security/role/get.rb +32 -0
- data/lib/superset/security/role/list.rb +45 -0
- data/lib/superset/security/role/permission/create.rb +35 -0
- data/lib/superset/security/role/permission/get.rb +37 -0
- data/lib/superset/security/user/create.rb +49 -0
- data/lib/superset/security/user/get.rb +27 -0
- data/lib/superset/security/user/list.rb +42 -0
- data/lib/superset/services/duplicate_dashboard.rb +298 -0
- data/lib/superset/sqllab/execute.rb +52 -0
- data/lib/superset/tag/add_to_object.rb +46 -0
- data/lib/superset/tag/get.rb +30 -0
- data/lib/superset/tag/list.rb +37 -0
- data/lib/superset/version.rb +5 -0
- data/lib/superset.rb +17 -0
- data/log/README.md +4 -0
- data/superset.gemspec +55 -0
- metadata +300 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
module Superset
|
2
|
+
module Dataset
|
3
|
+
class UpdateSchema < Superset::Request
|
4
|
+
|
5
|
+
attr_reader :source_dataset_id, :target_database_id, :target_schema, :remove_copy_suffix
|
6
|
+
|
7
|
+
def initialize(source_dataset_id: , target_database_id: , target_schema: , remove_copy_suffix: false)
|
8
|
+
@source_dataset_id = source_dataset_id
|
9
|
+
@target_database_id = target_database_id
|
10
|
+
@target_schema = target_schema
|
11
|
+
@remove_copy_suffix = remove_copy_suffix
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform
|
15
|
+
validate_proposed_changes
|
16
|
+
|
17
|
+
response
|
18
|
+
|
19
|
+
msg = if result['schema'] == target_schema
|
20
|
+
"Successfully updated dataset schema to #{target_schema} on Database: #{target_database_id}"
|
21
|
+
else
|
22
|
+
"Error: Failed to update dataset schema to #{target_schema} on Database: #{target_database_id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
logger.info " #{msg}"
|
26
|
+
msg
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def response
|
31
|
+
@response ||= client.put(route, params_updated)
|
32
|
+
end
|
33
|
+
|
34
|
+
def params_updated
|
35
|
+
@params_updated ||= begin
|
36
|
+
new_params = source_dataset.slice(*acceptable_attributes).with_indifferent_access
|
37
|
+
|
38
|
+
# primary database and schema changes
|
39
|
+
new_params.merge!("database_id": target_database_id) # add the target database id
|
40
|
+
new_params['schema'] = target_schema
|
41
|
+
new_params['owners'] = new_params['owners'].map {|o| o['id'] } # expects an array of user ids
|
42
|
+
new_params['table_name'] = new_params['table_name'].gsub(/ \(COPY\)/, '') if remove_copy_suffix
|
43
|
+
|
44
|
+
# remove unwanted fields from metrics and columns arrays
|
45
|
+
new_params['metrics'].each {|m| m.delete('changed_on') }
|
46
|
+
new_params['metrics'].each {|m| m.delete('created_on') }
|
47
|
+
new_params['columns'].each {|m| m.delete('changed_on') }
|
48
|
+
new_params['columns'].each {|m| m.delete('created_on') }
|
49
|
+
new_params['columns'].each {|m| m.delete('type_generic') }
|
50
|
+
new_params
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# check if the sql query embedds the schema name, if so it can not be duplicated cleanly
|
55
|
+
def sql_query_includes_hard_coded_schema?
|
56
|
+
source_dataset['sql'].include?("#{source_dataset['schema']}.")
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def source_dataset
|
62
|
+
# will raise an error if the dataset does not exist
|
63
|
+
@source_dataset ||= begin
|
64
|
+
dataset = Get.new(source_dataset_id)
|
65
|
+
dataset.result
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_proposed_changes
|
70
|
+
logger.info " Validating Dataset ID: #{source_dataset_id} schema update to #{target_schema} on Database: #{target_database_id}"
|
71
|
+
raise "Error: source_dataset_id integer is required" unless source_dataset_id.present? && source_dataset_id.is_a?(Integer)
|
72
|
+
raise "Error: target_database_id integer is required" unless target_database_id.present? && target_database_id.is_a?(Integer)
|
73
|
+
raise "Error: target_schema string is required" unless target_schema.present? && target_schema.is_a?(String)
|
74
|
+
|
75
|
+
# confirm the dataset exist? ... no need as the load_source_dataset method will raise an error if the dataset does not exist
|
76
|
+
|
77
|
+
# does the target schema exist in the target database?
|
78
|
+
raise "Error: Schema #{target_schema} does not exist in database: #{target_database_id}" unless target_database_available_schemas.include?(target_schema)
|
79
|
+
|
80
|
+
# does the sql query hard code the current schema name?
|
81
|
+
raise "Error: >>WARNING<< The Dataset ID #{source_dataset_id} SQL query is hard coded with the schema value and can not be duplicated cleanly. " +
|
82
|
+
"Remove all direct embedded schema calls from the Dataset SQL query before continuing." if sql_query_includes_hard_coded_schema?
|
83
|
+
end
|
84
|
+
|
85
|
+
# attrs as per swagger docs for dataset patch
|
86
|
+
def acceptable_attributes
|
87
|
+
%w(
|
88
|
+
always_filter_main_dttm
|
89
|
+
cache_timeout
|
90
|
+
columns
|
91
|
+
database_id
|
92
|
+
default_endpoint
|
93
|
+
description
|
94
|
+
extra
|
95
|
+
fetch_values_predicate
|
96
|
+
filter_select_enabled
|
97
|
+
is_managed_externally
|
98
|
+
is_sqllab_view
|
99
|
+
main_dttm_col
|
100
|
+
metrics
|
101
|
+
normalize_columns
|
102
|
+
offset
|
103
|
+
owners
|
104
|
+
schema
|
105
|
+
sql
|
106
|
+
table_name
|
107
|
+
template_params
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def route
|
112
|
+
"dataset/#{source_dataset_id}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def target_database_available_schemas
|
116
|
+
Superset::Database::GetSchemas.call(target_database_id)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Superset
|
2
|
+
module Dataset
|
3
|
+
class WarmUpCache < Superset::Request
|
4
|
+
|
5
|
+
attr_reader :dashboard_id, :table_name, :db_name
|
6
|
+
|
7
|
+
def initialize(dashboard_id:, table_name:, db_name:)
|
8
|
+
@dashboard_id = dashboard_id
|
9
|
+
@table_name = table_name
|
10
|
+
@db_name = db_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform
|
14
|
+
response
|
15
|
+
end
|
16
|
+
|
17
|
+
def response
|
18
|
+
logger.info("Hitting #{route} for warming up the cache for the dashboard #{dashboard_id.to_s} and for the dataset #{table_name}")
|
19
|
+
client.put(route, params(dashboard_id, table_name, db_name))
|
20
|
+
end
|
21
|
+
|
22
|
+
def params(dashboard_id, table_name, db_name)
|
23
|
+
{
|
24
|
+
"dashboard_id" => dashboard_id,
|
25
|
+
"table_name" => table_name,
|
26
|
+
"db_name" => db_name
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def route
|
33
|
+
"dataset/warm_up_cache"
|
34
|
+
end
|
35
|
+
|
36
|
+
def logger
|
37
|
+
@logger ||= Superset::Logger.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Superset
|
2
|
+
module Display
|
3
|
+
def list
|
4
|
+
puts table.to_s
|
5
|
+
end
|
6
|
+
|
7
|
+
def table
|
8
|
+
Terminal::Table.new(
|
9
|
+
title: title,
|
10
|
+
headings: headings,
|
11
|
+
rows: rows
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def rows
|
16
|
+
result.map do |d|
|
17
|
+
list_attributes.map { |la| d[la].to_s }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def title
|
22
|
+
self.class.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def headings
|
26
|
+
headings = display_headers ? display_headers : list_attributes
|
27
|
+
headings.map(&:to_s).map(&:humanize)
|
28
|
+
end
|
29
|
+
|
30
|
+
def display_headers
|
31
|
+
# optionally override this method to display custom headers
|
32
|
+
end
|
33
|
+
|
34
|
+
def list_attributes
|
35
|
+
raise NotImplementedError.new("You must implement list_attributes.")
|
36
|
+
end
|
37
|
+
|
38
|
+
def result
|
39
|
+
raise NotImplementedError.new("You must implement result.")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class ObjectType < EnumerateIt::Base
|
2
|
+
# replicates the Superset Core code base enum for Object Types
|
3
|
+
# https://github.com/apache/superset/blob/40e77be813c789c8b01aece739f32ff5753436b4/superset/tags/models.py#L79
|
4
|
+
|
5
|
+
associate_values(
|
6
|
+
query: 1,
|
7
|
+
chart: 2,
|
8
|
+
dashboard: 3,
|
9
|
+
dataset: 4
|
10
|
+
)
|
11
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'zip'
|
2
|
+
|
3
|
+
module Superset
|
4
|
+
module FileUtilities
|
5
|
+
def unzip_file(zip_file, destination)
|
6
|
+
entries = []
|
7
|
+
Zip::File.open(zip_file) do |zip|
|
8
|
+
zip.each do |entry|
|
9
|
+
entry_path = File.join(destination, entry.name)
|
10
|
+
entries << entry_path
|
11
|
+
FileUtils.mkdir_p(File.dirname(entry_path))
|
12
|
+
zip.extract(entry, entry_path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
puts entries
|
16
|
+
entries # return array of extracted files
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Superset
|
2
|
+
class GuestToken
|
3
|
+
include Credential::EmbeddedUser
|
4
|
+
|
5
|
+
attr_accessor :embedded_dashboard_id, :current_user
|
6
|
+
|
7
|
+
def initialize(embedded_dashboard_id: , current_user: nil)
|
8
|
+
@embedded_dashboard_id = embedded_dashboard_id
|
9
|
+
@current_user = current_user
|
10
|
+
end
|
11
|
+
|
12
|
+
def guest_token
|
13
|
+
response_body['token']
|
14
|
+
end
|
15
|
+
|
16
|
+
def params
|
17
|
+
{
|
18
|
+
"resources": [
|
19
|
+
{
|
20
|
+
"id": embedded_dashboard_id.to_s,
|
21
|
+
"type": "dashboard" }
|
22
|
+
],
|
23
|
+
"rls": [],
|
24
|
+
"user": current_user_params
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# optional param to be available in Superset for query templating using jinja
|
31
|
+
# ss expects username .. which could be used to query as current_user.id
|
32
|
+
def current_user_params
|
33
|
+
if current_user
|
34
|
+
{ "username": current_user.id.to_s }
|
35
|
+
else
|
36
|
+
{ }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def response_body
|
41
|
+
response.env.body
|
42
|
+
end
|
43
|
+
|
44
|
+
def route
|
45
|
+
'api/v1/security/guest_token/'
|
46
|
+
end
|
47
|
+
|
48
|
+
def response
|
49
|
+
@response ||= connection.post(route, params.to_json)
|
50
|
+
end
|
51
|
+
|
52
|
+
def connection
|
53
|
+
@connection ||= Faraday.new(authenticator.superset_host) do |f|
|
54
|
+
f.authorization :Bearer, access_token
|
55
|
+
f.use FaradayMiddleware::ParseJson, content_type: 'application/json'
|
56
|
+
f.request :json
|
57
|
+
f.adapter :net_http
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def access_token
|
62
|
+
@access_token ||= authenticator.access_token
|
63
|
+
end
|
64
|
+
|
65
|
+
def authenticator
|
66
|
+
@authenticator ||= Superset::Authenticator.new(credentials)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Superset
|
2
|
+
class Logger
|
3
|
+
|
4
|
+
def info(msg)
|
5
|
+
# puts msg # allow logs to console
|
6
|
+
logger.info msg
|
7
|
+
end
|
8
|
+
|
9
|
+
def error(msg)
|
10
|
+
# puts msg # allow logs to console
|
11
|
+
logger.error msg
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger
|
15
|
+
@logger ||= begin
|
16
|
+
::Logger.new("log/superset-client.log")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Superset
|
2
|
+
class Request
|
3
|
+
include Display
|
4
|
+
|
5
|
+
class InvalidParameterError < StandardError; end
|
6
|
+
class ValidationError < StandardError; end
|
7
|
+
|
8
|
+
|
9
|
+
PAGE_SIZE = 100
|
10
|
+
|
11
|
+
attr_accessor :page_num
|
12
|
+
|
13
|
+
def initialize(page_num: 0)
|
14
|
+
@page_num = page_num
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.call
|
18
|
+
self.new.response
|
19
|
+
end
|
20
|
+
|
21
|
+
def response
|
22
|
+
@response ||= client.get(route)
|
23
|
+
rescue => e
|
24
|
+
logger.error("#{e.message}")
|
25
|
+
raise e
|
26
|
+
end
|
27
|
+
|
28
|
+
def result
|
29
|
+
response['result']
|
30
|
+
end
|
31
|
+
|
32
|
+
def superset_host
|
33
|
+
client.superset_host
|
34
|
+
end
|
35
|
+
|
36
|
+
def query_params
|
37
|
+
[filters, pagination].join
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def route
|
43
|
+
raise NotImplementedError.new("You must implement route.")
|
44
|
+
end
|
45
|
+
|
46
|
+
def client
|
47
|
+
@client ||= Superset::Client.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def pagination
|
51
|
+
"page:#{page_num},page_size:#{PAGE_SIZE}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def filters
|
55
|
+
""
|
56
|
+
end
|
57
|
+
|
58
|
+
def logger
|
59
|
+
@logger ||= Superset::Logger.new
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Superset
|
2
|
+
class RouteInfo < Superset::Request
|
3
|
+
alias result response
|
4
|
+
|
5
|
+
attr_reader :route
|
6
|
+
|
7
|
+
def initialize(route:)
|
8
|
+
@route = route
|
9
|
+
end
|
10
|
+
|
11
|
+
def perform
|
12
|
+
validate_route
|
13
|
+
response
|
14
|
+
end
|
15
|
+
|
16
|
+
def response
|
17
|
+
validate_route
|
18
|
+
@response ||= client.get(route)
|
19
|
+
end
|
20
|
+
|
21
|
+
def filters
|
22
|
+
result['filters']
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def validate_route
|
28
|
+
unless route.present? && route.is_a?(String)
|
29
|
+
puts "Example Route: 'dashboard/_info' "
|
30
|
+
raise "Error: route string is required" unless route.present? && route.is_a?(String)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module PermissionsResources
|
4
|
+
class List < Superset::Request
|
5
|
+
|
6
|
+
def initialize(page_num: 0)
|
7
|
+
super(page_num: page_num)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def list_attributes
|
13
|
+
[:id, :permission, :view_menu]
|
14
|
+
end
|
15
|
+
|
16
|
+
def route
|
17
|
+
"security/permissions-resources/?q=(#{pagination})"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module Role
|
4
|
+
class Create < Superset::Request
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(name: '')
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def response
|
12
|
+
raise InvalidParameterError unless name.present?
|
13
|
+
|
14
|
+
@response ||= client.post(route, { 'name' => name } )
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def route
|
20
|
+
"security/roles/"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module Role
|
4
|
+
class Get < Superset::Request
|
5
|
+
attr_reader :id
|
6
|
+
|
7
|
+
def initialize(id)
|
8
|
+
@id = id
|
9
|
+
end
|
10
|
+
|
11
|
+
def result
|
12
|
+
[ super ]
|
13
|
+
end
|
14
|
+
|
15
|
+
def id_and_name
|
16
|
+
result.first.slice(:id, :name).values.join(': ')
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def list_attributes
|
22
|
+
[:id, :name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def route
|
26
|
+
"security/roles/#{id}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module Role
|
4
|
+
class List < Superset::Request
|
5
|
+
attr_reader :name_contains, :name_equals
|
6
|
+
|
7
|
+
def initialize(page_num: 0, name_contains: nil, name_equals: nil)
|
8
|
+
@name_contains= name_contains
|
9
|
+
@name_equals= name_equals
|
10
|
+
super(page_num: page_num)
|
11
|
+
end
|
12
|
+
|
13
|
+
def query_params
|
14
|
+
[filters, pagination].join
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def route
|
20
|
+
"security/roles/?q=(#{query_params})"
|
21
|
+
end
|
22
|
+
|
23
|
+
def filters
|
24
|
+
raise 'ERROR: only one filter supported currently' if name_contains.present? && name_equals.present?
|
25
|
+
|
26
|
+
if name_contains.present?
|
27
|
+
"filters:!((col:name,opr:ct,value:'#{name_contains}')),"
|
28
|
+
elsif name_equals.present?
|
29
|
+
"filters:!((col:name,opr:eq,value:'#{name_equals}')),"
|
30
|
+
else
|
31
|
+
''
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def title
|
36
|
+
"#{response[:count]} Roles for Host: #{superset_host}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def list_attributes
|
40
|
+
[:id, :name]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module Role
|
4
|
+
module Permission
|
5
|
+
class Create < Superset::Request
|
6
|
+
attr_reader :role_id, :permission_view_menu_ids
|
7
|
+
|
8
|
+
def initialize(role_id:, permission_view_menu_ids: [])
|
9
|
+
@permission_view_menu_ids = permission_view_menu_ids
|
10
|
+
@role_id = role_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def response
|
14
|
+
raise InvalidParameterError unless valid_params?
|
15
|
+
|
16
|
+
@response ||= client.post(route,
|
17
|
+
{ "permission_view_menu_ids": permission_view_menu_ids } )
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def valid_params?
|
23
|
+
role_id.present? &&
|
24
|
+
permission_view_menu_ids.is_a?(Array) &&
|
25
|
+
!permission_view_menu_ids.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def route
|
29
|
+
"security/roles/#{role_id}/permissions"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module Role
|
4
|
+
module Permission
|
5
|
+
class Get < Superset::Request
|
6
|
+
attr_reader :id
|
7
|
+
|
8
|
+
def initialize(id)
|
9
|
+
@id = id
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.call(id)
|
13
|
+
self.new(id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def result
|
17
|
+
response[:result]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def list_attributes
|
23
|
+
[:id, :permission_name, :view_menu_name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def route
|
27
|
+
"security/roles/#{id}/permissions/"
|
28
|
+
end
|
29
|
+
|
30
|
+
def title
|
31
|
+
Superset::Security::Role::Get.new(id).id_and_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Superset
|
2
|
+
module Security
|
3
|
+
module User
|
4
|
+
class Create < Superset::Request
|
5
|
+
attr_reader :user_params
|
6
|
+
|
7
|
+
def initialize(user_params: {})
|
8
|
+
@user_params = user_params.with_indifferent_access
|
9
|
+
end
|
10
|
+
|
11
|
+
def response
|
12
|
+
validate_user_params
|
13
|
+
|
14
|
+
@response ||= client.post(route, user_params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_user_params
|
18
|
+
raise InvalidParameterError, "Missing user params. Expects #{valid_user_params_keys}" unless symbolized_user_param_keys == valid_user_params_keys
|
19
|
+
raise InvalidParameterError, 'Roles must be an array ' unless user_params[:roles].is_a?(Array)
|
20
|
+
confirm_all_params_present
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def error_message
|
26
|
+
errors = ''
|
27
|
+
end
|
28
|
+
|
29
|
+
def confirm_all_params_present
|
30
|
+
symbolized_user_param_keys.each do |key|
|
31
|
+
raise InvalidParameterError, "Missing #{key}" unless user_params[key].present?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def symbolized_user_param_keys
|
36
|
+
user_params.keys.map(&:to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid_user_params_keys
|
40
|
+
[ :active, :email, :first_name, :last_name, :password, :roles, :username ]
|
41
|
+
end
|
42
|
+
|
43
|
+
def route
|
44
|
+
"security/users/"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|