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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +63 -15
  4. data/app/assets/javascripts/blazer/queries.js +12 -1
  5. data/app/assets/stylesheets/blazer/application.css +1 -0
  6. data/app/assets/stylesheets/blazer/bootstrap-propshaft.css +10 -0
  7. data/app/assets/stylesheets/blazer/bootstrap-sprockets.css.erb +10 -0
  8. data/app/assets/stylesheets/blazer/{bootstrap.css.erb → bootstrap.css} +0 -6
  9. data/app/controllers/blazer/base_controller.rb +45 -45
  10. data/app/controllers/blazer/dashboards_controller.rb +4 -11
  11. data/app/controllers/blazer/queries_controller.rb +29 -48
  12. data/app/models/blazer/query.rb +8 -2
  13. data/app/views/blazer/_variables.html.erb +5 -4
  14. data/app/views/blazer/dashboards/_form.html.erb +1 -1
  15. data/app/views/blazer/dashboards/show.html.erb +6 -4
  16. data/app/views/blazer/queries/_caching.html.erb +1 -1
  17. data/app/views/blazer/queries/_form.html.erb +3 -3
  18. data/app/views/blazer/queries/run.html.erb +1 -1
  19. data/app/views/blazer/queries/show.html.erb +12 -7
  20. data/app/views/layouts/blazer/application.html.erb +7 -2
  21. data/lib/blazer/adapters/athena_adapter.rb +55 -18
  22. data/lib/blazer/adapters/base_adapter.rb +16 -1
  23. data/lib/blazer/adapters/bigquery_adapter.rb +13 -2
  24. data/lib/blazer/adapters/cassandra_adapter.rb +15 -4
  25. data/lib/blazer/adapters/drill_adapter.rb +10 -0
  26. data/lib/blazer/adapters/druid_adapter.rb +36 -1
  27. data/lib/blazer/adapters/elasticsearch_adapter.rb +13 -2
  28. data/lib/blazer/adapters/hive_adapter.rb +10 -0
  29. data/lib/blazer/adapters/ignite_adapter.rb +12 -2
  30. data/lib/blazer/adapters/influxdb_adapter.rb +22 -10
  31. data/lib/blazer/adapters/mongodb_adapter.rb +4 -0
  32. data/lib/blazer/adapters/neo4j_adapter.rb +17 -2
  33. data/lib/blazer/adapters/opensearch_adapter.rb +4 -0
  34. data/lib/blazer/adapters/presto_adapter.rb +9 -0
  35. data/lib/blazer/adapters/salesforce_adapter.rb +5 -0
  36. data/lib/blazer/adapters/snowflake_adapter.rb +9 -0
  37. data/lib/blazer/adapters/soda_adapter.rb +9 -0
  38. data/lib/blazer/adapters/spark_adapter.rb +5 -0
  39. data/lib/blazer/adapters/sql_adapter.rb +37 -3
  40. data/lib/blazer/data_source.rb +85 -5
  41. data/lib/blazer/engine.rb +0 -4
  42. data/lib/blazer/result.rb +2 -0
  43. data/lib/blazer/run_statement.rb +7 -3
  44. data/lib/blazer/run_statement_job.rb +4 -2
  45. data/lib/blazer/slack_notifier.rb +5 -2
  46. data/lib/blazer/statement.rb +75 -0
  47. data/lib/blazer/version.rb +1 -1
  48. data/lib/blazer.rb +14 -6
  49. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fad6bd2d76ea45a8ec72956177648848a6dede796354a01f27359b4cb7cfeedb
4
- data.tar.gz: a8f81985d77b110c850d421ac86376bbf71cf5f2b318cfea496e8cedb1f1a108
3
+ metadata.gz: b32d2190afc8df872db60250651c97eae9d202d0b23042a4b853169edbc2d458
4
+ data.tar.gz: 64cb17476627ce2108e2aaf9619648e4a743774983c29bcb7478a3b4500f4617
5
5
  SHA512:
6
- metadata.gz: 6fd612ec162dc5b6a23ef1f6b3580da0de7f1cec8788520557e8a25ef0bdf4337df775b0cacb4e292003e1a4565460c411a67951a5ea27048a994fb1178463d7
7
- data.tar.gz: 4a5e760ca38fb96fa54df64469f3fd3223d6b23698da0491c43dc8bc3ef92f7f83b14bea028821ba5708adf209bc147975edaf6d4dc76ecb5916d51905e7f2f0
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 (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).
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 only permissions:
149
+ Create a user with read-only permissions:
152
150
 
153
151
  ```sql
154
152
  BEGIN;
155
- CREATE ROLE blazer LOGIN PASSWORD 'secret123';
156
- GRANT CONNECT ON DATABASE database_name TO blazer;
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 only permissions:
163
+ Create a user with read-only permissions:
166
164
 
167
165
  ```sql
168
- GRANT SELECT, SHOW VIEW ON database_name.* TO blazer@’127.0.0.1 IDENTIFIED BY ‘secret123‘;
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 only permissions:
173
+ Create a user with read-only permissions:
175
174
 
176
- ```
177
- db.createUser({user: "blazer", pwd: "password", roles: ["read"]})
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
- if (!query.canceled) {
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}
@@ -1,4 +1,5 @@
1
1
  /*
2
+ *= require ./bootstrap-sprockets
2
3
  *= require ./bootstrap
3
4
  *= require ./selectize
4
5
  *= require ./github
@@ -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, data_source)
36
- (@bind_vars ||= []).concat(Blazer.extract_vars(statement)).uniq!
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
- params[var] ||= Blazer.data_sources[data_source].variable_defaults[var]
39
- end
40
- @success = @bind_vars.all? { |v| params[v] }
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
- params[:cohort_period] ||= "week"
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
- # don't pass to url helpers
98
- #
99
- # some are dangerous when passed as symbols
100
- # root_url({host: "evilsite.com"})
101
- #
102
- # certain ones (like host) only affect *_url and not *_path
103
- #
104
- # when permitted parameters are passed in Rails 6,
105
- # they appear to be added as GET parameters
106
- # root_url(params.permit(:host))
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
- # remove unpermitted keys from both params and permitted keys for better sleep
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
- params.except(*UNPERMITTED_KEYS).slice(*permitted_keys).permit!
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
- statement = query.statement.dup
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
- data_source = Blazer.data_sources[query.data_source]
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