bullet_train-api 1.1.15 → 1.2.1

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: 14acbfaa73e947b800255ed5e8d31afeaa9d453e7da85ee6f46684bd2f824d8a
4
- data.tar.gz: 698e7d97b1c9bce05d5ed049bc8552002b7a769ed97b3f7e7d0690bf6ef19bce
3
+ metadata.gz: e3cec04f6456085bc115f66416e2f5fcaf249c0685166e8a46a88b79b4bd1978
4
+ data.tar.gz: 0b14b88a2aa523a9ce4d75de6ce79c4f0e81a46d0394085ca16e6b477bf66037
5
5
  SHA512:
6
- metadata.gz: 99eef514f9a218014d19576d8b17e0ecff0a475e672922c227a177203c6041e8db178ebc996a090919ffcb47b5b53d0adaadf70344de811501b7d8e4d49a8d09
7
- data.tar.gz: 016203f358c8cbb80069d6975ab3d44fbad04ac8fe172ca6ff2f888cf744367f948b06ac8596e9fbd0c4098f54cff2ac13053b332d6ce50a37eca75c597c40da
6
+ metadata.gz: ae4e8eaf3d5c89797e736de09866fc071427244120ed45b9fdced3881f433e91660e3372dfda36bda508c5af59a2db8ddb4e55354a7fc7dc3344e3a65b0cd106
7
+ data.tar.gz: 6551bce70c06a57a8b82511db07cbebbebf87f8f385bfb3bd4910166a2d7d5d5c4cbfa7a3c334d9bef1bbaf975eddf75b5a64175a16cae446a85d1cf9460ddd0
@@ -21,6 +21,23 @@ class Account::Platform::ApplicationsController < Account::ApplicationController
21
21
  def edit
22
22
  end
23
23
 
24
+ def provision
25
+ if ENV["TESTING_PROVISION_KEY"].present? && params[:key] == ENV["TESTING_PROVISION_KEY"]
26
+ user = User.create(email: "test@#{SecureRandom.hex}.example.com", password: (password = SecureRandom.hex), password_confirmation: password)
27
+ provision_team = current_user.teams.create(name: "provision-team-#{SecureRandom.hex}", time_zone: user.time_zone)
28
+ test_application = Platform::Application.new(name: "test-application-#{SecureRandom.hex}", team: provision_team)
29
+
30
+ if test_application.save
31
+ access_token = test_application.create_access_token
32
+ render json: {message: I18n.t("platform/applications.notifications.test_application_created"), team_id: provision_team.id, access_token: access_token.token}
33
+ else
34
+ render json: {errors: test_application.errors, status: :unprocessable_entity}
35
+ end
36
+ else
37
+ render json: {message: I18n.t("platform/applications.notifications.test_application_failure")}
38
+ end
39
+ end
40
+
24
41
  # POST /account/teams/:team_id/platform/applications
25
42
  # POST /account/teams/:team_id/platform/applications.json
26
43
  def create
@@ -6,6 +6,7 @@ module OpenApiHelper
6
6
  lines.unshift(first_line).join.html_safe
7
7
  end
8
8
 
9
+ # TODO: Remove this method? It's not being used anywhere
9
10
  def components_for(model)
10
11
  for_model model do
11
12
  indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/components"), 2)
@@ -73,15 +74,20 @@ module OpenApiHelper
73
74
 
74
75
  def attribute(attribute)
75
76
  heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
76
- # TODO A lot of logic to be done here.
77
- indent("#{attribute}:\n description: \"#{heading}\"\n type: string", 2)
78
- end
79
-
80
- def parameter(attribute)
81
- heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
82
- # TODO A lot of logic to be done here.
83
- indent("#{attribute}:\n description: \"#{heading}\"\n type: string", 2)
77
+ attribute_data = current_model.columns_hash[attribute.to_s]
78
+
79
+ # TODO: File fields don't show up in the columns_hash. How should we handle these?
80
+ # Default to `string` when the type returns nil.
81
+ type = attribute_data.nil? ? "string" : attribute_data.type
82
+
83
+ attribute_block = <<~YAML
84
+ #{attribute}:
85
+ description: "#{heading}"
86
+ type: #{type}
87
+ YAML
88
+ indent(attribute_block.chomp, 2)
84
89
  end
