bullet_train-api 1.2.9 → 1.2.11

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