blazer 2.5.0 → 2.6.4
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/CHANGELOG.md +25 -0
- data/README.md +63 -15
- data/app/assets/javascripts/blazer/queries.js +12 -1
- data/app/assets/stylesheets/blazer/application.css +1 -0
- data/app/assets/stylesheets/blazer/bootstrap-propshaft.css +10 -0
- data/app/assets/stylesheets/blazer/bootstrap-sprockets.css.erb +10 -0
- data/app/assets/stylesheets/blazer/{bootstrap.css.erb → bootstrap.css} +0 -6
- data/app/controllers/blazer/base_controller.rb +45 -45
- data/app/controllers/blazer/dashboards_controller.rb +4 -11
- data/app/controllers/blazer/queries_controller.rb +29 -48
- data/app/models/blazer/query.rb +8 -2
- data/app/views/blazer/_variables.html.erb +5 -4
- data/app/views/blazer/dashboards/_form.html.erb +1 -1
- data/app/views/blazer/dashboards/show.html.erb +6 -4
- data/app/views/blazer/queries/_caching.html.erb +1 -1
- data/app/views/blazer/queries/_form.html.erb +3 -3
- data/app/views/blazer/queries/run.html.erb +1 -1
- data/app/views/blazer/queries/show.html.erb +12 -7
- data/app/views/layouts/blazer/application.html.erb +7 -2
- data/lib/blazer/adapters/athena_adapter.rb +55 -18
- data/lib/blazer/adapters/base_adapter.rb +16 -1
- data/lib/blazer/adapters/bigquery_adapter.rb +13 -2
- data/lib/blazer/adapters/cassandra_adapter.rb +15 -4
- data/lib/blazer/adapters/drill_adapter.rb +10 -0
- data/lib/blazer/adapters/druid_adapter.rb +36 -1
- data/lib/blazer/adapters/elasticsearch_adapter.rb +13 -2
- data/lib/blazer/adapters/hive_adapter.rb +10 -0
- data/lib/blazer/adapters/ignite_adapter.rb +12 -2
- data/lib/blazer/adapters/influxdb_adapter.rb +22 -10
- data/lib/blazer/adapters/mongodb_adapter.rb +4 -0
- data/lib/blazer/adapters/neo4j_adapter.rb +17 -2
- data/lib/blazer/adapters/opensearch_adapter.rb +4 -0
- data/lib/blazer/adapters/presto_adapter.rb +9 -0
- data/lib/blazer/adapters/salesforce_adapter.rb +5 -0
- data/lib/blazer/adapters/snowflake_adapter.rb +9 -0
- data/lib/blazer/adapters/soda_adapter.rb +9 -0
- data/lib/blazer/adapters/spark_adapter.rb +5 -0
- data/lib/blazer/adapters/sql_adapter.rb +37 -3
- data/lib/blazer/data_source.rb +85 -5
- data/lib/blazer/engine.rb +0 -4
- data/lib/blazer/result.rb +2 -0
- data/lib/blazer/run_statement.rb +7 -3
- data/lib/blazer/run_statement_job.rb +4 -2
- data/lib/blazer/slack_notifier.rb +5 -2
- data/lib/blazer/statement.rb +75 -0
- data/lib/blazer/version.rb +1 -1
- data/lib/blazer.rb +14 -6
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b32d2190afc8df872db60250651c97eae9d202d0b23042a4b853169edbc2d458
|
4
|
+
data.tar.gz: 64cb17476627ce2108e2aaf9619648e4a743774983c29bcb7478a3b4500f4617
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6eb64793a84ba433e6a68caaa5419dbcbb3f80ae842854b486f552459e77b434bc7d43bacf1d97175fea1857c74e66b440f7de55cc1e591133740f47ea84f18
|
7
|
+
data.tar.gz: 0723a52bb56f41d3526d66799f19a6fa82b91cd51aa3a35b5bede9523012bc0cee291db1f6e71eb74657c8e595ac0dc1b3f20febb1687121c35830456b924c2a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
## 2.6.4 (2022-05-24)
|
2
|
+
|
3
|
+
- Fixed error with caching
|
4
|
+
|
5
|
+
## 2.6.3 (2022-05-11)
|
6
|
+
|
7
|
+
- Fixed error with canceling queries
|
8
|
+
|
9
|
+
## 2.6.2 (2022-05-06)
|
10
|
+
|
11
|
+
- Fixed error with Postgres when prepared statements are disabled with Rails < 6.1
|
12
|
+
|
13
|
+
## 2.6.1 (2022-04-21)
|
14
|
+
|
15
|
+
- Added `region` setting to Amazon Athena
|
16
|
+
- Fixed error with MySQL for Rails < 7
|
17
|
+
- Fixed error with binary data
|
18
|
+
|
19
|
+
## 2.6.0 (2022-04-20)
|
20
|
+
|
21
|
+
- Fixed quoting issue with variables
|
22
|
+
- Custom adapters now need to specify how to quote variables in queries
|
23
|
+
- Added experimental support for Propshaft
|
24
|
+
- Fixed error with empty results with InfluxDB
|
25
|
+
|
1
26
|
## 2.5.0 (2022-01-04)
|
2
27
|
|
3
28
|
- Added support for Slack OAuth tokens
|
data/README.md
CHANGED
@@ -61,7 +61,7 @@ For production, specify your database:
|
|
61
61
|
ENV["BLAZER_DATABASE_URL"] = "postgres://user:password@hostname:5432/database"
|
62
62
|
```
|
63
63
|
|
64
|
-
Blazer tries to protect against queries which modify data
|
64
|
+
When possible, Blazer tries to protect against queries which modify data by running each query in a transaction and rolling it back, but a safer approach is to use a read-only user. [See how to create one](#permissions).
|
65
65
|
|
66
66
|
#### Checks (optional)
|
67
67
|
|
@@ -144,16 +144,14 @@ Be sure to render or redirect for unauthorized users.
|
|
144
144
|
|
145
145
|
## Permissions
|
146
146
|
|
147
|
-
Blazer runs each query in a transaction and rolls it back to prevent queries from modifying data. As an additional line of defense, we recommend using a read only user.
|
148
|
-
|
149
147
|
### PostgreSQL
|
150
148
|
|
151
|
-
Create a user with read
|
149
|
+
Create a user with read-only permissions:
|
152
150
|
|
153
151
|
```sql
|
154
152
|
BEGIN;
|
155
|
-
CREATE ROLE blazer LOGIN PASSWORD '
|
156
|
-
GRANT CONNECT ON DATABASE
|
153
|
+
CREATE ROLE blazer LOGIN PASSWORD 'secret';
|
154
|
+
GRANT CONNECT ON DATABASE dbname TO blazer;
|
157
155
|
GRANT USAGE ON SCHEMA public TO blazer;
|
158
156
|
GRANT SELECT ON ALL TABLES IN SCHEMA public TO blazer;
|
159
157
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO blazer;
|
@@ -162,19 +160,20 @@ COMMIT;
|
|
162
160
|
|
163
161
|
### MySQL
|
164
162
|
|
165
|
-
Create a user with read
|
163
|
+
Create a user with read-only permissions:
|
166
164
|
|
167
165
|
```sql
|
168
|
-
|
166
|
+
CREATE USER 'blazer'@'127.0.0.1' IDENTIFIED BY 'secret';
|
167
|
+
GRANT SELECT, SHOW VIEW ON dbname.* TO 'blazer'@'127.0.0.1';
|
169
168
|
FLUSH PRIVILEGES;
|
170
169
|
```
|
171
170
|
|
172
171
|
### MongoDB
|
173
172
|
|
174
|
-
Create a user with read
|
173
|
+
Create a user with read-only permissions:
|
175
174
|
|
176
|
-
```
|
177
|
-
db.createUser({user: "blazer", pwd: "
|
175
|
+
```javascript
|
176
|
+
db.createUser({user: "blazer", pwd: "secret", roles: ["read"]})
|
178
177
|
```
|
179
178
|
|
180
179
|
Also, make sure authorization is enabled when you start the server.
|
@@ -609,6 +608,7 @@ data_sources:
|
|
609
608
|
workgroup: primary
|
610
609
|
access_key_id: ...
|
611
610
|
secret_access_key: ...
|
611
|
+
region: ...
|
612
612
|
```
|
613
613
|
|
614
614
|
Here’s an example IAM policy:
|
@@ -656,6 +656,8 @@ data_sources:
|
|
656
656
|
url: redshift://user:password@hostname:5439/database
|
657
657
|
```
|
658
658
|
|
659
|
+
Use a [read-only user](https://docs.aws.amazon.com/redshift/latest/dg/r_GRANT.html).
|
660
|
+
|
659
661
|
### Apache Drill
|
660
662
|
|
661
663
|
Add [drill-sergeant](https://github.com/ankane/drill-sergeant) to your Gemfile and set:
|
@@ -667,6 +669,8 @@ data_sources:
|
|
667
669
|
url: http://hostname:8047
|
668
670
|
```
|
669
671
|
|
672
|
+
Use a [read-only user](https://drill.apache.org/docs/roles-and-privileges/).
|
673
|
+
|
670
674
|
### Apache Hive
|
671
675
|
|
672
676
|
Add [hexspace](https://github.com/ankane/hexspace) to your Gemfile and set:
|
@@ -690,6 +694,8 @@ data_sources:
|
|
690
694
|
url: ignite://user:password@hostname:10800
|
691
695
|
```
|
692
696
|
|
697
|
+
Use a [read-only user](https://www.gridgain.com/docs/latest/administrators-guide/security/authorization-permissions) (requires a third-party plugin).
|
698
|
+
|
693
699
|
### Apache Spark
|
694
700
|
|
695
701
|
Add [hexspace](https://github.com/ankane/hexspace) to your Gemfile and set:
|
@@ -705,7 +711,7 @@ Use a read-only user. Requires the [Thrift server](https://spark.apache.org/docs
|
|
705
711
|
|
706
712
|
### Cassandra
|
707
713
|
|
708
|
-
Add [cassandra-driver](https://github.com/datastax/ruby-driver) to your Gemfile and set:
|
714
|
+
Add [cassandra-driver](https://github.com/datastax/ruby-driver) (and [sorted_set](https://github.com/knu/sorted_set) for Ruby 3+) to your Gemfile and set:
|
709
715
|
|
710
716
|
```yml
|
711
717
|
data_sources:
|
@@ -713,6 +719,8 @@ data_sources:
|
|
713
719
|
url: cassandra://user:password@hostname:9042/keyspace
|
714
720
|
```
|
715
721
|
|
722
|
+
Use a [read-only role](https://docs.datastax.com/en/cql-oss/3.3/cql/cql_using/useSecurePermission.html).
|
723
|
+
|
716
724
|
### Druid
|
717
725
|
|
718
726
|
Enable [SQL support](http://druid.io/docs/latest/querying/sql.html#configuration) on the broker and set:
|
@@ -724,6 +732,8 @@ data_sources:
|
|
724
732
|
url: http://hostname:8082
|
725
733
|
```
|
726
734
|
|
735
|
+
Use a [read-only role](https://druid.apache.org/docs/latest/development/extensions-core/druid-basic-security.html).
|
736
|
+
|
727
737
|
### Elasticsearch
|
728
738
|
|
729
739
|
Add [elasticsearch](https://github.com/elastic/elasticsearch-ruby) to your Gemfile and set:
|
@@ -735,6 +745,8 @@ data_sources:
|
|
735
745
|
url: http://user:password@hostname:9200
|
736
746
|
```
|
737
747
|
|
748
|
+
Use a [read-only role](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-privileges.html).
|
749
|
+
|
738
750
|
### Google BigQuery
|
739
751
|
|
740
752
|
Add [google-cloud-bigquery](https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/master/google-cloud-bigquery) to your Gemfile and set:
|
@@ -757,6 +769,8 @@ data_sources:
|
|
757
769
|
url: ibm-db://user:password@hostname:50000/database
|
758
770
|
```
|
759
771
|
|
772
|
+
Use a [read-only user](https://www.ibm.com/support/pages/creating-read-only-database-permissions-user).
|
773
|
+
|
760
774
|
### InfluxDB
|
761
775
|
|
762
776
|
Add [influxdb](https://github.com/influxdata/influxdb-ruby) to your Gemfile and set:
|
@@ -768,7 +782,7 @@ data_sources:
|
|
768
782
|
url: http://user:password@hostname:8086/database
|
769
783
|
```
|
770
784
|
|
771
|
-
Supports [InfluxQL](https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/)
|
785
|
+
Use a [read-only user](https://docs.influxdata.com/influxdb/v1.8/administration/authentication_and_authorization/). Supports [InfluxQL](https://docs.influxdata.com/influxdb/v1.8/query_language/explore-data/).
|
772
786
|
|
773
787
|
### MongoDB
|
774
788
|
|
@@ -782,6 +796,8 @@ data_sources:
|
|
782
796
|
url: mongodb://user:password@hostname:27017/database
|
783
797
|
```
|
784
798
|
|
799
|
+
Use a [read-only user](#mongodb).
|
800
|
+
|
785
801
|
### MySQL
|
786
802
|
|
787
803
|
Add [mysql2](https://github.com/brianmario/mysql2) to your Gemfile (if it’s not there) and set:
|
@@ -792,6 +808,8 @@ data_sources:
|
|
792
808
|
url: mysql2://user:password@hostname:3306/database
|
793
809
|
```
|
794
810
|
|
811
|
+
Use a [read-only user](#mysql).
|
812
|
+
|
795
813
|
### Neo4j
|
796
814
|
|
797
815
|
Add [neo4j-core](https://github.com/neo4jrb/neo4j-core) to your Gemfile and set:
|
@@ -803,6 +821,8 @@ data_sources:
|
|
803
821
|
url: http://user:password@hostname:7474
|
804
822
|
```
|
805
823
|
|
824
|
+
Use a [read-only user](https://neo4j.com/docs/cypher-manual/current/access-control/manage-privileges/).
|
825
|
+
|
806
826
|
### OpenSearch
|
807
827
|
|
808
828
|
Add [opensearch-ruby](https://github.com/opensearch-project/opensearch-ruby) to your Gemfile and set:
|
@@ -814,6 +834,8 @@ data_sources:
|
|
814
834
|
url: http://user:password@hostname:9200
|
815
835
|
```
|
816
836
|
|
837
|
+
Use a [read-only user](https://opensearch.org/docs/latest/security-plugin/access-control/permissions/).
|
838
|
+
|
817
839
|
### Oracle
|
818
840
|
|
819
841
|
Add [activerecord-oracle_enhanced-adapter](https://github.com/rsim/oracle-enhanced) and [ruby-oci8](https://github.com/kubo/ruby-oci8) to your Gemfile and set:
|
@@ -824,6 +846,8 @@ data_sources:
|
|
824
846
|
url: oracle-enhanced://user:password@hostname:1521/database
|
825
847
|
```
|
826
848
|
|
849
|
+
Use a [read-only user](https://docs.oracle.com/cd/B19306_01/network.102/b14266/authoriz.htm).
|
850
|
+
|
827
851
|
### PostgreSQL
|
828
852
|
|
829
853
|
Add [pg](https://github.com/ged/ruby-pg) to your Gemfile (if it’s not there) and set:
|
@@ -834,6 +858,8 @@ data_sources:
|
|
834
858
|
url: postgres://user:password@hostname:5432/database
|
835
859
|
```
|
836
860
|
|
861
|
+
Use a [read-only user](#postgresql).
|
862
|
+
|
837
863
|
### Presto
|
838
864
|
|
839
865
|
Add [presto-client](https://github.com/treasure-data/presto-client-ruby) to your Gemfile and set:
|
@@ -844,6 +870,8 @@ data_sources:
|
|
844
870
|
url: presto://user@hostname:8080/catalog
|
845
871
|
```
|
846
872
|
|
873
|
+
Use a [read-only user](https://prestodb.io/docs/current/security/built-in-system-access-control.html).
|
874
|
+
|
847
875
|
### Salesforce
|
848
876
|
|
849
877
|
Add [restforce](https://github.com/restforce/restforce) to your Gemfile and set:
|
@@ -865,7 +893,7 @@ SALESFORCE_CLIENT_SECRET="client secret"
|
|
865
893
|
SALESFORCE_API_VERSION="41.0"
|
866
894
|
```
|
867
895
|
|
868
|
-
Supports [SOQL](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm)
|
896
|
+
Use a read-only user. Supports [SOQL](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm).
|
869
897
|
|
870
898
|
### Socrata Open Data API (SODA)
|
871
899
|
|
@@ -879,7 +907,7 @@ data_sources:
|
|
879
907
|
app_token: ...
|
880
908
|
```
|
881
909
|
|
882
|
-
Supports [SoQL](https://dev.socrata.com/docs/functions/)
|
910
|
+
Supports [SoQL](https://dev.socrata.com/docs/functions/).
|
883
911
|
|
884
912
|
### Snowflake
|
885
913
|
|
@@ -913,6 +941,8 @@ data_sources:
|
|
913
941
|
conn_str: Driver=/path/to/libSnowflake.so;uid=user;pwd=password;server=host.snowflakecomputing.com
|
914
942
|
```
|
915
943
|
|
944
|
+
Use a [read-only role](https://docs.snowflake.com/en/user-guide/security-access-control-configure.html).
|
945
|
+
|
916
946
|
### SQLite
|
917
947
|
|
918
948
|
Add [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) to your Gemfile and set:
|
@@ -933,6 +963,8 @@ data_sources:
|
|
933
963
|
url: sqlserver://user:password@hostname:1433/database
|
934
964
|
```
|
935
965
|
|
966
|
+
Use a [read-only user](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/getting-started-with-database-engine-permissions?view=sql-server-ver15).
|
967
|
+
|
936
968
|
## Creating an Adapter
|
937
969
|
|
938
970
|
Create an adapter for any data store with:
|
@@ -1009,6 +1041,22 @@ override_csp: true
|
|
1009
1041
|
|
1010
1042
|
## Upgrading
|
1011
1043
|
|
1044
|
+
### 2.6
|
1045
|
+
|
1046
|
+
Custom adapters now need to specify how to quote variables in queries (there is no longer a default)
|
1047
|
+
|
1048
|
+
```ruby
|
1049
|
+
class FooAdapter < Blazer::Adapters::BaseAdapter
|
1050
|
+
def quoting
|
1051
|
+
:backslash_escape # single quote strings and convert ' to \' and \ to \\
|
1052
|
+
# or
|
1053
|
+
:single_quote_escape # single quote strings and convert ' to ''
|
1054
|
+
# or
|
1055
|
+
->(value) { ... } # custom method
|
1056
|
+
end
|
1057
|
+
end
|
1058
|
+
```
|
1059
|
+
|
1012
1060
|
### 2.3
|
1013
1061
|
|
1014
1062
|
To archive queries, create a migration
|
@@ -3,6 +3,9 @@ var runningQueries = []
|
|
3
3
|
var maxQueries = 3
|
4
4
|
|
5
5
|
function runQuery(data, success, error) {
|
6
|
+
if (!data.data_source) {
|
7
|
+
throw new Error("Data source is required to cancel queries")
|
8
|
+
}
|
6
9
|
data.run_id = uuid()
|
7
10
|
var query = {
|
8
11
|
data: data,
|
@@ -50,7 +53,11 @@ function runQueryHelper(query) {
|
|
50
53
|
queryComplete(query)
|
51
54
|
}
|
52
55
|
}).fail( function(jqXHR, textStatus, errorThrown) {
|
53
|
-
|
56
|
+
// check jqXHR.status instead of query.canceled
|
57
|
+
// so it works for page navigation with Firefox and Safari
|
58
|
+
if (jqXHR.status === 0) {
|
59
|
+
cancelServerQuery(query)
|
60
|
+
} else {
|
54
61
|
var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message
|
55
62
|
if (!message) {
|
56
63
|
message = "An error occurred"
|
@@ -83,6 +90,8 @@ function cancelAllQueries() {
|
|
83
90
|
}
|
84
91
|
}
|
85
92
|
|
93
|
+
// needed for Chrome
|
94
|
+
// queries are canceled before unload with Firefox and Safari
|
86
95
|
$(window).on("unload", cancelAllQueries)
|
87
96
|
|
88
97
|
function cancelQuery(query) {
|
@@ -90,7 +99,9 @@ function cancelQuery(query) {
|
|
90
99
|
if (query.xhr) {
|
91
100
|
query.xhr.abort()
|
92
101
|
}
|
102
|
+
}
|
93
103
|
|
104
|
+
function cancelServerQuery(query) {
|
94
105
|
// tell server
|
95
106
|
var path = Routes.cancel_queries_path()
|
96
107
|
var data = {run_id: query.run_id, data_source: query.data_source}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
/*!
|
2
|
+
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
3
|
+
* Copyright 2011-2019 Twitter, Inc.
|
4
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
5
|
+
*/
|
6
|
+
@font-face {
|
7
|
+
font-family: "Glyphicons Halflings";
|
8
|
+
src: url('/blazer/glyphicons-halflings-regular.eot');
|
9
|
+
src: url('/blazer/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('/blazer/glyphicons-halflings-regular.woff2') format('woff2'), url('/blazer/glyphicons-halflings-regular.woff') format('woff'), url('/blazer/glyphicons-halflings-regular.ttf') format('truetype'), url('/blazer/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
|
10
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
/*!
|
2
|
+
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
3
|
+
* Copyright 2011-2019 Twitter, Inc.
|
4
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
5
|
+
*/
|
6
|
+
@font-face {
|
7
|
+
font-family: "Glyphicons Halflings";
|
8
|
+
src: url('<%= font_path("blazer/glyphicons-halflings-regular.eot") %>');
|
9
|
+
src: url('<%= font_path("blazer/glyphicons-halflings-regular.eot?#iefix") %>') format('embedded-opentype'), url('<%= font_path("blazer/glyphicons-halflings-regular.woff2") %>') format('woff2'), url('<%= font_path("blazer/glyphicons-halflings-regular.woff") %>') format('woff'), url('<%= font_path("blazer/glyphicons-halflings-regular.ttf") %>') format('truetype'), url('<%= font_path("blazer/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") %>') format('svg');
|
10
|
+
}
|
@@ -263,11 +263,6 @@ th {
|
|
263
263
|
border: 1px solid #ddd !important;
|
264
264
|
}
|
265
265
|
}
|
266
|
-
@font-face {
|
267
|
-
font-family: "Glyphicons Halflings";
|
268
|
-
src: url('<%= font_path("blazer/glyphicons-halflings-regular.eot") %>');
|
269
|
-
src: url('<%= font_path("blazer/glyphicons-halflings-regular.eot?#iefix") %>') format('embedded-opentype'), url('<%= font_path("blazer/glyphicons-halflings-regular.woff2") %>') format('woff2'), url('<%= font_path("blazer/glyphicons-halflings-regular.woff") %>') format('woff'), url('<%= font_path("blazer/glyphicons-halflings-regular.ttf") %>') format('truetype'), url('<%= font_path("blazer/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") %>') format('svg');
|
270
|
-
}
|
271
266
|
.glyphicon {
|
272
267
|
position: relative;
|
273
268
|
top: 1px;
|
@@ -6831,4 +6826,3 @@ button.close {
|
|
6831
6826
|
display: none !important;
|
6832
6827
|
}
|
6833
6828
|
}
|
6834
|
-
/*# sourceMappingURL=bootstrap.css.map */
|
@@ -32,45 +32,34 @@ module Blazer
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
-
def process_vars(statement,
|
36
|
-
|
35
|
+
def process_vars(statement, var_params = nil)
|
36
|
+
var_params ||= request.query_parameters
|
37
|
+
(@bind_vars ||= []).concat(statement.variables).uniq!
|
38
|
+
# update in-place so populated in view and consistent across queries on dashboard
|
37
39
|
@bind_vars.each do |var|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
if @success
|
43
|
-
@bind_vars.each do |var|
|
44
|
-
value = params[var].presence
|
45
|
-
if value
|
46
|
-
if ["start_time", "end_time"].include?(var)
|
47
|
-
value = value.to_s.gsub(" ", "+") # fix for Quip bug
|
48
|
-
end
|
49
|
-
|
50
|
-
if var.end_with?("_at")
|
51
|
-
begin
|
52
|
-
value = Blazer.time_zone.parse(value)
|
53
|
-
rescue
|
54
|
-
# do nothing
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
if value =~ /\A\d+\z/
|
59
|
-
value = value.to_i
|
60
|
-
elsif value =~ /\A\d+\.\d+\z/
|
61
|
-
value = value.to_f
|
62
|
-
end
|
63
|
-
end
|
64
|
-
value = Blazer.transform_variable.call(var, value) if Blazer.transform_variable
|
65
|
-
statement.gsub!("{#{var}}", ActiveRecord::Base.connection.quote(value))
|
40
|
+
if !var_params[var]
|
41
|
+
default = statement.data_source.variable_defaults[var]
|
42
|
+
# only add if default exists
|
43
|
+
var_params[var] = default if default
|
66
44
|
end
|
67
45
|
end
|
46
|
+
runnable = @bind_vars.all? { |v| var_params[v] }
|
47
|
+
statement.add_values(var_params) if runnable
|
48
|
+
runnable
|
49
|
+
end
|
50
|
+
|
51
|
+
def refresh_query(query)
|
52
|
+
statement = query.statement_object
|
53
|
+
runnable = process_vars(statement)
|
54
|
+
cohort_analysis_statement(statement) if statement.cohort_analysis?
|
55
|
+
statement.clear_cache if runnable
|
68
56
|
end
|
69
57
|
|
70
58
|
def add_cohort_analysis_vars
|
71
59
|
@bind_vars << "cohort_period" unless @bind_vars.include?("cohort_period")
|
72
|
-
@smart_vars["cohort_period"] = ["day", "week", "month"]
|
73
|
-
|
60
|
+
@smart_vars["cohort_period"] = ["day", "week", "month"] if @smart_vars
|
61
|
+
# TODO create var_params method
|
62
|
+
request.query_parameters["cohort_period"] ||= "week"
|
74
63
|
end
|
75
64
|
|
76
65
|
def parse_smart_variables(var, data_source)
|
@@ -94,22 +83,33 @@ module Blazer
|
|
94
83
|
[smart_var, error]
|
95
84
|
end
|
96
85
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
86
|
+
def cohort_analysis_statement(statement)
|
87
|
+
@cohort_period = params["cohort_period"] || "week"
|
88
|
+
@cohort_period = "week" unless ["day", "week", "month"].include?(@cohort_period)
|
89
|
+
|
90
|
+
# for now
|
91
|
+
@conversion_period = @cohort_period
|
92
|
+
@cohort_days =
|
93
|
+
case @cohort_period
|
94
|
+
when "day"
|
95
|
+
1
|
96
|
+
when "week"
|
97
|
+
7
|
98
|
+
when "month"
|
99
|
+
30
|
100
|
+
end
|
101
|
+
|
102
|
+
statement.apply_cohort_analysis(period: @cohort_period, days: @cohort_days)
|
103
|
+
end
|
104
|
+
|
105
|
+
# TODO allow all keys
|
106
|
+
# or show error message for disallowed keys
|
107
107
|
UNPERMITTED_KEYS = [:controller, :action, :id, :host, :query, :dashboard, :query_id, :query_ids, :table_names, :authenticity_token, :utf8, :_method, :commit, :statement, :data_source, :name, :fork_query_id, :blazer, :run_id, :script_name, :original_script_name]
|
108
108
|
|
109
|
-
|
110
|
-
def variable_params(resource)
|
109
|
+
def variable_params(resource, var_params = nil)
|
111
110
|
permitted_keys = resource.variables - UNPERMITTED_KEYS.map(&:to_s)
|
112
|
-
|
111
|
+
var_params ||= request.query_parameters
|
112
|
+
var_params.slice(*permitted_keys)
|
113
113
|
end
|
114
114
|
helper_method :variable_params
|
115
115
|
|
@@ -21,11 +21,8 @@ module Blazer
|
|
21
21
|
|
22
22
|
def show
|
23
23
|
@queries = @dashboard.dashboard_queries.order(:position).preload(:query).map(&:query)
|
24
|
-
@statements = []
|
25
24
|
@queries.each do |query|
|
26
|
-
|
27
|
-
process_vars(statement, query.data_source)
|
28
|
-
@statements << statement
|
25
|
+
@success = process_vars(query.statement_object)
|
29
26
|
end
|
30
27
|
@bind_vars ||= []
|
31
28
|
|
@@ -48,7 +45,7 @@ module Blazer
|
|
48
45
|
|
49
46
|
def update
|
50
47
|
if update_dashboard(@dashboard)
|
51
|
-
redirect_to dashboard_path(@dashboard, variable_params(@dashboard))
|
48
|
+
redirect_to dashboard_path(@dashboard, params: variable_params(@dashboard))
|
52
49
|
else
|
53
50
|
render_errors @dashboard
|
54
51
|
end
|
@@ -61,13 +58,9 @@ module Blazer
|
|
61
58
|
|
62
59
|
def refresh
|
63
60
|
@dashboard.queries.each do |query|
|
64
|
-
|
65
|
-
statement = query.statement.dup
|
66
|
-
process_vars(statement, query.data_source)
|
67
|
-
Blazer.transform_statement.call(data_source, statement) if Blazer.transform_statement
|
68
|
-
data_source.clear_cache(statement)
|
61
|
+
refresh_query(query)
|
69
62
|
end
|
70
|
-
redirect_to dashboard_path(@dashboard, variable_params(@dashboard))
|
63
|
+
redirect_to dashboard_path(@dashboard, params: variable_params(@dashboard))
|
71
64
|
end
|
72
65
|
|
73
66
|
private
|