bullet_train-api 1.1.2 → 1.1.5
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/account/platform/access_tokens_controller.rb +76 -0
- data/app/controllers/account/platform/applications_controller.rb +2 -5
- data/app/controllers/api/open_api_controller.rb +59 -0
- data/app/controllers/api/v1/platform/access_tokens_controller.rb +53 -0
- data/app/controllers/concerns/api/controllers/base.rb +1 -0
- data/app/models/platform/access_token.rb +32 -0
- data/app/models/platform/application.rb +5 -0
- data/app/views/account/platform/access_tokens/_breadcrumbs.html.erb +8 -0
- data/app/views/account/platform/access_tokens/_form.html.erb +18 -0
- data/app/views/account/platform/access_tokens/_index.html.erb +91 -0
- data/app/views/account/platform/access_tokens/_menu_item.html.erb +10 -0
- data/app/views/account/platform/access_tokens/edit.html.erb +12 -0
- data/app/views/account/platform/access_tokens/index.html.erb +6 -0
- data/app/views/account/platform/access_tokens/new.html.erb +12 -0
- data/app/views/account/platform/access_tokens/show.html.erb +36 -0
- data/app/views/account/platform/applications/_application.json.jbuilder +0 -1
- data/app/views/account/platform/applications/_form.html.erb +0 -1
- data/app/views/account/platform/applications/_index.html.erb +1 -3
- data/app/views/account/platform/applications/show.html.erb +2 -3
- data/app/views/api/v1/open_api/index.yaml.erb +29 -0
- data/app/views/api/v1/open_api/teams/_paths.yaml.erb +55 -0
- data/app/views/api/v1/open_api/users/_paths.yaml.erb +55 -0
- data/app/views/api/v1/platform/access_tokens/_access_token.json.jbuilder +10 -0
- data/app/views/api/v1/platform/access_tokens/index.json.jbuilder +5 -0
- data/app/views/api/v1/platform/access_tokens/show.json.jbuilder +1 -0
- data/config/locales/en/platform/access_tokens.en.yml +109 -0
- data/config/locales/en/platform/applications.en.yml +5 -14
- data/config/routes.rb +21 -1
- data/lib/bullet_train/api/version.rb +1 -1
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2521c60465a29b8bbba8ce4b2e0ab2467eb6fe28d0eae93b62b1048814549ff
|
4
|
+
data.tar.gz: 51e147d8bf695bdd4a15e29132ab47c61adce31b2798f1b63d71bf874371e87f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27312b084571e76ce175b51572f7fb9c956c33ad0052777c4b26a3dcfb5577ad4f6ccccf3c441618ac4aab1229b21a16304cf1383791c21826a2ab08aa83758c
|
7
|
+
data.tar.gz: ef6a86089cbeaf1f83de3ed73a59c286b25b9c47104a7c522ef7d4d7eeab604a43641be0e0d203061b856829536b138f7d1baee2a050a829d61007967e4097c7
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Account::Platform::AccessTokensController < Account::ApplicationController
|
2
|
+
account_load_and_authorize_resource :access_token, through: :application, through_association: :access_tokens
|
3
|
+
|
4
|
+
# GET /account/platform/applications/:application_id/access_tokens
|
5
|
+
# GET /account/platform/applications/:application_id/access_tokens.json
|
6
|
+
def index
|
7
|
+
delegate_json_to_api do
|
8
|
+
redirect_to [:account, @application]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# GET /account/platform/access_tokens/:id
|
13
|
+
# GET /account/platform/access_tokens/:id.json
|
14
|
+
def show
|
15
|
+
delegate_json_to_api do
|
16
|
+
redirect_to [:account, @application]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# GET /account/platform/applications/:application_id/access_tokens/new
|
21
|
+
def new
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /account/platform/access_tokens/:id/edit
|
25
|
+
def edit
|
26
|
+
end
|
27
|
+
|
28
|
+
# POST /account/platform/applications/:application_id/access_tokens
|
29
|
+
# POST /account/platform/applications/:application_id/access_tokens.json
|
30
|
+
def create
|
31
|
+
@access_token.provisioned = true
|
32
|
+
|
33
|
+
respond_to do |format|
|
34
|
+
if @access_token.save
|
35
|
+
format.html { redirect_to [:account, @application, :access_tokens], notice: I18n.t("platform/access_tokens.notifications.created") }
|
36
|
+
format.json { render :show, status: :created, location: [:account, @access_token] }
|
37
|
+
else
|
38
|
+
format.html { render :new, status: :unprocessable_entity }
|
39
|
+
format.json { render json: @access_token.errors, status: :unprocessable_entity }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# PATCH/PUT /account/platform/access_tokens/:id
|
45
|
+
# PATCH/PUT /account/platform/access_tokens/:id.json
|
46
|
+
def update
|
47
|
+
respond_to do |format|
|
48
|
+
if @access_token.update(access_token_params)
|
49
|
+
format.html { redirect_to [:account, @access_token], notice: I18n.t("platform/access_tokens.notifications.updated") }
|
50
|
+
format.json { render :show, status: :ok, location: [:account, @access_token] }
|
51
|
+
else
|
52
|
+
format.html { render :edit, status: :unprocessable_entity }
|
53
|
+
format.json { render json: @access_token.errors, status: :unprocessable_entity }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# DELETE /account/platform/access_tokens/:id
|
59
|
+
# DELETE /account/platform/access_tokens/:id.json
|
60
|
+
def destroy
|
61
|
+
@access_token.destroy
|
62
|
+
respond_to do |format|
|
63
|
+
format.html { redirect_to [:account, @application, :access_tokens], notice: I18n.t("platform/access_tokens.notifications.destroyed") }
|
64
|
+
format.json { head :no_content }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
include strong_parameters_from_api
|
71
|
+
|
72
|
+
def process_params(strong_params)
|
73
|
+
assign_date_and_time(strong_params, :last_used_at)
|
74
|
+
# 🚅 super scaffolding will insert processing for new fields above this line.
|
75
|
+
end
|
76
|
+
end
|
@@ -26,7 +26,7 @@ class Account::Platform::ApplicationsController < Account::ApplicationController
|
|
26
26
|
def create
|
27
27
|
respond_to do |format|
|
28
28
|
if @application.save
|
29
|
-
format.html { redirect_to [:account, @
|
29
|
+
format.html { redirect_to [:account, @application], notice: I18n.t("platform/applications.notifications.created") }
|
30
30
|
format.json { render :show, status: :created, location: [:account, @application] }
|
31
31
|
else
|
32
32
|
format.html { render :new, status: :unprocessable_entity }
|
@@ -63,16 +63,13 @@ class Account::Platform::ApplicationsController < Account::ApplicationController
|
|
63
63
|
|
64
64
|
# Never trust parameters from the scary internet, only allow the white list through.
|
65
65
|
def application_params
|
66
|
-
|
66
|
+
params.require(:platform_application).permit(
|
67
67
|
:name,
|
68
|
-
:scopes,
|
69
68
|
:redirect_uri,
|
70
69
|
# 🚅 super scaffolding will insert new fields above this line.
|
71
70
|
# 🚅 super scaffolding will insert new arrays above this line.
|
72
71
|
)
|
73
72
|
|
74
73
|
# 🚅 super scaffolding will insert processing for new fields above this line.
|
75
|
-
|
76
|
-
strong_params
|
77
74
|
end
|
78
75
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module OpenApiHelper
|
2
|
+
def indent(string, count)
|
3
|
+
lines = string.lines
|
4
|
+
first_line = lines.shift
|
5
|
+
lines = lines.map { |line| (" " * count).to_s + line }
|
6
|
+
lines.unshift(first_line).join.html_safe
|
7
|
+
end
|
8
|
+
|
9
|
+
def components_for(model)
|
10
|
+
for_model model do
|
11
|
+
indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/components"), 2)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_model
|
16
|
+
@model_stack.last
|
17
|
+
end
|
18
|
+
|
19
|
+
def for_model(model)
|
20
|
+
@model_stack ||= []
|
21
|
+
@model_stack << model
|
22
|
+
result = yield
|
23
|
+
@model_stack.pop
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
def paths_for(model)
|
28
|
+
for_model model do
|
29
|
+
indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/paths"), 1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def attribute(attribute)
|
34
|
+
heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
|
35
|
+
# TODO A lot of logic to be done here.
|
36
|
+
indent("#{attribute}:\n description: \"#{heading}\"\n type: string", 2)
|
37
|
+
end
|
38
|
+
|
39
|
+
def parameter(attribute)
|
40
|
+
heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
|
41
|
+
# TODO A lot of logic to be done here.
|
42
|
+
indent("#{attribute}:\n description: \"#{heading}\"\n type: string", 2)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Api::OpenApiController < ApplicationController
|
47
|
+
helper :open_api
|
48
|
+
|
49
|
+
def set_default_response_format
|
50
|
+
request.format = :yaml
|
51
|
+
end
|
52
|
+
|
53
|
+
before_action :set_default_response_format
|
54
|
+
|
55
|
+
def index
|
56
|
+
@version = params[:version]
|
57
|
+
render "api/#{@version}/open_api/index", layout: nil, format: :text
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Api::V1::Platform::AccessTokensController < Api::V1::ApplicationController
|
2
|
+
account_load_and_authorize_resource :access_token, through: :application, through_association: :access_tokens
|
3
|
+
|
4
|
+
# GET /api/v1/platform/access_tokens/:id
|
5
|
+
def show
|
6
|
+
end
|
7
|
+
|
8
|
+
# POST /api/v1/platform/applications/:application_id/access_tokens
|
9
|
+
def create
|
10
|
+
@access_token.provisioned = true
|
11
|
+
|
12
|
+
if @access_token.save
|
13
|
+
render :show, status: :created, location: [:api, :v1, @access_token]
|
14
|
+
else
|
15
|
+
render json: @access_token.errors, status: :unprocessable_entity
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# PATCH/PUT /api/v1/platform/access_tokens/:id
|
20
|
+
def update
|
21
|
+
if @access_token.update(access_token_params)
|
22
|
+
render :show
|
23
|
+
else
|
24
|
+
render json: @access_token.errors, status: :unprocessable_entity
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# DELETE /api/v1/platform/access_tokens/:id
|
29
|
+
def destroy
|
30
|
+
@access_token.destroy
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
module StrongParameters
|
36
|
+
# Only allow a list of trusted parameters through.
|
37
|
+
def access_token_params
|
38
|
+
strong_params = params.require(:platform_access_token).permit(
|
39
|
+
*permitted_fields,
|
40
|
+
:description,
|
41
|
+
# 🚅 super scaffolding will insert new fields above this line.
|
42
|
+
*permitted_arrays,
|
43
|
+
# 🚅 super scaffolding will insert new arrays above this line.
|
44
|
+
)
|
45
|
+
|
46
|
+
process_params(strong_params)
|
47
|
+
|
48
|
+
strong_params
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
include StrongParameters
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Platform::AccessToken < ApplicationRecord
|
2
|
+
self.table_name = "oauth_access_tokens"
|
3
|
+
|
4
|
+
include Doorkeeper::Orm::ActiveRecord::Mixins::AccessToken
|
5
|
+
# 🚅 add concerns above.
|
6
|
+
|
7
|
+
# 🚅 add concerns above.
|
8
|
+
|
9
|
+
# 🚅 add attribute accessors above.
|
10
|
+
|
11
|
+
# 🚅 add belongs_to associations above.
|
12
|
+
|
13
|
+
# 🚅 add has_many associations above.
|
14
|
+
|
15
|
+
has_one :team, through: :application
|
16
|
+
# 🚅 add has_one associations above.
|
17
|
+
|
18
|
+
# 🚅 add scopes above.
|
19
|
+
|
20
|
+
validates :token, presence: true
|
21
|
+
validates :description, presence: true, if: :provisioned?
|
22
|
+
# 🚅 add validations above.
|
23
|
+
|
24
|
+
# 🚅 add callbacks above.
|
25
|
+
|
26
|
+
# 🚅 add delegations above.
|
27
|
+
|
28
|
+
def label_string
|
29
|
+
description
|
30
|
+
end
|
31
|
+
# 🚅 add methods above.
|
32
|
+
end
|
@@ -20,6 +20,7 @@ class Platform::Application < ApplicationRecord
|
|
20
20
|
# 🚅 add validations above.
|
21
21
|
|
22
22
|
after_create :create_user_and_membership
|
23
|
+
after_create :create_access_token
|
23
24
|
after_update :update_user_and_membership
|
24
25
|
before_destroy :destroy_user
|
25
26
|
# 🚅 add callbacks above.
|
@@ -37,6 +38,10 @@ class Platform::Application < ApplicationRecord
|
|
37
38
|
membership.roles << Role.admin
|
38
39
|
end
|
39
40
|
|
41
|
+
def create_access_token
|
42
|
+
access_tokens.create(resource_owner_id: user.id, description: "Default Access Token", provisioned: true)
|
43
|
+
end
|
44
|
+
|
40
45
|
def update_user_and_membership
|
41
46
|
user.update(first_name: label_string)
|
42
47
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<% access_token ||= @access_token %>
|
2
|
+
<% application ||= @application || access_token&.application %>
|
3
|
+
<%= render 'account/platform/applications/breadcrumbs', application: application %>
|
4
|
+
<%= render 'account/shared/breadcrumb', label: t('.label'), url: [:account, application, :access_tokens] %>
|
5
|
+
<% if access_token&.persisted? %>
|
6
|
+
<%= render 'account/shared/breadcrumb', label: access_token.label_string, url: [:account, access_token] %>
|
7
|
+
<% end %>
|
8
|
+
<%= render 'account/shared/breadcrumbs/actions', only_for: 'platform/access_tokens' %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= form_with model: access_token, url: (access_token.persisted? ? [:account, access_token] : [:account, @application, :access_tokens]), local: true, class: 'form' do |form| %>
|
2
|
+
<%= render 'account/shared/forms/errors', form: form %>
|
3
|
+
|
4
|
+
<% with_field_settings form: form do %>
|
5
|
+
<%= render 'shared/fields/text_field', method: :description, options: {autofocus: true} %>
|
6
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<div class="buttons">
|
10
|
+
<%= form.submit (form.object.persisted? ? t('.buttons.update') : t('.buttons.create')), class: "button" %>
|
11
|
+
<% if form.object.persisted? %>
|
12
|
+
<%= link_to t('global.buttons.cancel'), [:account, access_token], class: "button-secondary" %>
|
13
|
+
<% else %>
|
14
|
+
<%= link_to t('global.buttons.cancel'), [:account, @application, :access_tokens], class: "button-secondary" %>
|
15
|
+
<% end %>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<% end %>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
<% application = @application || @application %>
|
2
|
+
<% context ||= application %>
|
3
|
+
<% collection ||= :access_tokens %>
|
4
|
+
<% hide_actions ||= false %>
|
5
|
+
<% hide_back ||= false %>
|
6
|
+
|
7
|
+
<% access_tokens = access_tokens.order(:id) unless has_order?(access_tokens) %>
|
8
|
+
<% pagy, access_tokens = pagy(access_tokens, page_param: :access_tokens_page) %>
|
9
|
+
|
10
|
+
<%= action_model_select_controller do %>
|
11
|
+
<%= updates_for context, collection do %>
|
12
|
+
<%= render 'account/shared/box', pagy: pagy do |p| %>
|
13
|
+
<% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
|
14
|
+
<% p.content_for :description do %>
|
15
|
+
<%= t(".contexts.#{context.class.name.underscore}.description") %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% p.content_for :table do %>
|
19
|
+
<% if access_tokens.any? %>
|
20
|
+
<table class="table">
|
21
|
+
<thead>
|
22
|
+
<tr>
|
23
|
+
<%= render "shared/tables/select_all" %>
|
24
|
+
<th><%= t('.fields.token.heading') %></th>
|
25
|
+
<th><%= t('.fields.description.heading') %></th>
|
26
|
+
<th><%= t('.fields.last_used_at.heading') %></th>
|
27
|
+
<%# 🚅 super scaffolding will insert new field headers above this line. %>
|
28
|
+
<th><%= t('.fields.created_at.heading') %></th>
|
29
|
+
<th class="text-right"></th>
|
30
|
+
</tr>
|
31
|
+
</thead>
|
32
|
+
<tbody>
|
33
|
+
<% access_tokens.each do |access_token| %>
|
34
|
+
<% with_attribute_settings object: access_token do %>
|
35
|
+
<tr data-id="<%= access_token.id %>">
|
36
|
+
<%= render "shared/tables/checkbox", object: access_token %>
|
37
|
+
<td><%= render 'shared/attributes/code', attribute: :token, secret: true %></td>
|
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>
|
47
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
48
|
+
<td><%= render 'shared/attributes/date_and_time', attribute: :created_at %></td>
|
49
|
+
<td class="buttons">
|
50
|
+
<% unless hide_actions %>
|
51
|
+
<% if can? :edit, access_token %>
|
52
|
+
<%= link_to t('.buttons.shorthand.edit'), [:edit, :account, access_token], class: 'button-secondary button-smaller' %>
|
53
|
+
<% end %>
|
54
|
+
<% if can? :destroy, access_token %>
|
55
|
+
<%= button_to t('.buttons.shorthand.destroy'), [:account, access_token], method: :delete, data: { confirm: t('.buttons.confirmations.destroy', model_locales(access_token)) }, class: 'button-secondary button-smaller' %>
|
56
|
+
<% end %>
|
57
|
+
<%# 🚅 super scaffolding will insert new action model buttons above this line. %>
|
58
|
+
<% end %>
|
59
|
+
</td>
|
60
|
+
</tr>
|
61
|
+
<% end %>
|
62
|
+
<% end %>
|
63
|
+
</tbody>
|
64
|
+
</table>
|
65
|
+
<% end %>
|
66
|
+
<% end %>
|
67
|
+
|
68
|
+
<% p.content_for :actions do %>
|
69
|
+
<% unless hide_actions %>
|
70
|
+
<% if context == application %>
|
71
|
+
<% if can? :create, Platform::AccessToken.new(application: application, provisioned: true) %>
|
72
|
+
<%= link_to t('.buttons.new'), [:new, :account, application, :access_token], class: "#{first_button_primary(:access_token)} new" %>
|
73
|
+
<% end %>
|
74
|
+
<% end %>
|
75
|
+
|
76
|
+
<%# 🚅 super scaffolding will insert new targets one parent action model buttons above this line. %>
|
77
|
+
<%# 🚅 super scaffolding will insert new bulk action model buttons above this line. %>
|
78
|
+
<%= render "shared/bulk_action_select" %>
|
79
|
+
|
80
|
+
<% unless hide_back %>
|
81
|
+
<%= link_to t('global.buttons.back'), [:account, context], class: "#{first_button_primary(:access_token)} back" %>
|
82
|
+
<% end %>
|
83
|
+
<% end %>
|
84
|
+
<% end %>
|
85
|
+
|
86
|
+
<% p.content_for :raw_footer do %>
|
87
|
+
<%# 🚅 super scaffolding will insert new action model index views above this line. %>
|
88
|
+
<% end %>
|
89
|
+
<% end %>
|
90
|
+
<% end %>
|
91
|
+
<% end %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% if can? :read, Platform::AccessToken.new(team: current_team) %>
|
2
|
+
<%= render 'account/shared/menu/item', {
|
3
|
+
url: main_app.polymorphic_path([:account, current_team, :platform_access_tokens]),
|
4
|
+
label: t('platform/access_tokens.navigation.label'),
|
5
|
+
} do |p| %>
|
6
|
+
<% p.content_for :icon do %>
|
7
|
+
<i class="<%= t('platform/access_tokens.navigation.icon') %>"></i>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= render 'account/shared/page' do |p| %>
|
2
|
+
<% p.content_for :title, t('.section') %>
|
3
|
+
<% p.content_for :body do %>
|
4
|
+
<%= render 'account/shared/box', divider: true do |p| %>
|
5
|
+
<% p.content_for :title, t('.header') %>
|
6
|
+
<% p.content_for :description, t('.description') %>
|
7
|
+
<% p.content_for :body do %>
|
8
|
+
<%= render 'form', access_token: @access_token %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= render 'account/shared/page' do |p| %>
|
2
|
+
<% p.content_for :title, t('.section') %>
|
3
|
+
<% p.content_for :body do %>
|
4
|
+
<%= render 'account/shared/box', divider: true do |p| %>
|
5
|
+
<% p.content_for :title, t('.header') %>
|
6
|
+
<% p.content_for :description, t('.description') %>
|
7
|
+
<% p.content_for :body do %>
|
8
|
+
<%= render 'form', access_token: @access_token %>
|
9
|
+
<% end %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<%= render 'account/shared/page' do |p| %>
|
2
|
+
<% p.content_for :title, t('.section') %>
|
3
|
+
<% p.content_for :body do %>
|
4
|
+
<%= updates_for @access_token do %>
|
5
|
+
<%= render 'account/shared/box', divider: true do |p| %>
|
6
|
+
<% p.content_for :title, t('.header') %>
|
7
|
+
<% p.content_for :description do %>
|
8
|
+
<%= t('.description') %>
|
9
|
+
<%= t('.manage_description') if can? :manage, @access_token %>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<% p.content_for :body do %>
|
13
|
+
<% with_attribute_settings object: @access_token, strategy: :label do %>
|
14
|
+
<%= render 'shared/attributes/text', attribute: :token %>
|
15
|
+
<%= render 'shared/attributes/date_and_time', attribute: :last_used_at %>
|
16
|
+
<%= render 'shared/attributes/text', attribute: :description %>
|
17
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<% p.content_for :actions do %>
|
22
|
+
<%= link_to t('.buttons.edit'), [:edit, :account, @access_token], class: first_button_primary if can? :edit, @access_token %>
|
23
|
+
<%# 🚅 super scaffolding will insert new action model buttons above this line. %>
|
24
|
+
<%= button_to t('.buttons.destroy'), [:account, @access_token], method: :delete, class: first_button_primary, data: { confirm: t('.buttons.confirmations.destroy', model_locales(@access_token)) } if can? :destroy, @access_token %>
|
25
|
+
<%= link_to t('global.buttons.back'), [:account, @application, :access_tokens], class: first_button_primary %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<% p.content_for :raw_footer do %>
|
29
|
+
<%# 🚅 super scaffolding will insert new action model index views above this line. %>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<%# 🚅 super scaffolding will insert new children above this line. %>
|
35
|
+
<% end %>
|
36
|
+
<% end %>
|
@@ -3,7 +3,6 @@
|
|
3
3
|
|
4
4
|
<% with_field_settings form: form do %>
|
5
5
|
<%= render 'shared/fields/text_field', method: :name, options: {autofocus: true} %>
|
6
|
-
<%= render 'shared/fields/text_field', method: :scopes %>
|
7
6
|
<%= render 'shared/fields/text_field', method: :redirect_uri %>
|
8
7
|
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
9
8
|
<% end %>
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<%= render 'account/shared/box' do |p| %>
|
8
8
|
<% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
|
9
9
|
<% p.content_for :description do %>
|
10
|
-
<%= t(".contexts.#{context.class.name.underscore}.description
|
10
|
+
<%= t(".contexts.#{context.class.name.underscore}.description") %>
|
11
11
|
<% end %>
|
12
12
|
|
13
13
|
<% p.content_for :table do %>
|
@@ -16,7 +16,6 @@
|
|
16
16
|
<thead>
|
17
17
|
<tr>
|
18
18
|
<th><%= t('.fields.name.heading') %></th>
|
19
|
-
<th><%= t('.fields.scopes.heading') %></th>
|
20
19
|
<%# 🚅 super scaffolding will insert new field headers above this line. %>
|
21
20
|
<th><%= t('.fields.created_at.heading') %></th>
|
22
21
|
<th class="text-right"></th>
|
@@ -27,7 +26,6 @@
|
|
27
26
|
<% with_attribute_settings object: application do %>
|
28
27
|
<tr data-id="<%= application.id %>">
|
29
28
|
<td><%= render 'shared/attributes/text', attribute: :name, url: [:account, application] %></td>
|
30
|
-
<td><%= render 'shared/attributes/text', attribute: :scopes %></td>
|
31
29
|
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
32
30
|
<td><%= display_date_and_time(application.created_at) %></td>
|
33
31
|
<td class="buttons">
|
@@ -5,15 +5,13 @@
|
|
5
5
|
<% p.content_for :title, t('.header') %>
|
6
6
|
<% p.content_for :description do %>
|
7
7
|
<%= t('.description') %>
|
8
|
-
<%= t('.manage_description') if can? :manage, @application %>
|
9
8
|
<% end %>
|
10
9
|
|
11
10
|
<% p.content_for :body do %>
|
12
11
|
<% with_attribute_settings object: @application, strategy: :label do %>
|
13
12
|
<%= render 'shared/attributes/text', attribute: :name %>
|
14
13
|
<%= render 'shared/attributes/code', attribute: :uid %>
|
15
|
-
<%= render 'shared/attributes/code', attribute: :secret %>
|
16
|
-
<%= render 'shared/attributes/text', attribute: :scopes %>
|
14
|
+
<%= render 'shared/attributes/code', attribute: :secret, secret: true %>
|
17
15
|
<%= render 'shared/attributes/text', attribute: :redirect_uri %>
|
18
16
|
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
19
17
|
<% end %>
|
@@ -26,6 +24,7 @@
|
|
26
24
|
<% end %>
|
27
25
|
<% end %>
|
28
26
|
|
27
|
+
<%= render 'account/platform/access_tokens/index', access_tokens: @application.access_tokens.accessible_by(current_ability), hide_back: true %>
|
29
28
|
<%# 🚅 super scaffolding will insert new children above this line. %>
|
30
29
|
<% end %>
|
31
30
|
<% end %>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
openapi: 3.1.0
|
2
|
+
info:
|
3
|
+
title: Bullet Train API
|
4
|
+
description: |
|
5
|
+
The baseline API of a new Bullet Train application.
|
6
|
+
license:
|
7
|
+
name: MIT
|
8
|
+
url: https://opensource.org/licenses/MIT
|
9
|
+
version: "<%= @version.upcase %>"
|
10
|
+
servers:
|
11
|
+
- url: <%= ENV["BASE_URL"] %>/api/<%= @version %>
|
12
|
+
components:
|
13
|
+
schemas:
|
14
|
+
<%= components_for Team %>
|
15
|
+
<%= components_for User %>
|
16
|
+
<%= components_for Scaffolding::CompletelyConcrete::TangibleThing unless scaffolding_things_disabled? %>
|
17
|
+
<%# 🚅 super scaffolding will insert new components above this line. %>
|
18
|
+
parameters:
|
19
|
+
id:
|
20
|
+
name: id
|
21
|
+
in: path
|
22
|
+
required: true
|
23
|
+
schema:
|
24
|
+
type: string
|
25
|
+
paths:
|
26
|
+
<%= paths_for Team %>
|
27
|
+
<%= paths_for User %>
|
28
|
+
<%= paths_for Scaffolding::CompletelyConcrete::TangibleThing unless scaffolding_things_disabled? %>
|
29
|
+
<%# 🚅 super scaffolding will insert new paths above this line. %>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/teams:
|
2
|
+
get:
|
3
|
+
tags:
|
4
|
+
- Teams
|
5
|
+
summary: "List Teams"
|
6
|
+
operationId: listTeams
|
7
|
+
responses:
|
8
|
+
"404":
|
9
|
+
description: "Not Found"
|
10
|
+
"200":
|
11
|
+
description: "OK"
|
12
|
+
content:
|
13
|
+
application/json:
|
14
|
+
schema:
|
15
|
+
type: object
|
16
|
+
properties:
|
17
|
+
data:
|
18
|
+
type: array
|
19
|
+
items:
|
20
|
+
$ref: "#/components/schemas/Team::Attributes"
|
21
|
+
has_more:
|
22
|
+
type: boolean
|
23
|
+
/teams/{id}:
|
24
|
+
get:
|
25
|
+
tags:
|
26
|
+
- Teams
|
27
|
+
summary: "Fetch Team"
|
28
|
+
operationId: fetchTeam
|
29
|
+
parameters:
|
30
|
+
- $ref: "#/components/parameters/id"
|
31
|
+
responses:
|
32
|
+
"404":
|
33
|
+
description: "Not Found"
|
34
|
+
"200":
|
35
|
+
description: "OK"
|
36
|
+
content:
|
37
|
+
application/json:
|
38
|
+
schema:
|
39
|
+
$ref: "#/components/schemas/Team::Attributes"
|
40
|
+
put:
|
41
|
+
tags:
|
42
|
+
- Teams
|
43
|
+
summary: "Update Team"
|
44
|
+
operationId: updateTeam
|
45
|
+
parameters:
|
46
|
+
- $ref: "#/components/parameters/id"
|
47
|
+
responses:
|
48
|
+
"404":
|
49
|
+
description: "Not Found"
|
50
|
+
"200":
|
51
|
+
description: "OK"
|
52
|
+
content:
|
53
|
+
application/json:
|
54
|
+
schema:
|
55
|
+
$ref: "#/components/schemas/Team::Parameters"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/users:
|
2
|
+
get:
|
3
|
+
tags:
|
4
|
+
- Users
|
5
|
+
summary: "List Users"
|
6
|
+
operationId: listUsers
|
7
|
+
responses:
|
8
|
+
"404":
|
9
|
+
description: "Not Found"
|
10
|
+
"200":
|
11
|
+
description: "OK"
|
12
|
+
content:
|
13
|
+
application/json:
|
14
|
+
schema:
|
15
|
+
type: object
|
16
|
+
properties:
|
17
|
+
data:
|
18
|
+
type: array
|
19
|
+
items:
|
20
|
+
$ref: "#/components/schemas/User::Attributes"
|
21
|
+
has_more:
|
22
|
+
type: boolean
|
23
|
+
/users/{id}:
|
24
|
+
get:
|
25
|
+
tags:
|
26
|
+
- Users
|
27
|
+
summary: "Fetch User"
|
28
|
+
operationId: fetchUser
|
29
|
+
parameters:
|
30
|
+
- $ref: "#/components/parameters/id"
|
31
|
+
responses:
|
32
|
+
"404":
|
33
|
+
description: "Not Found"
|
34
|
+
"200":
|
35
|
+
description: "OK"
|
36
|
+
content:
|
37
|
+
application/json:
|
38
|
+
schema:
|
39
|
+
$ref: "#/components/schemas/User::Attributes"
|
40
|
+
put:
|
41
|
+
tags:
|
42
|
+
- Users
|
43
|
+
summary: "Update User"
|
44
|
+
operationId: updateUser
|
45
|
+
parameters:
|
46
|
+
- $ref: "#/components/parameters/id"
|
47
|
+
responses:
|
48
|
+
"404":
|
49
|
+
description: "Not Found"
|
50
|
+
"200":
|
51
|
+
description: "OK"
|
52
|
+
content:
|
53
|
+
application/json:
|
54
|
+
schema:
|
55
|
+
$ref: "#/components/schemas/User::Parameters"
|
@@ -0,0 +1 @@
|
|
1
|
+
json.partial! "api/v1/platform/access_tokens/access_token", access_token: @access_token
|
@@ -0,0 +1,109 @@
|
|
1
|
+
en:
|
2
|
+
platform/access_tokens: &access_tokens
|
3
|
+
label: &label API Access Tokens
|
4
|
+
breadcrumbs:
|
5
|
+
label: *label
|
6
|
+
navigation:
|
7
|
+
label: *label
|
8
|
+
icon: fal fa-puzzle-piece
|
9
|
+
buttons: &buttons
|
10
|
+
new: Provision New Access Token
|
11
|
+
create: Create Access Token
|
12
|
+
edit: Edit Access Token
|
13
|
+
update: Update Access Token
|
14
|
+
destroy: Remove Access Token
|
15
|
+
shorthand:
|
16
|
+
edit: Edit
|
17
|
+
destroy: Delete
|
18
|
+
confirmations:
|
19
|
+
# TODO customize for your use-case.
|
20
|
+
destroy: Are you sure you want to remove %{access_token_name}? This will break any active integrations using this token and can't be undone.
|
21
|
+
fields: &fields
|
22
|
+
id:
|
23
|
+
heading: Access Token ID
|
24
|
+
application_id:
|
25
|
+
heading: Application ID
|
26
|
+
token:
|
27
|
+
_: &token Token
|
28
|
+
label: *token
|
29
|
+
heading: *token
|
30
|
+
expires_in:
|
31
|
+
_: &expires_in Expires In
|
32
|
+
label: *expires_in
|
33
|
+
heading: *expires_in
|
34
|
+
scopes:
|
35
|
+
_: &scopes Scopes
|
36
|
+
label: *scopes
|
37
|
+
heading: *scopes
|
38
|
+
last_used_at:
|
39
|
+
_: &last_used_at Last Used At
|
40
|
+
label: *last_used_at
|
41
|
+
heading: *last_used_at
|
42
|
+
description:
|
43
|
+
_: &description Description
|
44
|
+
label: *description
|
45
|
+
heading: *description
|
46
|
+
# 🚅 super scaffolding will insert new fields above this line.
|
47
|
+
created_at:
|
48
|
+
_: &created_at Created
|
49
|
+
label: *created_at
|
50
|
+
heading: *created_at
|
51
|
+
updated_at:
|
52
|
+
_: &updated_at Updated
|
53
|
+
label: *updated_at
|
54
|
+
heading: *updated_at
|
55
|
+
api:
|
56
|
+
collection_actions: "Collection Actions for Access Tokens"
|
57
|
+
index: "List Access Tokens"
|
58
|
+
create: "Add a New Access Token"
|
59
|
+
member_actions: "Actions for an Individual Access Token"
|
60
|
+
show: "Retrieve a Access Token"
|
61
|
+
update: "Update a Access Token"
|
62
|
+
destroy: "Delete a Access Token"
|
63
|
+
fields: *fields
|
64
|
+
index:
|
65
|
+
section: "%{applications_possessive} API Access Tokens"
|
66
|
+
contexts:
|
67
|
+
platform/application:
|
68
|
+
header: API Access Tokens
|
69
|
+
description: You can use Access Tokens to allow %{application_name} to make requests to the API.
|
70
|
+
fields: *fields
|
71
|
+
buttons: *buttons
|
72
|
+
show:
|
73
|
+
section: "%{access_token_name}"
|
74
|
+
header: Access Token Details
|
75
|
+
description: Below are the details we have for %{access_token_name}.
|
76
|
+
manage_description: You'll also find options for updating these details or removing %{access_token_name} from %{application_name} entirely.
|
77
|
+
fields: *fields
|
78
|
+
buttons: *buttons
|
79
|
+
form: &form
|
80
|
+
buttons: *buttons
|
81
|
+
fields: *fields
|
82
|
+
new:
|
83
|
+
section: "New Access Token for %{application_name}"
|
84
|
+
header: New Access Token Details
|
85
|
+
description: Please provide the details of the new Access Token you'd like to add to %{application_name}.
|
86
|
+
form: *form
|
87
|
+
edit:
|
88
|
+
section: "%{access_token_name}"
|
89
|
+
header: Edit Access Token Details
|
90
|
+
description: You can update the settings for %{access_token_name} below.
|
91
|
+
form: *form
|
92
|
+
notifications:
|
93
|
+
created: Access Token was successfully created.
|
94
|
+
updated: Access Token was successfully updated.
|
95
|
+
destroyed: Access Token was successfully destroyed.
|
96
|
+
account:
|
97
|
+
platform:
|
98
|
+
access_tokens: *access_tokens
|
99
|
+
activerecord:
|
100
|
+
attributes:
|
101
|
+
platform/access_token:
|
102
|
+
token: *token
|
103
|
+
expires_in: *expires_in
|
104
|
+
scopes: *scopes
|
105
|
+
last_used_at: *last_used_at
|
106
|
+
description: *description
|
107
|
+
# 🚅 super scaffolding will insert new activerecord attributes above this line.
|
108
|
+
created_at: *created_at
|
109
|
+
updated_at: *updated_at
|
@@ -7,7 +7,7 @@ en:
|
|
7
7
|
label: Your Applications
|
8
8
|
icon: fal fa-browser ti ti-plug
|
9
9
|
buttons: &buttons
|
10
|
-
new:
|
10
|
+
new: Provision New Platform Application
|
11
11
|
create: Provision Platform Application
|
12
12
|
edit: Edit Platform Application
|
13
13
|
update: Update Platform Application
|
@@ -18,7 +18,7 @@ en:
|
|
18
18
|
disconnect: Disconnect
|
19
19
|
confirmations:
|
20
20
|
# TODO customize for your use-case.
|
21
|
-
destroy: Are you sure you want to remove %{application_name}? This will
|
21
|
+
destroy: Are you sure you want to remove %{application_name}? This will break any integrations using this client UID and secret and any associated API access tokens. This can't be undone.
|
22
22
|
disconnect: Are you sure you want to disconnect %{application_name}? This might affect an ongoing service provided by %{application_name} and can not be undone.
|
23
23
|
fields: &fields
|
24
24
|
name:
|
@@ -26,17 +26,11 @@ en:
|
|
26
26
|
label: *name
|
27
27
|
heading: Application Name
|
28
28
|
|
29
|
-
scopes:
|
30
|
-
_: &scopes Scopes
|
31
|
-
label: *scopes
|
32
|
-
heading: *scopes
|
33
|
-
help: Scopes are like permissions. An OAuth application can have read, write, and/or delete access. Separate scopes with spaces. Leave this field blank to use the default scope, e.g. "read". Optional scopes are "write" and "delete".
|
34
|
-
|
35
29
|
redirect_uri:
|
36
30
|
_: &redirect_uri Redirect URI
|
37
31
|
label: *redirect_uri
|
38
32
|
heading: *redirect_uri
|
39
|
-
help:
|
33
|
+
help: This is only required if you're building an OAuth2-powered integration for other users.
|
40
34
|
|
41
35
|
uid:
|
42
36
|
heading: Client UID
|
@@ -61,15 +55,13 @@ en:
|
|
61
55
|
contexts:
|
62
56
|
team:
|
63
57
|
header: Platform Applications
|
64
|
-
description:
|
65
|
-
description_empty: No Platform Applications have been provisioned for %{team_name}.
|
58
|
+
description: Platform Applications allow you to build API integrations for %{team_name} or build OAuth2-powered integrations that %{team_name} can share with others.
|
66
59
|
fields: *fields
|
67
60
|
buttons: *buttons
|
68
61
|
show:
|
69
62
|
section: "%{application_name}"
|
70
63
|
header: Platform Application Details
|
71
|
-
description: Below
|
72
|
-
manage_description: You'll also find options for updating these details or removing %{application_name} from %{team_name} entirely.
|
64
|
+
description: Below is the configuration and OAuth2 credentials for %{application_name}.
|
73
65
|
fields: *fields
|
74
66
|
buttons: *buttons
|
75
67
|
form: &form
|
@@ -96,7 +88,6 @@ en:
|
|
96
88
|
attributes:
|
97
89
|
platform/application:
|
98
90
|
name: *name
|
99
|
-
scopes: *scopes
|
100
91
|
redirect_uri: *redirect_uri
|
101
92
|
# 🚅 super scaffolding will insert new activerecord attributes above this line.
|
102
93
|
created_at: *created_at
|
data/config/routes.rb
CHANGED
@@ -1,7 +1,25 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
use_doorkeeper
|
3
3
|
|
4
|
+
# See `config/routes.rb` in the starter repository for details.
|
5
|
+
collection_actions = [:index, :new, :create] # standard:disable Lint/UselessAssignment
|
6
|
+
extending = {only: []}
|
7
|
+
|
8
|
+
namespace :account do
|
9
|
+
shallow do
|
10
|
+
resources :teams, extending do
|
11
|
+
namespace :platform do
|
12
|
+
resources :applications do
|
13
|
+
resources :access_tokens
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
4
20
|
namespace :api do
|
21
|
+
match "*version/openapi.yaml" => "open_api#index", :via => :get
|
22
|
+
|
5
23
|
namespace :v1 do
|
6
24
|
shallow do
|
7
25
|
resources :users
|
@@ -9,7 +27,9 @@ Rails.application.routes.draw do
|
|
9
27
|
resources :invitations
|
10
28
|
resources :memberships
|
11
29
|
namespace :platform do
|
12
|
-
resources :applications
|
30
|
+
resources :applications do
|
31
|
+
resources :access_tokens
|
32
|
+
end
|
13
33
|
end
|
14
34
|
end
|
15
35
|
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.
|
4
|
+
version: 1.1.5
|
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-09-
|
11
|
+
date: 2022-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -120,11 +120,23 @@ files:
|
|
120
120
|
- README.md
|
121
121
|
- Rakefile
|
122
122
|
- app/assets/config/bullet_train_api_manifest.js
|
123
|
+
- app/controllers/account/platform/access_tokens_controller.rb
|
123
124
|
- app/controllers/account/platform/applications_controller.rb
|
125
|
+
- app/controllers/api/open_api_controller.rb
|
126
|
+
- app/controllers/api/v1/platform/access_tokens_controller.rb
|
124
127
|
- app/controllers/concerns/api/controllers/base.rb
|
125
128
|
- app/controllers/concerns/api/v1/teams/controller_base.rb
|
126
129
|
- app/controllers/concerns/api/v1/users/controller_base.rb
|
130
|
+
- app/models/platform/access_token.rb
|
127
131
|
- app/models/platform/application.rb
|
132
|
+
- app/views/account/platform/access_tokens/_breadcrumbs.html.erb
|
133
|
+
- app/views/account/platform/access_tokens/_form.html.erb
|
134
|
+
- app/views/account/platform/access_tokens/_index.html.erb
|
135
|
+
- app/views/account/platform/access_tokens/_menu_item.html.erb
|
136
|
+
- app/views/account/platform/access_tokens/edit.html.erb
|
137
|
+
- app/views/account/platform/access_tokens/index.html.erb
|
138
|
+
- app/views/account/platform/access_tokens/new.html.erb
|
139
|
+
- app/views/account/platform/access_tokens/show.html.erb
|
128
140
|
- app/views/account/platform/applications/_application.json.jbuilder
|
129
141
|
- app/views/account/platform/applications/_breadcrumbs.html.erb
|
130
142
|
- app/views/account/platform/applications/_form.html.erb
|
@@ -136,12 +148,19 @@ files:
|
|
136
148
|
- app/views/account/platform/applications/new.html.erb
|
137
149
|
- app/views/account/platform/applications/show.html.erb
|
138
150
|
- app/views/account/platform/applications/show.json.jbuilder
|
151
|
+
- app/views/api/v1/open_api/index.yaml.erb
|
152
|
+
- app/views/api/v1/open_api/teams/_paths.yaml.erb
|
153
|
+
- app/views/api/v1/open_api/users/_paths.yaml.erb
|
154
|
+
- app/views/api/v1/platform/access_tokens/_access_token.json.jbuilder
|
155
|
+
- app/views/api/v1/platform/access_tokens/index.json.jbuilder
|
156
|
+
- app/views/api/v1/platform/access_tokens/show.json.jbuilder
|
139
157
|
- app/views/api/v1/teams/index.json.jbuilder
|
140
158
|
- app/views/api/v1/teams/show.json.jbuilder
|
141
159
|
- app/views/api/v1/users/index.json.jbuilder
|
142
160
|
- app/views/api/v1/users/show.json.jbuilder
|
143
161
|
- config/locales/en/api.en.yml
|
144
162
|
- config/locales/en/me.en.yml
|
163
|
+
- config/locales/en/platform/access_tokens.en.yml
|
145
164
|
- config/locales/en/platform/applications.en.yml
|
146
165
|
- config/routes.rb
|
147
166
|
- lib/bullet_train/api.rb
|