90
+ alias_method :parameter, :attribute
85
91
  end
86
92
 
87
93
  class Api::OpenApiController < ApplicationController
@@ -4,10 +4,6 @@ require "pagy_cursor/pagy/extras/uuid_cursor"
4
4
  module Api::Controllers::Base
5
5
  extend ActiveSupport::Concern
6
6
 
7
- # TODO Why doesn't `before_action :doorkeeper_authorize!` throw an exception?
8
- class NotAuthenticatedError < StandardError
9
- end
10
-
11
7
  included do
12
8
  include ActionController::Helpers
13
9
  helper ApplicationHelper
@@ -16,14 +12,13 @@ module Api::Controllers::Base
16
12
  include Pagy::Backend
17
13
 
18
14
  before_action :set_default_response_format
19
- before_action :doorkeeper_authorize!
20
15
  after_action :set_pagination_headers
21
16
 
22
17
  def modify_url_params(url, new_params)
23
18
  uri = URI.parse(url)
24
19
  query = Rack::Utils.parse_query(uri.query)
25
20
  new_params.each do |key, value|
26
- query[key] = value
21
+ query[key.to_s] = value
27
22
  end
28
23
  uri.query = Rack::Utils.build_query(query)
29
24
  uri.to_s
@@ -35,8 +30,9 @@ module Api::Controllers::Base
35
30
  if @pagy.has_more?
36
31
  if (collection = instance_variable_get(collection_variable))
37
32
  next_cursor = collection.last.id
38
- # TODO Probably not great that we're clobbering any `Link` header that might be set.
39
- response.headers["Link"] = "<#{modify_url_params(request.url, after: next_cursor)}>; rel=next"
33
+ link_header = response.headers["Link"]
34
+ link_value = "<#{modify_url_params(request.url, after: next_cursor)}>; rel=\"next\""
35
+ response.headers["Link"] = link_header ? "#{link_header}, #{link_value}" : link_value
40
36
  response.headers["Pagination-Next"] = next_cursor
41
37
  end
42
38
  end
@@ -46,10 +42,6 @@ module Api::Controllers::Base
46
42
  render json: {error: "Not found"}, status: :not_found
47
43
  end
48
44
 
49
- rescue_from NotAuthenticatedError do |exception|
50
- render json: {error: "Invalid token"}, status: :unauthorized
51
- end
52
-
53
45
  before_action :apply_pagination, only: [:index]
54
46
  end
55
47
 
@@ -65,7 +57,7 @@ module Api::Controllers::Base
65
57
  end
66
58
 
67
59
  def current_user
68
- raise NotAuthenticatedError unless doorkeeper_token.present?
60
+ raise Doorkeeper::Errors::InvalidToken unless doorkeeper_token.present?
69
61
  # TODO Remove this rescue once workspace clusters can write to this column on the identity server.
70
62
  # TODO Make this logic configurable so that downstream developers can write different methods for this column getting updated.
71
63
  begin
@@ -95,8 +87,12 @@ module Api::Controllers::Base
95
87
  end
96
88
 
97
89
  class_methods do
90
+ def controller_namespace
91
+ name.split("::").first(2).join("::")
92
+ end
93
+
98
94
  def regex_to_remove_controller_namespace
99
- /^#{name.split("::").first(2).join("::") + "::"}/
95
+ /^#{controller_namespace + "::"}/
100
96
  end
101
97
  end
102
98
  end
@@ -11,6 +11,9 @@ module Api::V1::Users::ControllerBase
11
11
  :last_name,
12
12
  :time_zone,
13
13
  :locale,
