superset 0.3.6 → 0.5.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 +4 -4
- data/AGENTS.md +105 -0
- data/CHANGELOG.md +16 -0
- data/CLAUDE.md +1 -0
- data/README.md +17 -0
- data/doc/setting_up_personal_api_credentials.md +22 -2
- data/lib/superset/client.rb +34 -0
- data/lib/superset/configuration.rb +11 -0
- data/lib/superset/dashboard/import.rb +1 -0
- data/lib/superset/dashboard/warm_up_cache.rb +3 -7
- data/lib/superset/file_utilities.rb +3 -2
- data/lib/superset/guest_token.rb +17 -1
- data/lib/superset/logger.rb +2 -11
- data/lib/superset/services/import_dashboard_across_environment.rb +1 -0
- data/lib/superset/version.rb +1 -1
- data/lib/superset.rb +30 -1
- data/superset.gemspec +7 -2
- metadata +27 -25
- data/lib/loggers/duplicate_dashboard_logger.rb +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59ab63d9f8d51f73e9ca6606a0a559c75def26e9c69ab09eeeb59fd91cf24447
|
|
4
|
+
data.tar.gz: c7ae83dfa2a5b5f0e100d6cce0d38e7badf04e20d174c661207223493179f851
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f0f70518ea7bc2f9e19ba9c115bdb1c2c44f05abc0e887fcfb0de1934499847841e601ec0d5e8aabb957c368196873cad0bae6ccb300ce55fe8d9eedd3c4e29
|
|
7
|
+
data.tar.gz: 3a90c54aca065f2187bf971912dc2993f25034f6c1880fb4d973a90da3b2a1d63188871acfe64d7448abd431f27a2ea52ecc91d1c9c55194f9815016b8872b61
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Agents
|
|
2
|
+
|
|
3
|
+
This file provides guidance to AI coding agents working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
bundle install
|
|
10
|
+
|
|
11
|
+
# Open interactive console (auto-loads .env)
|
|
12
|
+
bin/console
|
|
13
|
+
|
|
14
|
+
# Run full test suite
|
|
15
|
+
rspec
|
|
16
|
+
|
|
17
|
+
# Run a single test file
|
|
18
|
+
rspec spec/path/to/test_spec.rb
|
|
19
|
+
|
|
20
|
+
# Run a single test by line number
|
|
21
|
+
rspec spec/path/to/test_spec.rb:42
|
|
22
|
+
|
|
23
|
+
# Lint
|
|
24
|
+
rubocop
|
|
25
|
+
|
|
26
|
+
# Run specs + rubocop together
|
|
27
|
+
rake
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Docker equivalents: prefix commands with `docker-compose run --rm app`.
|
|
31
|
+
|
|
32
|
+
### Environment Setup
|
|
33
|
+
|
|
34
|
+
Copy `env.sample` to `.env` and fill in:
|
|
35
|
+
- `SUPERSET_HOST` — API base URL (required)
|
|
36
|
+
- `SUPERSET_API_USERNAME` / `SUPERSET_API_PASSWORD` — API credentials (required)
|
|
37
|
+
- `SUPERSET_ENVIRONMENT` — optional; loads `.env-{ENVIRONMENT}` instead
|
|
38
|
+
- `CONSOLE_TIMEOUT` — seconds before auto-logout in console (default 1800)
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
### Request Framework
|
|
43
|
+
|
|
44
|
+
All API interactions inherit from `Superset::Request` (`lib/superset/request.rb`). Subclasses implement:
|
|
45
|
+
- `route` — returns the API path (e.g., `"dashboard/#{id}"`)
|
|
46
|
+
- `filters` — returns a filter query string or `""`
|
|
47
|
+
- `list_attributes` — array of field names used for terminal table display
|
|
48
|
+
|
|
49
|
+
**Patterns by HTTP verb:**
|
|
50
|
+
- **GET/LIST** — inherit `Superset::Request`, implement `route` and `filters`
|
|
51
|
+
- **PUT** — inherit `Superset::BasePutRequest`, takes `target_id:` and `params:`, implement `route`
|
|
52
|
+
- **DELETE/POST** — call `client.delete(route)` or `client.post(route, params)` directly
|
|
53
|
+
|
|
54
|
+
Pagination is built into `Superset::Request` (default page size: 100, max: 1000). List classes accept `page_num:` and `page_size:` kwargs.
|
|
55
|
+
|
|
56
|
+
### Authentication Flow
|
|
57
|
+
|
|
58
|
+
1. `Superset::Client` (extends `Happi::Client`) includes `Credential::ApiUser` and creates a `Superset::Authenticator`
|
|
59
|
+
2. `Authenticator` POSTs to `api/v1/security/login` and extracts `access_token`
|
|
60
|
+
3. `Client#connection` builds a Faraday connection with Bearer token; supports both JSON and multipart modes (`config.use_json`)
|
|
61
|
+
|
|
62
|
+
### Query Filter Syntax
|
|
63
|
+
|
|
64
|
+
Superset uses an ORM-like filter string format:
|
|
65
|
+
```
|
|
66
|
+
filters:!((col:column_name,opr:operation,value:value)),
|
|
67
|
+
```
|
|
68
|
+
Common operations: `ct` (contains), `eq` (equals), `neq` (not equals), `rel_o_m`, `rel_m_m`, `dashboard_tags`.
|
|
69
|
+
|
|
70
|
+
### Service Layer
|
|
71
|
+
|
|
72
|
+
`lib/superset/services/` contains complex multi-step workflows. The main one is `DuplicateDashboard`, which:
|
|
73
|
+
1. Validates source/target IDs, schema existence, and data sovereignty rules (all chart datasets must share the same DB schema)
|
|
74
|
+
2. Copies the dashboard and its charts
|
|
75
|
+
3. Duplicates datasets pointing to the target schema
|
|
76
|
+
4. Rewires chart JSON metadata and filter configs to the new dataset IDs
|
|
77
|
+
5. Optionally sets embedded config, tags, and publishes
|
|
78
|
+
6. **Rolls back all created objects on failure**
|
|
79
|
+
|
|
80
|
+
`ImportDashboardAcrossEnvironment` handles cross-environment migration via export/import ZIP files.
|
|
81
|
+
|
|
82
|
+
### Display Mixin
|
|
83
|
+
|
|
84
|
+
`Superset::Display` (`lib/superset/display.rb`) is included in `Superset::Request` and provides `list`, `rows`, `to_h`, and `ids`. Requires `list_attributes` and `result` to be implemented by the subclass.
|
|
85
|
+
|
|
86
|
+
### Resource–Relationship Model
|
|
87
|
+
|
|
88
|
+
- **Dashboards** contain **Charts**
|
|
89
|
+
- **Charts** reference **Datasets** (datasources)
|
|
90
|
+
- **Dashboard JSON metadata** stores layout, chart positions, and filter configurations
|
|
91
|
+
- **Filters** reference Datasets for filter values
|
|
92
|
+
- Duplication/migration requires updating all these cross-references
|
|
93
|
+
|
|
94
|
+
### Conventions
|
|
95
|
+
|
|
96
|
+
- Namespace: `Superset::<ResourceType>::<Action>` (e.g., `Superset::Dashboard::List`)
|
|
97
|
+
- `perform` — executes a state-changing action, returns `self`
|
|
98
|
+
- `response` — raw (cached) HTTP response
|
|
99
|
+
- `result` — extracts `response['result']`
|
|
100
|
+
- Constructor filter params follow naming: `title_contains:`, `title_equals:`, etc.
|
|
101
|
+
- Logging goes through `Superset.logger`; by default writes to `log/superset-client.log`. Consumers can inject any `::Logger`-compatible object via `Superset.configure { |c| c.logger = your_logger }`.
|
|
102
|
+
|
|
103
|
+
### Console Helpers
|
|
104
|
+
|
|
105
|
+
In `bin/console`: `sshelp` (alias: `superset_class_list`) lists all available `Superset::` classes. On startup, `Superset::Database::List.call` prints available DB connections.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0 - 2026-07-21
|
|
4
|
+
|
|
5
|
+
* Decouple from Rollbar — remove the `Rollbar.error(...) if defined?(Rollbar)` call in `WarmUpCache`; exceptions now propagate to the caller so consumers' own error handling can react
|
|
6
|
+
* Introduce configurable logger via `Superset.configure { |c| c.logger = ... }` — any object responding to `#info` and `#error` (default remains `log/superset-client.log`)
|
|
7
|
+
* **Breaking:** `Superset::Dashboard::WarmUpCache.new(...).perform` now raises on per-dataset failures instead of swallowing them; wrap the call in your own `rescue` if you need the previous silent behavior
|
|
8
|
+
* Remove unused `DuplicateDashboardLogger` module (dead code)
|
|
9
|
+
* Drop `rollbar` dev dependency; drop `require "rollbar"` from `spec_helper.rb` and `bin/console`
|
|
10
|
+
* Add explicit `require 'json'` (the gem uses `to_json` in 8+ places and was relying on rollbar to transitively load it)
|
|
11
|
+
|
|
12
|
+
## 0.4.0 - 2026-06-05
|
|
13
|
+
|
|
14
|
+
* send X-CSRFToken (and replay the session cookie) on state-changing requests so writes work against a CSRF-protected Superset
|
|
15
|
+
* send a same-origin Referer on state-changing requests to satisfy Flask-WTF WTF_CSRF_SSL_STRICT over HTTPS
|
|
16
|
+
* GuestToken: send X-CSRFToken + Referer (and replay the session cookie) on the guest_token POST — that endpoint is CSRF-protected too, so embedded dashboards broke without it
|
|
17
|
+
* add faraday-cookie_jar dependency
|
|
18
|
+
|
|
3
19
|
## 0.3.6 - 2026-02-26
|
|
4
20
|
|
|
5
21
|
* add dry_run to dashboard bulk delete cascade #74
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See [AGENTS.md](AGENTS.md) for project context and development instructions.
|
data/README.md
CHANGED
|
@@ -44,6 +44,23 @@ Add to your Gemfile `gem 'superset'`
|
|
|
44
44
|
And then execute: `bundle install`
|
|
45
45
|
Or install it yourself as `gem install superset`
|
|
46
46
|
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
The gem writes logs (dashboard duplication progress, API failures, etc.) through `Superset.logger`. By default it writes to `log/superset-client.log` relative to the working directory.
|
|
50
|
+
|
|
51
|
+
To route logs elsewhere — for example, STDOUT for a background worker, a null sink for tests, or your application's existing logger — configure it once at boot:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
require 'logger'
|
|
55
|
+
require 'superset'
|
|
56
|
+
|
|
57
|
+
Superset.configure do |config|
|
|
58
|
+
config.logger = ::Logger.new($stdout) # or any object responding to #info(msg) and #error(msg)
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Any object that responds to `#info(msg)` and `#error(msg)` will work — a stdlib `::Logger`, a `SemanticLogger` instance, a framework-provided logger, or a custom wrapper that forwards to your error-reporting service. The gem does not assume any particular framework.
|
|
63
|
+
|
|
47
64
|
## Run specs
|
|
48
65
|
|
|
49
66
|
```
|
|
@@ -4,6 +4,8 @@ Superset API Credentials are essentially the username, password and host of the
|
|
|
4
4
|
|
|
5
5
|
If you know these already, plug them and your host value into the `.env` and it should all just work. A sample env.sample is provided as a template.
|
|
6
6
|
|
|
7
|
+
Note: `.env` files are for local development only—do not store production credentials in a `.env` file (or commit it to git). In production, inject secrets at runtime via your platform's environment variables or a secret manager.
|
|
8
|
+
|
|
7
9
|
Create your own .env file with
|
|
8
10
|
|
|
9
11
|
```
|
|
@@ -59,9 +61,17 @@ Scroll down to the 'Security Users' area and find the PUT request that will upda
|
|
|
59
61
|
|
|
60
62
|
PUT `/api/v1/security/users/{pk}`
|
|
61
63
|
|
|
62
|
-
Click 'Try it Out' and add your users ID in the PK input box.
|
|
64
|
+
Click 'Try it Out' and add your users ID in the PK input box.
|
|
65
|
+
|
|
66
|
+
Generate a secure random password with your preferred tool ... or in ruby with something like:
|
|
67
|
+
```ruby
|
|
68
|
+
# ruby SecureRandom code to provide 32 random bytes
|
|
69
|
+
require 'securerandom'
|
|
70
|
+
SecureRandom.urlsafe_base64(32)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Edit the params to only consist of only the password field and the value of your new password.
|
|
63
74
|
|
|
64
|
-
Edit the params to only consist of only the password field and the value of your new password.
|
|
65
75
|
|
|
66
76
|
```
|
|
67
77
|
{
|
|
@@ -159,5 +169,15 @@ Superset::GuestToken.new(embedded_dashboard_id: '15').guest_token
|
|
|
159
169
|
=> "eyJ0eXAiOi............VV4mrMfsvg"
|
|
160
170
|
```
|
|
161
171
|
|
|
172
|
+
## Troubleshooting tips
|
|
162
173
|
|
|
174
|
+
### Password or token expired
|
|
175
|
+
|
|
176
|
+
If your Superset password has expired (or your auth token is no longer valid), API calls may fail with an error like:
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
179
|
+
Superset::Dashboard::List.call
|
|
180
|
+
ArgumentError: Can't build an Authorization Bearer header from nil
|
|
181
|
+
```
|
|
163
182
|
|
|
183
|
+
Fix: refresh your credentials via swagger interface then update your credentials in .env and try again.
|
data/lib/superset/client.rb
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
require 'faraday-cookie_jar'
|
|
2
|
+
|
|
1
3
|
module Superset
|
|
2
4
|
class Client < Happi::Client
|
|
3
5
|
include Credential::ApiUser
|
|
4
6
|
|
|
7
|
+
# Superset enforces CSRF on state-changing requests once WTF_CSRF_ENABLED is on;
|
|
8
|
+
# GETs are never CSRF-checked. Bearer-token auth is not sufficient,
|
|
9
|
+
# so these verbs must carry an X-CSRFToken header (see #call / #csrf_token).
|
|
10
|
+
CSRF_PROTECTED_METHODS = %i[post put patch delete].freeze
|
|
11
|
+
|
|
5
12
|
attr_reader :authenticator
|
|
6
13
|
|
|
7
14
|
def initialize
|
|
@@ -17,6 +24,15 @@ module Superset
|
|
|
17
24
|
@superset_host ||= authenticator.superset_host
|
|
18
25
|
end
|
|
19
26
|
|
|
27
|
+
# All verbs funnel through Happi::Client#call. Before any state-changing request,
|
|
28
|
+
# attach a CSRF token; fetching one also sets the Flask session cookie that the
|
|
29
|
+
# token is validated against, which the cookie jar on this connection replays on
|
|
30
|
+
# the write.
|
|
31
|
+
def call(method, url, params = {})
|
|
32
|
+
set_csrf_token if CSRF_PROTECTED_METHODS.include?(method)
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
|
|
20
36
|
# TODO: Happi has not got a put method yet
|
|
21
37
|
def put(resource, params = {})
|
|
22
38
|
call(:put, url(resource), param_check(params))
|
|
@@ -40,9 +56,27 @@ module Superset
|
|
|
40
56
|
|
|
41
57
|
private
|
|
42
58
|
|
|
59
|
+
# Set the CSRF headers for the upcoming write:
|
|
60
|
+
# * X-CSRFToken — session-bound token; GET /api/v1/security/csrf_token/ returns it
|
|
61
|
+
# and sets the Flask session cookie it is validated against (the cookie jar on
|
|
62
|
+
# this connection replays that cookie on the write).
|
|
63
|
+
# * Referer — over HTTPS, Flask-WTF's WTF_CSRF_SSL_STRICT (default True) also
|
|
64
|
+
# requires a Referer matching the Superset host (same-origin check), else the
|
|
65
|
+
# write fails with "400 The referrer header is missing." Browsers send this
|
|
66
|
+
# automatically; an API client must set it explicitly.
|
|
67
|
+
def set_csrf_token
|
|
68
|
+
connection.headers['X-CSRFToken'] = csrf_token
|
|
69
|
+
connection.headers['Referer'] = superset_host
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def csrf_token
|
|
73
|
+
@csrf_token ||= get('security/csrf_token/')['result']
|
|
74
|
+
end
|
|
75
|
+
|
|
43
76
|
def connection
|
|
44
77
|
@connection ||= Faraday.new(superset_host) do |f|
|
|
45
78
|
f.authorization :Bearer, access_token
|
|
79
|
+
f.use :cookie_jar # persist the Flask session cookie across the csrf_token GET and the write
|
|
46
80
|
f.use FaradayMiddleware::ParseJson, content_type: 'application/json'
|
|
47
81
|
|
|
48
82
|
if self.config.use_json
|
|
@@ -78,6 +78,7 @@ module Superset
|
|
|
78
78
|
def source_zip_file
|
|
79
79
|
return source if zip?
|
|
80
80
|
|
|
81
|
+
require 'zip' # lazy: only import/export needs rubyzip
|
|
81
82
|
Zip::File.open(new_zip_file, create: true) do |zipfile|
|
|
82
83
|
Dir[File.join(source, "**", "**")].each do |file|
|
|
83
84
|
next unless File.file?(file)
|
|
@@ -3,7 +3,7 @@ module Superset
|
|
|
3
3
|
class WarmUpCache < Superset::Request
|
|
4
4
|
|
|
5
5
|
attr_reader :dashboard_id
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
def initialize(dashboard_id:)
|
|
8
8
|
@dashboard_id = dashboard_id
|
|
9
9
|
end
|
|
@@ -16,11 +16,7 @@ module Superset
|
|
|
16
16
|
def response
|
|
17
17
|
dataset_details = fetch_dataset_details(dashboard_id)
|
|
18
18
|
dataset_details.each do |dataset|
|
|
19
|
-
|
|
20
|
-
warm_up_dataset(dataset["datasource_name"], dataset["name"])
|
|
21
|
-
rescue => e
|
|
22
|
-
Rollbar.error("Warm up cache failed for the dashboard #{dashboard_id.to_s} and for the dataset #{dataset["datasource_name"]} - #{e}") if defined?(Rollbar)
|
|
23
|
-
end
|
|
19
|
+
warm_up_dataset(dataset["datasource_name"], dataset["name"])
|
|
24
20
|
end
|
|
25
21
|
end
|
|
26
22
|
|
|
@@ -29,7 +25,7 @@ module Superset
|
|
|
29
25
|
end
|
|
30
26
|
|
|
31
27
|
private
|
|
32
|
-
|
|
28
|
+
|
|
33
29
|
def validate_dashboard_id
|
|
34
30
|
raise InvalidParameterError, "dashboard_id must be present and must be an integer" unless dashboard_id.present? && dashboard_id.is_a?(Integer)
|
|
35
31
|
end
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
require 'zip'
|
|
2
|
-
|
|
3
1
|
module Superset
|
|
4
2
|
module FileUtilities
|
|
3
|
+
# rubyzip is loaded lazily so the gem can be required without it; only
|
|
4
|
+
# consumers that actually import/export need rubyzip installed.
|
|
5
5
|
def unzip_file(zip_file, destination)
|
|
6
|
+
require 'zip'
|
|
6
7
|
entries = []
|
|
7
8
|
Zip::File.open(zip_file) do |zip|
|
|
8
9
|
zip.each do |entry|
|
data/lib/superset/guest_token.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'faraday-cookie_jar'
|
|
2
|
+
|
|
1
3
|
module Superset
|
|
2
4
|
class GuestToken
|
|
3
5
|
include Credential::EmbeddedUser
|
|
@@ -52,13 +54,27 @@ module Superset
|
|
|
52
54
|
'api/v1/security/guest_token/'
|
|
53
55
|
end
|
|
54
56
|
|
|
57
|
+
# The guest_token endpoint is CSRF-protected (it is NOT in Superset's CSRF
|
|
58
|
+
# exempt list), so this POST needs the same treatment as Client writes:
|
|
59
|
+
# an X-CSRFToken bound to the session cookie, plus a same-origin
|
|
60
|
+
# Referer for WTF_CSRF_SSL_STRICT over HTTPS. The csrf_token GET also sets the
|
|
61
|
+
# session cookie that the cookie jar replays on the POST.
|
|
55
62
|
def response
|
|
56
|
-
@response ||=
|
|
63
|
+
@response ||= begin
|
|
64
|
+
connection.headers['X-CSRFToken'] = csrf_token
|
|
65
|
+
connection.headers['Referer'] = authenticator.superset_host
|
|
66
|
+
connection.post(route, params.to_json)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def csrf_token
|
|
71
|
+
@csrf_token ||= connection.get('api/v1/security/csrf_token/').env.body['result']
|
|
57
72
|
end
|
|
58
73
|
|
|
59
74
|
def connection
|
|
60
75
|
@connection ||= Faraday.new(authenticator.superset_host) do |f|
|
|
61
76
|
f.authorization :Bearer, access_token
|
|
77
|
+
f.use :cookie_jar # replay the Flask session cookie from the csrf_token GET on the POST
|
|
62
78
|
f.use FaradayMiddleware::ParseJson, content_type: 'application/json'
|
|
63
79
|
f.request :json
|
|
64
80
|
f.adapter :net_http
|
data/lib/superset/logger.rb
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
module Superset
|
|
2
2
|
class Logger
|
|
3
|
-
|
|
4
3
|
def info(msg)
|
|
5
|
-
|
|
6
|
-
logger.info msg
|
|
4
|
+
Superset.logger.info(msg)
|
|
7
5
|
end
|
|
8
6
|
|
|
9
7
|
def error(msg)
|
|
10
|
-
|
|
11
|
-
logger.error msg
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def logger
|
|
15
|
-
@logger ||= begin
|
|
16
|
-
::Logger.new("log/superset-client.log")
|
|
17
|
-
end
|
|
8
|
+
Superset.logger.error(msg)
|
|
18
9
|
end
|
|
19
10
|
end
|
|
20
11
|
end
|
|
@@ -87,6 +87,7 @@ module Superset
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def create_new_dashboard_zip
|
|
90
|
+
require 'zip' # lazy: only import/export needs rubyzip
|
|
90
91
|
Zip::File.open(new_zip_file, create: true) do |zipfile|
|
|
91
92
|
Dir[File.join(dashboard_export_root_path, '**', '**')].each do |file|
|
|
92
93
|
zipfile.add(file.sub(dashboard_export_root_path + '/', File.basename(dashboard_export_root_path) + '/' ), file) if File.file?(file)
|
data/lib/superset/version.rb
CHANGED
data/lib/superset.rb
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
require 'require_all'
|
|
4
4
|
require 'terminal-table'
|
|
5
5
|
require 'happi'
|
|
6
|
+
require 'logger'
|
|
7
|
+
require 'json'
|
|
6
8
|
|
|
9
|
+
require_relative "superset/configuration"
|
|
7
10
|
require_rel "superset/credential"
|
|
8
11
|
require_relative "superset/authenticator"
|
|
9
12
|
require_relative "superset/client"
|
|
@@ -15,5 +18,31 @@ require_rel "superset"
|
|
|
15
18
|
|
|
16
19
|
module Superset
|
|
17
20
|
class Error < StandardError; end
|
|
18
|
-
|
|
21
|
+
|
|
22
|
+
DEFAULT_LOG_PATH = "log/superset-client.log"
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
def configuration
|
|
26
|
+
@configuration ||= Configuration.new
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def configure
|
|
30
|
+
yield configuration
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def logger
|
|
34
|
+
configuration.logger || default_logger
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def reset_configuration!
|
|
38
|
+
@configuration = nil
|
|
39
|
+
@default_logger = nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def default_logger
|
|
45
|
+
@default_logger ||= ::Logger.new(DEFAULT_LOG_PATH)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
19
48
|
end
|
data/superset.gemspec
CHANGED
|
@@ -37,17 +37,22 @@ Gem::Specification.new do |spec|
|
|
|
37
37
|
spec.add_dependency "json", ">= 2.0"
|
|
38
38
|
spec.add_dependency "terminal-table", "~> 4.0"
|
|
39
39
|
spec.add_dependency "require_all", ">= 3.0"
|
|
40
|
-
spec.add_dependency "rubyzip", ">= 3.0"
|
|
41
40
|
spec.add_dependency "faraday", "~> 1.0"
|
|
42
41
|
spec.add_dependency "faraday-multipart", "~> 1.0"
|
|
42
|
+
spec.add_dependency "faraday-cookie_jar", "~> 0.0.7" # replay the Flask session cookie for CSRF
|
|
43
43
|
spec.add_dependency "enumerate_it", ">= 1.7"
|
|
44
44
|
|
|
45
|
+
# rubyzip is only needed by the dashboard import/export feature, which lazily
|
|
46
|
+
# `require 'zip'` at call time. Kept as a dev dependency so those specs run here,
|
|
47
|
+
# but NOT a runtime dependency — consumers that don't import/export (embedders,
|
|
48
|
+
# read/write API clients) shouldn't inherit its rubyzip >= 3 pin.
|
|
49
|
+
# Apps that DO use import/export must declare rubyzip (>= 3.0) themselves.
|
|
50
|
+
spec.add_development_dependency "rubyzip", ">= 3.0"
|
|
45
51
|
spec.add_development_dependency "dotenv", ">= 2.0"
|
|
46
52
|
spec.add_development_dependency "rake", ">= 13.0"
|
|
47
53
|
spec.add_development_dependency "rspec", ">= 3.0"
|
|
48
54
|
spec.add_development_dependency "rubocop", ">= 1.0"
|
|
49
55
|
spec.add_development_dependency "pry", ">= 0.14"
|
|
50
|
-
spec.add_development_dependency "rollbar", ">= 3.0"
|
|
51
56
|
|
|
52
57
|
# For more information and examples about making a new gem, check out our
|
|
53
58
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: superset
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- jbat
|
|
@@ -52,21 +52,21 @@ dependencies:
|
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '3.0'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name:
|
|
55
|
+
name: faraday
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
|
-
- - "
|
|
58
|
+
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
60
|
+
version: '1.0'
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
|
-
- - "
|
|
65
|
+
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '
|
|
67
|
+
version: '1.0'
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: faraday
|
|
69
|
+
name: faraday-multipart
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
@@ -80,19 +80,19 @@ dependencies:
|
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
81
|
version: '1.0'
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
|
-
name: faraday-
|
|
83
|
+
name: faraday-cookie_jar
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
86
|
- - "~>"
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version:
|
|
88
|
+
version: 0.0.7
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version:
|
|
95
|
+
version: 0.0.7
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: enumerate_it
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -107,6 +107,20 @@ dependencies:
|
|
|
107
107
|
- - ">="
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: '1.7'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: rubyzip
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '3.0'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '3.0'
|
|
110
124
|
- !ruby/object:Gem::Dependency
|
|
111
125
|
name: dotenv
|
|
112
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -177,20 +191,6 @@ dependencies:
|
|
|
177
191
|
- - ">="
|
|
178
192
|
- !ruby/object:Gem::Version
|
|
179
193
|
version: '0.14'
|
|
180
|
-
- !ruby/object:Gem::Dependency
|
|
181
|
-
name: rollbar
|
|
182
|
-
requirement: !ruby/object:Gem::Requirement
|
|
183
|
-
requirements:
|
|
184
|
-
- - ">="
|
|
185
|
-
- !ruby/object:Gem::Version
|
|
186
|
-
version: '3.0'
|
|
187
|
-
type: :development
|
|
188
|
-
prerelease: false
|
|
189
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
190
|
-
requirements:
|
|
191
|
-
- - ">="
|
|
192
|
-
- !ruby/object:Gem::Version
|
|
193
|
-
version: '3.0'
|
|
194
194
|
email:
|
|
195
195
|
- jonathon.batson@gmail.com
|
|
196
196
|
executables: []
|
|
@@ -201,7 +201,9 @@ files:
|
|
|
201
201
|
- ".rspec"
|
|
202
202
|
- ".rubocop.yml"
|
|
203
203
|
- ".ruby-version"
|
|
204
|
+
- AGENTS.md
|
|
204
205
|
- CHANGELOG.md
|
|
206
|
+
- CLAUDE.md
|
|
205
207
|
- Dockerfile
|
|
206
208
|
- LICENSE
|
|
207
209
|
- README.md
|
|
@@ -214,7 +216,6 @@ files:
|
|
|
214
216
|
- docker-compose.override.yml
|
|
215
217
|
- docker-compose.yml
|
|
216
218
|
- env.sample
|
|
217
|
-
- lib/loggers/duplicate_dashboard_logger.rb
|
|
218
219
|
- lib/superset.rb
|
|
219
220
|
- lib/superset/authenticator.rb
|
|
220
221
|
- lib/superset/base_put_request.rb
|
|
@@ -227,6 +228,7 @@ files:
|
|
|
227
228
|
- lib/superset/chart/put.rb
|
|
228
229
|
- lib/superset/chart/update_dataset.rb
|
|
229
230
|
- lib/superset/client.rb
|
|
231
|
+
- lib/superset/configuration.rb
|
|
230
232
|
- lib/superset/credential/api_user.rb
|
|
231
233
|
- lib/superset/credential/embedded_user.rb
|
|
232
234
|
- lib/superset/dashboard/bulk_delete.rb
|