bullet_train-api 1.2.9 → 1.2.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b3fdf5c4b02d770a18da4612bc302ad25ebc2dbe91fb71457e75e2a9d47702b
4
- data.tar.gz: d2e9a87102c8e1fcae0d2c9938a6e5b05e77cc4906c19234c31128f4be556586
3
+ metadata.gz: a4f8d6d77dec24dd8d2766815d042af01738dca790794a8b25566e7cd856460d
4
+ data.tar.gz: 9824629fabe7e7c6cbc6ad32aa33c1f15a2d6c96f41549c0222565cdfba4c708
5
5
  SHA512:
6
- metadata.gz: 57265a7f4ff132ccc4651b9e753a1844b39712777a7f3212dc124747489a6873bcdc1f440449ab0dc4601f888c3306cc0d78032feff19fff9066f312cb5c06b6
7
- data.tar.gz: 213ed7b2de13d9305efaa4bb7b4d224c514133425b07d06d4f91f751d36a6bf64022bde0bff1da424ee3fe90161751d050b727069f928a4306311f6892f6b639
6
+ metadata.gz: 4a2d7f5e1718ab4fc68507c0c63a0ebe19cb3f7ef1c235e05ba96b41c93902f309300778431b4c0b6e66b4b24b9bdbced1761507471ac488ad4dbcd4c9208b82
7
+ data.tar.gz: b1e2fe3aac4d7e8bfe715b02c1741681fbac2d93a8cb6255bc69b5f8529d5a2ec694690ad2908a83a6788985b3be412de560a1dc0ccc50a1b30ef0dad9b16be8
@@ -25,6 +25,10 @@ module OpenApiHelper
25
25
  result
26
26
  end
27
27
 
28
+ def gem_paths
29
+ @gem_paths ||= `bundle show --paths`.lines.map { |gem_path| gem_path.chomp }
30
+ end
31
+
28
32
  def automatic_paths_for(model, parent, except: [])
29
33
  output = render("api/#{@version}/open_api/shared/paths", except: except)
30
34
  output = Scaffolding::Transformer.new(model.name, [parent&.name]).transform_string(output).html_safe
@@ -33,7 +37,7 @@ module OpenApiHelper
33
37
 
34
38
  def automatic_components_for(model, locals: {})
35
39
  path = "app/views/api/#{@version}"