14
+ :current_password,
15
+ :password,
16
+ :password_confirmation,
14
17
  # 🚅 super scaffolding will insert new fields above this line.
15
18
  *permitted_arrays,
16
19
  # 🚅 super scaffolding will insert new arrays above this line.
@@ -34,7 +34,7 @@ class Platform::Application < ApplicationRecord
34
34
  def create_user_and_membership
35
35
  faux_password = SecureRandom.hex
36
36
  create_user(email: "noreply+#{SecureRandom.hex}@bullettrain.co", password: faux_password, password_confirmation: faux_password, first_name: label_string)
37
- create_membership(team: team, user: user)
37
+ create_membership(team: team, user: user, platform_agent: true)
38
38
  membership.roles << Role.admin
39
39
  end
40
40
 
@@ -13,22 +13,23 @@
13
13
  required: true
14
14
  schema:
15
15
  type: string
16
+ - $ref: "#/components/parameters/after"
16
17
  responses:
17
18
  "404":
18
19
  description: "Not Found"
19
20
  "200":
20
21
  description: "OK"
22
+ headers:
23
+ Pagination-Next:
24
+ $ref: "#/components/headers/PaginationNext"
25
+ Link:
26
+ $ref: "#/components/headers/Link"
21
27
  content:
22
28
  application/json:
23
29
  schema:
24
- type: object
25
- properties:
26
- data:
27
- type: array
28
- items:
29
- $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
30
- has_more:
31
- type: boolean
30
+ type: array
31
+ items:
32
+ $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
32
33
  <% end %>
33
34
  <% unless except.include?(:create) %>
34
35
  post:
@@ -42,6 +43,17 @@
42
43
  required: true
43
44
  schema:
44
45
  type: string
46
+ requestBody:
47
+ description: "Information about a new Tangible Thing"
48
+ required: true
49
+ content:
50
+ application/json:
51
+ schema:
52
+ type: object
53
+ properties:
54
+ scaffolding_completely_concrete_tangible_thing:
55
+ type: object
56
+ $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingParameters"
45
57
  responses:
46
58
  "404":
47
59
  description: "Not Found"
@@ -50,7 +62,7 @@
50
62
  content:
51
63
  application/json:
52
64
  schema:
53
- $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingParameters"
65
+ $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
54
66
  <% end %>
55
67
  <% end %>
56
68
  <% unless except.include?(:show) && except.include?(:update) && except.include?(:destroy) %>
@@ -81,6 +93,17 @@
81
93
  operationId: updateScaffoldingCompletelyConcreteTangibleThings
82
94
  parameters:
83
95
  - $ref: "#/components/parameters/id"
96
+ requestBody:
97
+ description: "Information about updated fields in Tangible Thing"
98
+ required: true
99
+ content:
100
+ application/json:
101
+ schema:
102
+ type: object
103
+ properties:
104
+ scaffolding_completely_concrete_tangible_thing:
105
+ type: object
106
+ $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingParameters"
84
107
  responses:
85
108
  "404":
86
109
  description: "Not Found"
@@ -89,7 +112,7 @@
89
112
  content:
90
113
  application/json:
91
114
  schema:
92
- $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingParameters"
115
+ $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
93
116
  <% end %>
94
117
  <% unless except.include?(:destroy) %>
95
118
  delete:
@@ -102,7 +125,7 @@
102
125
  responses:
103
126
  "404":
104
127
  description: "Not Found"
105
- "200":
106
- description: "OK"
128
+ "204":
129
+ description: "No Content"
107
130
  <% end %>
108
131
  <% end %>
@@ -4,22 +4,24 @@
4
4
  - Teams
5
5
  summary: "List Teams"
6
6
  operationId: listTeams
7
+ parameters:
8
+ - $ref: "#/components/parameters/after"
7
9
  responses:
8
10
  "404":
9
11
  description: "Not Found"
10
12
  "200":
11
13
  description: "OK"
