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 +4 -4
- data/app/controllers/api/open_api_controller.rb +45 -14
- data/app/controllers/concerns/api/controllers/base.rb +23 -5
- data/app/controllers/concerns/api/v1/users/controller_base.rb +24 -6
- data/app/views/account/platform/access_tokens/_index.html.erb +1 -8
- data/app/views/account/platform/connections/new.html.erb +6 -6
- data/lib/bullet_train/api/version.rb +1 -1
- data/lib/bullet_train/api.rb +10 -0
- data/lib/tasks/bullet_train/api_tasks.rake +17 -1
- data/lib/tokens_controller.rb +21 -0
- metadata +4 -6
- data/app/views/account/platform/applications/_application.json.jbuilder +0 -9
- data/app/views/account/platform/applications/index.json.jbuilder +0 -1
- data/app/views/account/platform/applications/show.json.jbuilder +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4f8d6d77dec24dd8d2766815d042af01738dca790794a8b25566e7cd856460d
|
4
|
+
data.tar.gz: 9824629fabe7e7c6cbc6ad32aa33c1f15a2d6c96f41549c0222565cdfba4c708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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] +
|
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
|
-
|
54
|
-
|
55
|
-
if
|
56
|
-
|
57
|
-
|
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
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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
|
-
|
8
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
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-
|
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-
|
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-
|
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-
|
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-
|
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-
|
34
|
+
<div class="block dark:text-slate-800">
|
35
35
|
<%= body %>
|
36
36
|
</div>
|
37
37
|
<% end %>
|
data/lib/bullet_train/api.rb
CHANGED
@@ -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
|
-
|
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.
|
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:
|
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.
|
218
|
+
rubygems_version: 3.4.1
|
221
219
|
signing_key:
|
222
220
|
specification_version: 4
|
223
221
|
summary: Bullet Train API
|
@@ -1 +0,0 @@
|
|
1
|
-
json.array! @applications, partial: "platform/applications/application", as: :application
|
@@ -1 +0,0 @@
|
|
1
|
-
json.partial! "platform/applications/application", application: @application
|