superset 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|