14
+ headers:
15
+ Pagination-Next:
16
+ $ref: "#/components/headers/PaginationNext"
17
+ Link:
18
+ $ref: "#/components/headers/Link"
12
19
  content:
13
20
  application/json:
14
21
  schema:
15
- type: object
16
- properties:
17
- data:
18
- type: array
19
- items:
20
- $ref: "#/components/schemas/TeamAttributes"
21
- has_more:
22
- type: boolean
22
+ type: array
23
+ items:
24
+ $ref: "#/components/schemas/TeamAttributes"
23
25
  /teams/{id}:
24
26
  get:
25
27
  tags:
@@ -44,6 +46,17 @@
44
46
  operationId: updateTeam
45
47
  parameters:
46
48
  - $ref: "#/components/parameters/id"
49
+ requestBody:
50
+ description: "Information about updated fields in Team"
51
+ required: true
52
+ content:
53
+ application/json:
54
+ schema:
55
+ type: object
56
+ properties:
57
+ team:
58
+ type: object
59
+ $ref: "#/components/schemas/TeamParameters"
47
60
  responses:
48
61
  "404":
49
62
  description: "Not Found"
@@ -52,4 +65,4 @@
52
65
  content:
53
66
  application/json:
54
67
  schema:
55
- $ref: "#/components/schemas/TeamParameters"
68
+ $ref: "#/components/schemas/TeamAttributes"
@@ -4,22 +4,24 @@
4
4
  - Users
5
5
  summary: "List Users"
6
6
  operationId: listUsers
7
+ parameters:
8
+ - $ref: "#/components/parameters/after"
7
9
  responses:
8
10
  "404":
9
11
  description: "Not Found"
10
12
  "200":
11
13
  description: "OK"
14
+ headers:
15
+ Pagination-Next:
16
+ $ref: "#/components/headers/PaginationNext"
17
+ Link:
18
+ $ref: "#/components/headers/Link"
12
19
  content:
13
20
  application/json:
14
21
  schema:
15
- type: object
16
- properties:
17
- data:
18
- type: array
19
- items:
20
- $ref: "#/components/schemas/UserAttributes"
21
- has_more:
22
- type: boolean
22
+ type: array
23
+ items:
24
+ $ref: "#/components/schemas/UserAttributes"
23
25
  /users/{id}:
24
26
  get:
25
27
  tags:
@@ -44,6 +46,17 @@
44
46
  operationId: updateUser
45
47
  parameters:
46
48
  - $ref: "#/components/parameters/id"
49
+ requestBody:
50
+ description: "Information about updated fields in User"
51
+ required: true
52
+ content:
53
+ application/json:
54
+ schema:
55
+ type: object
56
+ properties:
57
+ user:
58
+ type: object
59
+ $ref: "#/components/schemas/UserParameters"
47
60
  responses:
48
61
  "404":
49
62
  description: "Not Found"
@@ -52,4 +65,4 @@
52
65
  content:
53
66
  application/json:
54
67
  schema:
55
- $ref: "#/components/schemas/UserParameters"
68
+ $ref: "#/components/schemas/UserAttributes"
@@ -81,6 +81,8 @@ en:
81
81
  created: Platform Application was successfully created.
82
82
  updated: Platform Application was successfully updated.
83
83
  destroyed: Platform Application was successfully destroyed.
84
+ test_application_created: Test Platform Application was successfully created.
85
+ test_application_failure: You must provide the proper testing provision key to create a test application.
84
86
  account:
85
87
  platform:
86
88
  applications: *applications
data/config/routes.rb CHANGED
@@ -17,6 +17,10 @@ Rails.application.routes.draw do
17
17
  end
18
18
  end
19
19
 
20
+ if ENV["TESTING_PROVISION_KEY"].present?
21
+ get "/testing/provision", to: "account/platform/applications#provision"
22
+ end
23
+
20
24
  namespace :api do
21
25
  match "*version/openapi.yaml" => "open_api#index", :via => :get