36
- paths = ([path] + `bundle show --paths`.lines.map { |gem_path| "#{gem_path.chomp}/#{path}" })
40
+ paths = ([path] + gem_paths.map { |gem_path| "#{gem_path}/#{path}" })
37
41
  jbuilder = Jbuilder::Schema.renderer(paths, locals: {
38
42
  # If we ever get to the point where we need a real model here, we should implement an example team in seeds that we can source it from.
39
43
  model.name.underscore.split("/").last.to_sym => model.new,
@@ -50,20 +54,41 @@ module OpenApiHelper
50
54
 
51
55
  attributes_output = JSON.parse(schema_json)
52
56
 
53
- strong_params_module = "Api::#{@version.upcase}::#{model.name.pluralize}Controller::StrongParameters".constantize
54
- strong_parameter_keys = BulletTrain::Api::StrongParametersReporter.new(model, strong_params_module).report
55
- if strong_parameter_keys.last.is_a?(Hash)
56
- strong_parameter_keys += strong_parameter_keys.pop.keys
57
- end
57
+ # Rails attachments aren't technically attributes in a model,
58
+ # so we add the attributes manually to make them available in the API.
59
+ if model.attachment_reflections.any?
60
+ model.attachment_reflections.each do |reflection|
61
+ attribute_name = reflection.first
58
62
 
59
- parameters_output = JSON.parse(schema_json)
60
- parameters_output["required"].select! { |key| strong_parameter_keys.include?(key.to_sym) }
61
- parameters_output["properties"].select! { |key, value| strong_parameter_keys.include?(key.to_sym) }
63
+ attributes_output["properties"][attribute_name] = {
64
+ "type" => "object",
65
+ "description" => attribute_name.titleize.to_s
66
+ }
67
+
68
+ attributes_output["example"].merge!({attribute_name.to_s => nil})
69
+ end
70
+ end
62
71
 
63
- (
64
- indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3) +
65
- indent(" " + parameters_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Parameters:"), 3)
66
- ).html_safe
72
+ if has_strong_parameters?("Api::#{@version.upcase}::#{model.name.pluralize}Controller".constantize)
73
+ strong_params_module = "Api::#{@version.upcase}::#{model.name.pluralize}Controller::StrongParameters".constantize
74
+ strong_parameter_keys = BulletTrain::Api::StrongParametersReporter.new(model, strong_params_module).report
75
+ if strong_parameter_keys.last.is_a?(Hash)
76
+ strong_parameter_keys += strong_parameter_keys.pop.keys
77
+ end
78
+
79
+ parameters_output = JSON.parse(schema_json)
80
+ parameters_output["required"].select! { |key| strong_parameter_keys.include?(key.to_sym) }
81
+ parameters_output["properties"].select! { |key, value| strong_parameter_keys.include?(key.to_sym) }
82
+
83
+ (
84
+ indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3) +
85
+ indent(" " + parameters_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Parameters:"), 3)
86
+ ).html_safe
87
+ else
88
+
89
+ indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3)
90
+ .html_safe
91
+ end
67
92
  end
68
93
 
69
94
  def paths_for(model)
@@ -76,7 +101,6 @@ module OpenApiHelper
76
101
  heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
77
102
  attribute_data = current_model.columns_hash[attribute.to_s]
78
103
 
79
- # TODO: File fields don't show up in the columns_hash. How should we handle these?
80
104
  # Default to `string` when the type returns nil.
81
105
  type = attribute_data.nil? ? "string" : attribute_data.type
82
106
 
@@ -88,6 +112,13 @@ module OpenApiHelper
88
112
  indent(attribute_block.chomp, 2)
89
113
  end
90
114
  alias_method :parameter, :attribute
115
+
116
+ private
117
+
118
+ def has_strong_parameters?(controller)
119
+ methods = controller.action_methods
120
+ methods.include?("create") || methods.include?("update")
121
+ end
91
122
  end
92
123
 
93
124
  class Api::OpenApiController < ApplicationController
@@ -4,6 +4,10 @@ require "pagy_cursor/pagy/extras/uuid_cursor"
4
4
  module Api::Controllers::Base
5
5
  extend ActiveSupport::Concern
6
6
 
7
+ # We need this to show custom error that user is not authenticated
8
+ # neither with Doorkeeper nor with Devise
9
+ class NotAuthenticatedError < StandardError; end
10
+
7
11
  included do
8
12
  include ActionController::Helpers
9
13
  helper ApplicationHelper
@@ -42,6 +46,10 @@ module Api::Controllers::Base
42
46
  render json: {error: "Not found"}, status: :not_found
43
47
  end
44
48
 
49
+ rescue_from NotAuthenticatedError do |exception|
50
+ render json: {error: "Invalid token or no user signed in"}, status: :unauthorized
51
+ end
52
+
45
53
  before_action :apply_pagination, only: [:index]
46
54
  end
47
55
 
@@ -57,14 +65,24 @@ module Api::Controllers::Base
57
65
  end
58
66
 
59
67
  def current_user
60
- raise Doorkeeper::Errors::InvalidToken unless doorkeeper_token.present?
68
+ @current_user ||= if doorkeeper_token
69
+ User.find_by(id: doorkeeper_token[:resource_owner_id])
70
+ else
71
+ warden.authenticate(scope: :user)
72
+ end
73
+
61
74
  # TODO Remove this rescue once workspace clusters can write to this column on the identity server.
62
75
  # TODO Make this logic configurable so that downstream developers can write different methods for this column getting updated.
63
- begin
64
- doorkeeper_token.update(last_used_at: Time.zone.now)
65
- rescue ActiveRecord::StatementInvalid => _
76
+ if doorkeeper_token
77
+ begin
78
+ doorkeeper_token.update(last_used_at: Time.zone.now)
79
+ rescue ActiveRecord::StatementInvalid => _
80
+ end
66
81
  end
67
- @current_user ||= User.find_by(id: doorkeeper_token[:resource_owner_id])
82
+
83
+ raise NotAuthenticatedError unless @current_user
84
+
85
+ @current_user
68
86
  end
69
87
 
70
88
  def current_team
@@ -4,16 +4,28 @@ module Api::V1::Users::ControllerBase
4
4
  module StrongParameters
5
5
  # Only allow a list of trusted parameters through.
6
6
  def user_params
7
- strong_params = params.require(:user).permit(
8
- *permitted_fields,
7
+ password_fields = [
8
+ :password,
9
+ :current_password,
10
+ :password_confirmation
11
+ ]
12
+ general_fields = [
9
13
  :email,
10
14
  :first_name,
11
15
  :last_name,
12
16
  :time_zone,
13
- :locale,
14
- :current_password,
15
- :password,
16
- :password_confirmation,
17
+ :locale
18
+ ]
19
+
20
+ selected_fields = if params.is_a?(BulletTrain::Api::StrongParametersReporter)
21
+ password_fields + general_fields
22
+ else
23
+ (params["commit"] == t(".buttons.update_password")) ? password_fields : general_fields
24
+ end
25
+
26
+ strong_params = params.require(:user).permit(
27
+ *permitted_fields,
28
+ *selected_fields,
17
29
  # 🚅 super scaffolding will insert new fields above this line.
18
30
  *permitted_arrays,
19
31
  # 🚅 super scaffolding will insert new arrays above this line.
@@ -50,4 +62,10 @@ module Api::V1::Users::ControllerBase
50
62
  # GET /api/v1/users/:id
51
63
  def show
52
64
  end
65
+
66
+ # PUT /api/v1/users/:id
67
+ # TODO: Implement this!
68
+ def update
69
+ raise "Not implemented"
70
+ end
53
71
  end
@@ -36,14 +36,7 @@
36
36
  <%= render "shared/tables/checkbox", object: access_token %>
37
37
  <td><%= render 'shared/attributes/code', attribute: :token, secret: true %></td>
38
38
  <td><%= render 'shared/attributes/text', attribute: :description %></td>
39
- <td>
40
- <% if access_token.last_used_at %>
41
- <%= render 'shared/attributes/date_and_time', attribute: :last_used_at %>
42
- <% else %>
43
- <% # TODO Make it so we can just define a `default` key for `last_used_at` in the locale file and it will us that when present. %>
44
- Never
45
- <% end %>
46
- </td>
39
+ <td><%= render 'shared/attributes/date_and_time', attribute: :last_used_at %></td>
47
40
  <%# 🚅 super scaffolding will insert new fields above this line. %>
48
41
  <td><%= render 'shared/attributes/date_and_time', attribute: :created_at %></td>
49
42
  <td class="buttons">
@@ -3,22 +3,22 @@
3
3
  <% p.content_for :body do %>
4
4
  <ul class="space-y" data-turbo="false">
5
5
  <% @teams.each do |team| %>
6
- <li class="bg-white border overflow-hidden sm:rounded-md dark:bg-sealBlue-400">
6
+ <li class="bg-white border overflow-hidden sm:rounded-md dark:bg-slate-400">
7
7
  <% body = capture do %>
8
8
  <div class="px-4 py-4 flex items-center sm:pl-8 sm:pr-6">
9
9
  <div class="min-w-0 flex-1 sm:flex sm:items-center sm:justify-between">
10
- <div class="flex text-xl font-semibold text-blue uppercase group-hover:text-blue-dark tracking-widest dark:text-white">
10
+ <div class="flex text-xl font-semibold text-blue uppercase group-hover:text-blue-800 tracking-widest dark:text-white">
11
11
  <%= team.name %>
12
12
  </div>
13
13
  <% unless can? :connect, team %>
14
- <div class="ml-5 flex-shrink-0 text-gray-400">
14
+ <div class="ml-5 flex-shrink-0 text-slate-400">
15
15
  <%= t(".not_allowed") %>
16
16
  </div>
17
17
  <% end %>
18
18
  </div>
19
19
  <% if can? :connect, team %>
20
20
  <div class="ml-5 flex-shrink-0">
21
- <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
21
+ <svg class="h-5 w-5 text-slate-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
22
22
  <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
23
23
  </svg>
24
24
  </div>
@@ -27,11 +27,11 @@
27
27
  <% end %>
28
28
 
29
29
  <% if can? :connect, team %>
30
- <%= link_to request.url + "&team_id=#{team.id}", class: "group block hover:bg-gray-50 dark:hover:bg-sealBlue-400 dark:text-sealBlue-800" do %>
30
+ <%= link_to request.url + "&team_id=#{team.id}", class: "group block hover:bg-slate-50 dark:hover:bg-slate-400 dark:text-slate-800", data: {controller: "connection-workflow", action: "connection-workflow#disableTeamButton"} do %>
31
31
  <%= body %>
32
32
  <% end %>
33
33
  <% else %>
34
- <div class="block dark:text-sealBlue-800">
34
+ <div class="block dark:text-slate-800">
35
35
  <%= body %>
36
36
  </div>
37
37
  <% end %>
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module Api
3
- VERSION = "1.2.9"
3
+ VERSION = "1.2.11"
4
4
  end
5
5
  end
@@ -30,5 +30,15 @@ module BulletTrain
30
30
  def self.all_versions
31
31
  (initial_version_numeric..current_version_numeric).map { |version| "v#{version}".to_sym }
32
32
  end
33
+
34
+ def self.set_configuration(application_class)
35
+ application_class.config.to_prepare do
36
+ Doorkeeper::ApplicationController.layout "devise"
37
+
38
+ if Doorkeeper::TokensController
39
+ require_relative "../tokens_controller"
40
+ end
41
+ end
42
+ end
33
43
  end
34
44
  end
@@ -8,7 +8,8 @@ namespace :bullet_train do
8
8
  # Calculate new version.
9
9
  initializer_content = File.new("config/initializers/api.rb").readline
10
10
  previous_version = initializer_content.scan(/v\d+/).pop
11
- new_version = "v#{previous_version.scan(/\d+/).pop.to_i + 1}"
11
+ new_version_int = previous_version.scan(/\d+/).pop.to_i + 1
12
+ new_version = "v#{new_version_int}"
12
13
 
13
14
  # Update initializer.
14
15
  File.write("config/initializers/api.rb", initializer_content.gsub(previous_version, new_version))
@@ -70,6 +71,21 @@ namespace :bullet_train do
70
71
  end
71
72
  Scaffolding::FileManipulator.write("config/routes.rb", updated_file_contents)
72
73
 
74
+ # Update application locale for each locale that exists.
75
+ I18n.available_locales.each do |lang|
76
+ file = "config/locales/#{lang}/application.#{lang}.yml"
77
+ transformer = Scaffolding::Transformer.new("", "")
78
+
79
+ if File.exist?(file)
80
+ transformer.add_line_to_file(
81
+ file,
82
+ "#{new_version_int}: #{new_version.upcase}",
83
+ Scaffolding::Transformer::RUBY_NEW_API_VERSION_HOOK,
84
+ prepend: true
85
+ )
86
+ end
87
+ end
88
+
73
89
  puts "Finished bumping to #{new_version}"
74
90
  end
75
91
  end
@@ -0,0 +1,21 @@
1
+ # TODO Is there a better way to implement this?
2
+ # This monkey patch is required to ensure the OAuth2 token includes which team was connected to.
3
+ # It gets required by BulletTrain::Api.set_configuration.
4
+
5
+ class Doorkeeper::TokensController
6
+ def create
7
+ headers.merge!(authorize_response.headers)
8
+
9
+ user = if authorize_response.is_a?(Doorkeeper::OAuth::ErrorResponse)
10
+ nil
11
+ else
12
+ User.find(authorize_response.token.resource_owner_id)
13
+ end
14
+
15
+ # Add the selected `team_id` to this response.
16
+ render json: authorize_response.body.merge(user&.teams&.one? ? {"team_id" => user.team_ids.first} : {}),
17
+ status: authorize_response.status
18
+ rescue Doorkeeper::Errors::DoorkeeperError => e
19
+ handle_token_exception(e)
20
+ end
21
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.9
4
+ version: 1.2.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-28 00:00:00.000000000 Z
11
+ date: 2023-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard
@@ -151,17 +151,14 @@ files:
151
151
  - app/views/account/platform/access_tokens/index.html.erb
152
152
  - app/views/account/platform/access_tokens/new.html.erb
153
153
  - app/views/account/platform/access_tokens/show.html.erb
154
- - app/views/account/platform/applications/_application.json.jbuilder
155
154
  - app/views/account/platform/applications/_breadcrumbs.html.erb
156
155
  - app/views/account/platform/applications/_form.html.erb
157
156
  - app/views/account/platform/applications/_index.html.erb
158
157
  - app/views/account/platform/applications/_menu_item.html.erb
159
158
  - app/views/account/platform/applications/edit.html.erb
160
159
  - app/views/account/platform/applications/index.html.erb
161
- - app/views/account/platform/applications/index.json.jbuilder
162
160
  - app/views/account/platform/applications/new.html.erb
163
161
  - app/views/account/platform/applications/show.html.erb
164
- - app/views/account/platform/applications/show.json.jbuilder
165
162
  - app/views/account/platform/connections/new.html.erb
166
163
  - app/views/api/v1/open_api/shared/_paths.yaml.erb
167
164
  - app/views/api/v1/open_api/teams/_paths.yaml.erb
@@ -196,6 +193,7 @@ files:
196
193
  - lib/bullet_train/platform.rb
197
194
  - lib/bullet_train/platform/connection_workflow.rb
198
195
  - lib/tasks/bullet_train/api_tasks.rake
196
+ - lib/tokens_controller.rb
199
197
  homepage: https://github.com/bullet-train-co/bullet_train-api
200
198
  licenses:
201
199
  - MIT
@@ -217,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
215
  - !ruby/object:Gem::Version
218
216
  version: '0'
219
217
  requirements: []
220
- rubygems_version: 3.3.7
218
+ rubygems_version: 3.4.1
221
219
  signing_key:
222
220
  specification_version: 4
223
221
  summary: Bullet Train API
@@ -1,9 +0,0 @@
1
- json.extract! application,
2
- :id,
3
- :team_id,
4
- :name,
5
- :redirect_uri,
6
- # 🚅 super scaffolding will insert new fields above this line.
7
- :created_at,
8
- :updated_at
9
- json.url account_platform_application_url(application, format: :json)
@@ -1 +0,0 @@
1
- json.array! @applications, partial: "platform/applications/application", as: :application
@@ -1 +0,0 @@
1
- json.partial! "platform/applications/application", application: @application