22
26
 
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module Api
3
- VERSION = "1.1.15"
3
+ VERSION = "1.2.1"
4
4
  end
5
5
  end
@@ -1,4 +1,76 @@
1
- # desc "Explaining what the task does"
2
- # task :bullet_train_api do
3
- # # Task goes here
4
- # end
1
+ require "scaffolding"
2
+ require "scaffolding/file_manipulator"
3
+
4
+ namespace :bullet_train do
5
+ namespace :api do
6
+ desc "Bump the current version of application's API"
7
+ task :bump_version do
8
+ # Calculate new version.
9
+ initializer_content = File.new("config/initializers/api.rb").readline
10
+ previous_version = initializer_content.scan(/v\d+/).pop
11
+ new_version = "v#{previous_version.scan(/\d+/).pop.to_i + 1}"
12
+
13
+ # Update initializer.
14
+ File.write("config/initializers/api.rb", initializer_content.gsub(previous_version, new_version))
15
+
16
+ [
17
+ "app/controllers/api/#{new_version}",
18
+ "app/views/api/#{new_version}",
19
+ "test/controllers/api/#{new_version}"
20
+ ].each do |dir|
21
+ Dir.mkdir(dir)
22
+ end
23
+
24
+ files_to_update = [
25
+ "config/routes/api/#{previous_version}.rb",
26
+ Dir.glob("app/controllers/api/#{previous_version}/**/*.rb") +
27
+ Dir.glob("app/views/api/#{previous_version}/**/*.json.jbuilder") +
28
+ Dir.glob("test/controllers/api/#{previous_version}/**/*.rb")
29
+ ].flatten
30
+
31
+ files_to_update.each do |file_name|
32
+ previous_file_contents = File.open(file_name).readlines
33
+ new_file_name = file_name.gsub(previous_version, new_version)
34
+
35
+ updated_file_contents = previous_file_contents.map do |line|
36
+ if line.match?(previous_version)
37
+ line.gsub(previous_version, new_version)
38
+ else
39
+ line.gsub("Api::#{previous_version.upcase}", "Api::#{new_version.upcase}")
40
+ end
41
+ end
42
+
43
+ # We can't create new files unless each directory under #{api/previous_version}
44
+ # has been created under the new api directory. For example, we have to create
45
+ # the `projects` directory before we can create the file `api/v2/projects/pages.json.jbuilder.`
46
+ new_version_dir, dir_hierarchy = new_file_name.split(/(?<=#{new_version})\//)
47
+ if dir_hierarchy.present? && dir_hierarchy.match?("/")
48
+ dir_hierarchy = dir_hierarchy.split("/")
49
+ dir_hierarchy.inject(new_version_dir) do |base, child_dir_or_file|
50
+ # Stop making new directories if the string has an extention like ".rb"
51
+ break if child_dir_or_file.match?(/\./)
52
+
53
+ new_hierarchy = "#{base}/#{child_dir_or_file}"
54
+ Dir.mkdir(new_hierarchy) unless Dir.exist?(new_hierarchy)
55
+ new_hierarchy
56
+ end
57
+ end
58
+ Scaffolding::FileManipulator.write(new_file_name, updated_file_contents)
59
+ end
60
+
61
+ # Here we make sure config/api/#{new_version}.rb is called from within the main routes file.
62
+ previous_file_contents = File.open("config/routes.rb").readlines
63
+ updated_file_contents = previous_file_contents.map do |line|
64
+ if line.match?("draw \"api/#{previous_version}\"")
65
+ new_version_draw_line = line.gsub(previous_version, new_version)
66
+ line + new_version_draw_line
67
+ else
68
+ line
69
+ end
70
+ end
71
+ Scaffolding::FileManipulator.write("config/routes.rb", updated_file_contents)
72
+
73
+ puts "Finished bumping to #{new_version}"
74
+ end
75
+ end
76
+ 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.1.15
4
+ version: 1.2.1
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-11-16 00:00:00.000000000 Z
11
+ date: 2022-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard