bullet_train-api 1.0.0

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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/bullet_train_api_manifest.js +0 -0
  6. data/app/controllers/account/platform/applications_controller.rb +78 -0
  7. data/app/controllers/api/v1/defaults.rb +36 -0
  8. data/app/controllers/api/v1/exceptions_handler.rb +50 -0
  9. data/app/controllers/api/v1/loads_and_authorizes_api_resource.rb +42 -0
  10. data/app/controllers/api/v1/me_endpoint.rb +8 -0
  11. data/app/controllers/api/v1/root.rb +27 -0
  12. data/app/controllers/api/v1/teams_endpoint.rb +79 -0
  13. data/app/controllers/api/v1.rb +4 -0
  14. data/app/models/platform/application.rb +51 -0
  15. data/app/views/account/platform/applications/_application.json.jbuilder +10 -0
  16. data/app/views/account/platform/applications/_breadcrumbs.html.erb +8 -0
  17. data/app/views/account/platform/applications/_form.html.erb +20 -0
  18. data/app/views/account/platform/applications/_index.html.erb +64 -0
  19. data/app/views/account/platform/applications/_menu_item.html.erb +10 -0
  20. data/app/views/account/platform/applications/edit.html.erb +12 -0
  21. data/app/views/account/platform/applications/index.html.erb +6 -0
  22. data/app/views/account/platform/applications/index.json.jbuilder +1 -0
  23. data/app/views/account/platform/applications/new.html.erb +12 -0
  24. data/app/views/account/platform/applications/show.html.erb +31 -0
  25. data/app/views/account/platform/applications/show.json.jbuilder +1 -0
  26. data/config/locales/en/api.en.yml +13 -0
  27. data/config/locales/en/platform/applications.en.yml +103 -0
  28. data/config/routes.rb +2 -0
  29. data/lib/bullet_train/api/engine.rb +6 -0
  30. data/lib/bullet_train/api/version.rb +5 -0
  31. data/lib/bullet_train/api.rb +8 -0
  32. data/lib/tasks/bullet_train/api_tasks.rake +4 -0
  33. metadata +90 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e1a328cffebe8bbf05bf9d14df56afe1142c64cae544f63cc2a306fa1b999cd8
4
+ data.tar.gz: 6e0d56ea3c25db247665f92b2c443ab027ad2a14540307ae0e938b4a9ad890cd
5
+ SHA512:
6
+ metadata.gz: 417fb8b614b5a43313c63f1c12572a5ce26eb604412d04deccade31ba27b22974dd32c08791cb1aba0b5397ddba59d94874a131af11e77ea61080875dc85442c
7
+ data.tar.gz: dc17c6b4d31ef02c167da2f69262794960e7cd4e1d8bc96142109262c9326a73f7e0cb77998a6854df0eb0cb2c87f1119f4a6ba257c9675beed3a2b487997ca7
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Andrew Culver
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # BulletTrain::Api
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem "bullet_train-api"
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install bullet_train-api
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
File without changes
@@ -0,0 +1,78 @@
1
+ class Account::Platform::ApplicationsController < Account::ApplicationController
2
+ account_load_and_authorize_resource :application, through: :team, through_association: :platform_applications
3
+
4
+ # GET /account/teams/:team_id/platform/applications
5
+ # GET /account/teams/:team_id/platform/applications.json
6
+ def index
7
+ # if you only want these objects shown on their parent's show page, uncomment this:
8
+ # redirect_to [:account, @team]
9
+ end
10
+
11
+ # GET /account/platform/applications/:id
12
+ # GET /account/platform/applications/:id.json
13
+ def show
14
+ end
15
+
16
+ # GET /account/teams/:team_id/platform/applications/new
17
+ def new
18
+ end
19
+
20
+ # GET /account/platform/applications/:id/edit
21
+ def edit
22
+ end
23
+
24
+ # POST /account/teams/:team_id/platform/applications
25
+ # POST /account/teams/:team_id/platform/applications.json
26
+ def create
27
+ respond_to do |format|
28
+ if @application.save
29
+ format.html { redirect_to [:account, @team, :platform_applications], notice: I18n.t("platform/applications.notifications.created") }
30
+ format.json { render :show, status: :created, location: [:account, @application] }
31
+ else
32
+ format.html { render :new, status: :unprocessable_entity }
33
+ format.json { render json: @application.errors, status: :unprocessable_entity }
34
+ end
35
+ end
36
+ end
37
+
38
+ # PATCH/PUT /account/platform/applications/:id
39
+ # PATCH/PUT /account/platform/applications/:id.json
40
+ def update
41
+ respond_to do |format|
42
+ if @application.update(application_params)
43
+ format.html { redirect_to [:account, @application], notice: I18n.t("platform/applications.notifications.updated") }
44
+ format.json { render :show, status: :ok, location: [:account, @application] }
45
+ else
46
+ format.html { render :edit, status: :unprocessable_entity }
47
+ format.json { render json: @application.errors, status: :unprocessable_entity }
48
+ end
49
+ end
50
+ end
51
+
52
+ # DELETE /account/platform/applications/:id
53
+ # DELETE /account/platform/applications/:id.json
54
+ def destroy
55
+ @application.destroy
56
+ respond_to do |format|
57
+ format.html { redirect_to [:account, @team, :platform_applications], notice: I18n.t("platform/applications.notifications.destroyed") }
58
+ format.json { head :no_content }
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ # Never trust parameters from the scary internet, only allow the white list through.
65
+ def application_params
66
+ strong_params = params.require(:platform_application).permit(
67
+ :name,
68
+ :scopes,
69
+ :redirect_uri,
70
+ # 🚅 super scaffolding will insert new fields above this line.
71
+ # 🚅 super scaffolding will insert new arrays above this line.
72
+ )
73
+
74
+ # 🚅 super scaffolding will insert processing for new fields above this line.
75
+
76
+ strong_params
77
+ end
78
+ end
@@ -0,0 +1,36 @@
1
+ module Api::V1::Defaults
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before do
6
+ header["Access-Control-Allow-Origin"] = "*"
7
+ header["Access-Control-Request-Method"] = "*"
8
+ end
9
+
10
+ helpers do
11
+ def current_token
12
+ doorkeeper_access_token
13
+ end
14
+
15
+ def current_user
16
+ resource_owner
17
+ end
18
+
19
+ def current_scopes
20
+ current_token.scopes
21
+ end
22
+
23
+ def current_team
24
+ current_user.current_team
25
+ end
26
+
27
+ def current_membership
28
+ current_user.memberships.where(team: current_team).first
29
+ end
30
+
31
+ def current_locale
32
+ current_user.locale || current_team.locale || "en"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,50 @@
1
+ module Api::V1::ExceptionsHandler
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ helpers do
6
+ def record_not_saved(model)
7
+ handle_api_error(ActiveRecord::RecordNotSaved.new(model.errors.full_messages.first), :unprocessable_entity)
8
+ end
9
+
10
+ def handle_api_error(error, status = nil)
11
+ error!("Something rather unexpected has occurred", 500) unless error
12
+
13
+ error_class = error.class.name
14
+ status_code = convert_status_symbol_to_integer(status) if status # allows an explicit status to be defined
15
+
16
+ message = error.message # works fine for most errors
17
+ message = "OAuth error: #{error}" if /WineBouncer::Errors/.match?(error_class)
18
+ message = "Route error: #{error}" if /CanCan::AccessDenied/.match?(error_class)
19
+
20
+ if /OAuthUnauthorizedError/.match?(error_class)
21
+ error!(message, status_code || 401) # unauthorized
22
+ elsif /OAuthForbiddenError/.match?(error_class) || /CanCan::AccessDenied/.match?(error_class)
23
+ error!(message, status_code || 403) # forbidden
24
+ elsif /RecordNotFound/.match?(error_class) || /unable to find/i.match?(message)
25
+ error!(message, status_code || 404) # not found
26
+ elsif /Grape::Exceptions::ValidationErrors/.match?(error_class)
27
+ error!(message, status_code || 406) # not acceptable
28
+ else
29
+ Rails.logger.error message unless Rails.env.test?
30
+
31
+ options = {error: message}
32
+ options[:trace] = error.backtrace[0, 10] unless Rails.env.production?
33
+
34
+ status_code = status_code || error.try(:status) || 500 # internal server error
35
+
36
+ Rack::Response.new(options.to_json, status_code, {
37
+ "Content-Type" => "application/json",
38
+ "Access-Control-Allow-Origin" => "*",
39
+ "Access-Control-Request-Method" => "*"
40
+ }).finish
41
+ end
42
+ end
43
+
44
+ def convert_status_symbol_to_integer(status)
45
+ # defaults to an internal server error if the status code can't be found
46
+ Rack::Utils::SYMBOL_TO_STATUS_CODE[status] || 500
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ module Api::V1::LoadsAndAuthorizesApiResource
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ helpers do
6
+ def load_and_authorize_api_resource(api_resource_class)
7
+ raise unless api_resource_class.present?
8
+
9
+ instance_variable_name = "@#{api_resource_class.name.demodulize.underscore}"
10
+ instance_variable_collection_name = instance_variable_name.pluralize
11
+
12
+ options = route.settings[:api_resource_options] || {permission: :read, skip_authorize: false}
13
+
14
+ permission = options[:permission]
15
+ skip_authorize = options[:skip_authorize]
16
+
17
+ api_resource_params = declared(params, include_missing: false)
18
+ api_resource_param_id = api_resource_params[:id]
19
+ api_resource_params_other_ids = api_resource_params.select { |param, value|
20
+ /_id$/i.match?(param)
21
+ }
22
+
23
+ all_accessible_api_resources = api_resource_class.accessible_by(current_ability, permission)
24
+
25
+ if api_resource_param_id.present? # :read, :update, :delete
26
+ instance_variable_set(instance_variable_name, all_accessible_api_resources.find(api_resource_param_id))
27
+ elsif permission.eql? :create
28
+ instance_variable_set(instance_variable_name, api_resource_class.new(api_resource_params))
29
+ elsif permission.eql? :read
30
+ all_accessible_api_resources = all_accessible_api_resources.where(api_resource_params_other_ids) if api_resource_params_other_ids.present?
31
+ instance_variable_set(instance_variable_collection_name, all_accessible_api_resources)
32
+ skip_authorize = true # can't use CanCan to authorize collections
33
+ end
34
+
35
+ eval "authorize! :#{permission}, #{instance_variable_name}" unless skip_authorize
36
+ rescue ActiveRecord::RecordNotFound
37
+ # the default RecordNotFound message includes the raw SQL... which feels bad
38
+ handle_api_error(ActiveRecord::RecordNotFound.new("The id #{api_resource_param_id} could not be found."))
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,8 @@
1
+ class Api::V1::MeEndpoint < Api::V1::Root
2
+ resource :me do
3
+ oauth2
4
+ get "/" do
5
+ render Api::V1::UserSerializer.new(current_user, include: [:teams, :memberships]).to_json
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ class Api::V1::Root < Api::Base
2
+ include Api::V1::Defaults
3
+ include Api::V1::LoadsAndAuthorizesApiResource
4
+
5
+ version "v1"
6
+ use ::WineBouncer::OAuth2
7
+
8
+ rescue_from :all do |error|
9
+ handle_api_error(error)
10
+ end
11
+
12
+ unless scaffolding_things_disabled?
13
+ mount Api::V1::Scaffolding::AbsolutelyAbstract::CreativeConceptsEndpoint
14
+ mount Api::V1::Scaffolding::CompletelyConcrete::TangibleThingsEndpoint
15
+ end
16
+
17
+ mount Api::V1::MeEndpoint
18
+ mount Api::V1::TeamsEndpoint
19
+ mount Api::V1::Webhooks::Outgoing::EndpointsEndpoint
20
+ mount Api::V1::Webhooks::Outgoing::DeliveriesEndpoint
21
+ mount Api::V1::Webhooks::Outgoing::DeliveryAttemptsEndpoint
22
+ # 🚅 super scaffolding will mount new endpoints above this line.
23
+
24
+ route :any, "*path" do
25
+ raise StandardError, "Unable to find API endpoint"
26
+ end
27
+ end
@@ -0,0 +1,79 @@
1
+ class Api::V1::TeamsEndpoint < Api::V1::Root
2
+ helpers do
3
+ params :id do
4
+ requires :id, type: Integer, allow_blank: false, desc: Api.heading(:id)
5
+ end
6
+
7
+ params :team do
8
+ optional :name, type: String, allow_blank: false, desc: Api.heading(:name)
9
+ optional :locale, type: String, desc: Api.heading(:locale)
10
+ # 🚅 super scaffolding will insert new fields above this line.
11
+ # 🚅 super scaffolding will insert new arrays above this line.
12
+
13
+ # 🚅 super scaffolding will insert processing for new fields above this line.
14
+ end
15
+ end
16
+
17
+ resource :teams, desc: Api.title(:actions) do
18
+ after_validation do
19
+ load_and_authorize_api_resource Team
20
+ end
21
+
22
+ desc Api.title(:index), &Api.index_desc
23
+ oauth2
24
+ paginate per_page: 100
25
+ get "/" do
26
+ @paginated_teams = paginate @teams
27
+ render @paginated_teams, serializer: Api.serializer, adapter: :attributes
28
+ end
29
+
30
+ desc Api.title(:show), &Api.show_desc
31
+ params do
32
+ use :id
33
+ end
34
+ oauth2
35
+ route_param :id do
36
+ get do
37
+ render @team, serializer: Api.serializer
38
+ end
39
+ end
40
+
41
+ desc Api.title(:create), &Api.create_desc
42
+ params do
43
+ use :team
44
+ end
45
+ route_setting :api_resource_options, permission: :create
46
+ oauth2 "write"
47
+ post "/" do
48
+ if @team.save
49
+ # sets the team creator as the default admin
50
+ @team.memberships.create(user: current_user, roles: [Role.admin])
51
+
52
+ current_user.current_team = @team
53
+ current_user.former_user = false
54
+ current_user.save
55
+
56
+ render @team, serializer: Api.serializer
57
+ else
58
+ record_not_saved @team
59
+ end
60
+ end
61
+
62
+ desc Api.title(:update), &Api.update_desc
63
+ params do
64
+ use :id
65
+ use :team
66
+ end
67
+ route_setting :api_resource_options, permission: :update
68
+ oauth2 "write"
69
+ route_param :id do
70
+ put do
71
+ if @team.update(declared(params, include_missing: false))
72
+ render @team, serializer: Api.serializer
73
+ else
74
+ record_not_saved @team
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,4 @@
1
+ require "api"
2
+
3
+ module Api::V1
4
+ end
@@ -0,0 +1,51 @@
1
+ class Platform::Application < ApplicationRecord
2
+ self.table_name = "oauth_applications"
3
+
4
+ include Doorkeeper::Orm::ActiveRecord::Mixins::Application
5
+ # 🚅 add concerns above.
6
+
7
+ belongs_to :team
8
+ # 🚅 add belongs_to associations above.
9
+
10
+ # 🚅 add has_many associations above.
11
+
12
+ # 🚅 add oauth providers above.
13
+
14
+ has_one :membership, foreign_key: :platform_agent_of_id, dependent: :nullify
15
+ has_one :user, foreign_key: :platform_agent_of_id
16
+ # 🚅 add has_one associations above.
17
+
18
+ # 🚅 add scopes above.
19
+
20
+ # 🚅 add validations above.
21
+
22
+ after_create :create_user_and_membership
23
+ after_update :update_user_and_membership
24
+ before_destroy :destroy_user
25
+ # 🚅 add callbacks above.
26
+
27
+ # 🚅 add delegations above.
28
+
29
+ def label_string
30
+ name
31
+ end
32
+
33
+ def create_user_and_membership
34
+ faux_password = SecureRandom.hex
35
+ create_user(email: "noreply+#{SecureRandom.hex}@bullettrain.co", password: faux_password, password_confirmation: faux_password, first_name: label_string)
36
+ create_membership(team: team, user: user)
37
+ membership.roles << Role.admin
38
+ end
39
+
40
+ def update_user_and_membership
41
+ user.update(first_name: label_string)
42
+ end
43
+
44
+ def destroy_user
45
+ former_user = membership.user
46
+ membership.nullify_user
47
+ former_user.destroy
48
+ end
49
+
50
+ # 🚅 add methods above.
51
+ end
@@ -0,0 +1,10 @@
1
+ json.extract! application,
2
+ :id,
3
+ :team_id,
4
+ :name,
5
+ :scopes,
6
+ :redirect_uri,
7
+ # 🚅 super scaffolding will insert new fields above this line.
8
+ :created_at,
9
+ :updated_at
10
+ json.url account_platform_application_url(application, format: :json)
@@ -0,0 +1,8 @@
1
+ <% application ||= @application %>
2
+ <% team ||= @team || application&.team %>
3
+ <%= render 'account/teams/breadcrumbs', team: team %>
4
+ <%= render 'account/shared/breadcrumb', label: t('.label'), url: [:account, team, :platform_applications] %>
5
+ <% if application&.persisted? %>
6
+ <%= render 'account/shared/breadcrumb', label: application.label_string, url: [:account, application] %>
7
+ <% end %>
8
+ <%= render 'account/shared/breadcrumbs/actions', only_for: 'platform/applications' %>
@@ -0,0 +1,20 @@
1
+ <%= form_with model: application, url: (application.persisted? ? [:account, application] : [:account, @team, :platform_applications]), 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: :name, options: {autofocus: true} %>
6
+ <%= render 'shared/fields/text_field', method: :scopes %>
7
+ <%= render 'shared/fields/text_field', method: :redirect_uri %>
8
+ <%# 🚅 super scaffolding will insert new fields above this line. %>
9
+ <% end %>
10
+
11
+ <div class="buttons">
12
+ <%= form.submit (form.object.persisted? ? t('.buttons.update') : t('.buttons.create')), class: "button" %>
13
+ <% if form.object.persisted? %>
14
+ <%= link_to t('global.buttons.cancel'), [:account, application], class: "button-secondary" %>
15
+ <% else %>
16
+ <%= link_to t('global.buttons.cancel'), [:account, @team, :platform_applications], class: "button-secondary" %>
17
+ <% end %>
18
+ </div>
19
+
20
+ <% end %>
@@ -0,0 +1,64 @@
1
+ <% team = @team || @team %>
2
+ <% context ||= team %>
3
+ <% collection ||= :platform_applications %>
4
+ <% hide_actions ||= false %>
5
+ <% hide_back ||= false %>
6
+
7
+ <%= render 'account/shared/box' do |p| %>
8
+ <% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
9
+ <% p.content_for :description do %>
10
+ <%= t(".contexts.#{context.class.name.underscore}.description#{"_empty" unless applications.any?}") %>
11
+ <% end %>
12
+
13
+ <% p.content_for :table do %>
14
+ <% if applications.any? %>
15
+ <table class="table">
16
+ <thead>
17
+ <tr>
18
+ <th><%= t('.fields.name.heading') %></th>
19
+ <th><%= t('.fields.scopes.heading') %></th>
20
+ <%# 🚅 super scaffolding will insert new field headers above this line. %>
21
+ <th><%= t('.fields.created_at.heading') %></th>
22
+ <th class="text-right"></th>
23
+ </tr>
24
+ </thead>
25
+ <tbody>
26
+ <% applications.each do |application| %>
27
+ <% with_attribute_settings object: application do %>
28
+ <tr data-id="<%= application.id %>">
29
+ <td><%= render 'shared/attributes/text', attribute: :name, url: [:account, application] %></td>
30
+ <td><%= render 'shared/attributes/text', attribute: :scopes %></td>
31
+ <%# 🚅 super scaffolding will insert new fields above this line. %>
32
+ <td><%= display_date_and_time(application.created_at) %></td>
33
+ <td class="buttons">
34
+ <% unless hide_actions %>
35
+ <% if can? :edit, application %>
36
+ <%= link_to t('.buttons.shorthand.edit'), [:edit, :account, application], class: 'button-secondary button-smaller' %>
37
+ <% end %>
38
+ <% if can? :destroy, application %>
39
+ <%= button_to t('.buttons.shorthand.destroy'), [:account, application], method: :delete, data: { confirm: t('.buttons.confirmations.destroy', model_locales(application)) }, class: 'button-secondary button-smaller' %>
40
+ <% end %>
41
+ <% end %>
42
+ </td>
43
+ </tr>
44
+ <% end %>
45
+ <% end %>
46
+ </tbody>
47
+ </table>
48
+ <% end %>
49
+ <% end %>
50
+
51
+ <% p.content_for :actions do %>
52
+ <% unless hide_actions %>
53
+ <% if context == team %>
54
+ <% if can? :create, Platform::Application.new(team: team) %>
55
+ <%= link_to t('.buttons.new'), [:new, :account, team, :platform_application], class: "#{first_button_primary(:platform_application)} new" %>
56
+ <% end %>
57
+ <% end %>
58
+
59
+ <% unless hide_back %>
60
+ <%= link_to t('global.buttons.back'), [:account, context], class: "#{first_button_primary(:platform_application)} back" %>
61
+ <% end %>
62
+ <% end %>
63
+ <% end %>
64
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <% if can? :read, Platform::Application.new(team: current_team) %>
2
+ <%= render 'account/shared/menu/item', {
3
+ url: main_app.polymorphic_path([:account, current_team, :platform_applications]),
4
+ label: t('platform/applications.navigation.label'),
5
+ } do |p| %>
6
+ <% p.content_for :icon do %>
7
+ <i class="<%= t('platform/applications.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', application: @application %>
9
+ <% end %>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <%= render 'account/shared/page' do |p| %>
2
+ <% p.content_for :title, t('.section') %>
3
+ <% p.content_for :body do %>
4
+ <%= render 'index', applications: @applications %>
5
+ <% end %>
6
+ <% end %>
@@ -0,0 +1 @@
1
+ json.array! @applications, partial: "platform/applications/application", as: :application
@@ -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', application: @application %>
9
+ <% end %>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
@@ -0,0 +1,31 @@
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 do %>
7
+ <%= t('.description') %>
8
+ <%= t('.manage_description') if can? :manage, @application %>
9
+ <% end %>
10
+
11
+ <% p.content_for :body do %>
12
+ <% with_attribute_settings object: @application, strategy: :label do %>
13
+ <%= render 'shared/attributes/text', attribute: :name %>
14
+ <%= render 'shared/attributes/code', attribute: :uid %>
15
+ <%= render 'shared/attributes/code', attribute: :secret %>
16
+ <%= render 'shared/attributes/text', attribute: :scopes %>
17
+ <%= render 'shared/attributes/text', attribute: :redirect_uri %>
18
+ <%# 🚅 super scaffolding will insert new fields above this line. %>
19
+ <% end %>
20
+ <% end %>
21
+
22
+ <% p.content_for :actions do %>
23
+ <%= link_to t('.buttons.edit'), [:edit, :account, @application], class: first_button_primary if can? :edit, @application %>
24
+ <%= button_to t('.buttons.destroy'), [:account, @application], method: :delete, class: first_button_primary, data: { confirm: t('.buttons.confirmations.destroy', model_locales(@application)) } if can? :destroy, @application %>
25
+ <%= link_to t('global.buttons.back'), [:account, @team, :platform_applications], class: first_button_primary %>
26
+ <% end %>
27
+ <% end %>
28
+
29
+ <%# 🚅 super scaffolding will insert new children above this line. %>
30
+ <% end %>
31
+ <% end %>
@@ -0,0 +1 @@
1
+ json.partial! "platform/applications/application", application: @application
@@ -0,0 +1,13 @@
1
+ en:
2
+ api:
3
+ statuses:
4
+ 200: "Success" # okay
5
+ 201: "Success" # created
6
+ 400: "Missing or Bad Parameters" # bad request
7
+ 401: "Not Authorized" # unauthorized
8
+ 403: "Permission Denied" # forbidden
9
+ 404: "Record Not Found" # not found
10
+ 406: "Validation Errors" # not acceptable
11
+ 422: "Record Not Saved" # unprocessable entity
12
+ 429: "API Rate Limit Exceeded" # too many requests
13
+ 500: "Internal Server Error" # internal server error
@@ -0,0 +1,103 @@
1
+ en:
2
+ platform/applications: &applications
3
+ label: &label Platform Applications
4
+ breadcrumbs:
5
+ label: *label
6
+ navigation:
7
+ label: Your Applications
8
+ icon: fal fa-browser ti ti-plug
9
+ buttons: &buttons
10
+ new: Add New Platform Application
11
+ create: Provision Platform Application
12
+ edit: Edit Platform Application
13
+ update: Update Platform Application
14
+ destroy: Remove Platform Application
15
+ shorthand:
16
+ edit: Edit
17
+ destroy: Delete
18
+ disconnect: Disconnect
19
+ confirmations:
20
+ # TODO customize for your use-case.
21
+ destroy: Are you sure you want to remove %{application_name}? This will also remove it's associated data. This can't be undone.
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
+ fields: &fields
24
+ name:
25
+ _: &name Name
26
+ label: *name
27
+ heading: Application Name
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
+ redirect_uri:
36
+ _: &redirect_uri Redirect URI
37
+ label: *redirect_uri
38
+ heading: *redirect_uri
39
+ help: You can leave this field blank.
40
+
41
+ uid:
42
+ heading: Client UID
43
+
44
+ secret:
45
+ heading: Client Secret
46
+
47
+ label_string:
48
+ heading: Application Name
49
+
50
+ # 🚅 super scaffolding will insert new fields above this line.
51
+ created_at:
52
+ _: &created_at Added
53
+ label: *created_at
54
+ heading: *created_at
55
+ updated_at:
56
+ _: &updated_at Updated
57
+ label: *updated_at
58
+ heading: *updated_at
59
+ index:
60
+ section: "%{teams_possessive} Platform Applications"
61
+ contexts:
62
+ team:
63
+ header: Platform Applications
64
+ description: Below is a list of Platform Applications that have been provisioned for %{team_name}.
65
+ description_empty: No Platform Applications have been provisioned for %{team_name}.
66
+ fields: *fields
67
+ buttons: *buttons
68
+ show:
69
+ section: "%{application_name}"
70
+ header: Platform Application Details
71
+ description: Below are the details we have for %{application_name}.
72
+ manage_description: You'll also find options for updating these details or removing %{application_name} from %{team_name} entirely.
73
+ fields: *fields
74
+ buttons: *buttons
75
+ form: &form
76
+ buttons: *buttons
77
+ fields: *fields
78
+ new:
79
+ section: "New Platform Application for %{team_name}"
80
+ header: New Platform Application Details
81
+ description: Please provide the details of the new Platform Application you'd like to provision for %{team_name}.
82
+ form: *form
83
+ edit:
84
+ section: "%{application_name}"
85
+ header: Edit Platform Application Details
86
+ description: You can update the details or settings for %{application_name} below.
87
+ form: *form
88
+ notifications:
89
+ created: Platform Application was successfully created.
90
+ updated: Platform Application was successfully updated.
91
+ destroyed: Platform Application was successfully destroyed.
92
+ account:
93
+ platform:
94
+ applications: *applications
95
+ activerecord:
96
+ attributes:
97
+ platform/application:
98
+ name: *name
99
+ scopes: *scopes
100
+ redirect_uri: *redirect_uri
101
+ # 🚅 super scaffolding will insert new activerecord attributes above this line.
102
+ created_at: *created_at
103
+ updated_at: *updated_at
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,6 @@
1
+ module BulletTrain
2
+ module Api
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module BulletTrain
2
+ module Api
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require "bullet_train/api/version"
2
+ require "bullet_train/api/engine"
3
+
4
+ module BulletTrain
5
+ module Api
6
+ # Your code goes here...
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :bullet_train_api do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bullet_train-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Culver
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.0
27
+ description: Bullet Train API
28
+ email:
29
+ - andrew.culver@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/assets/config/bullet_train_api_manifest.js
38
+ - app/controllers/account/platform/applications_controller.rb
39
+ - app/controllers/api/v1.rb
40
+ - app/controllers/api/v1/defaults.rb
41
+ - app/controllers/api/v1/exceptions_handler.rb
42
+ - app/controllers/api/v1/loads_and_authorizes_api_resource.rb
43
+ - app/controllers/api/v1/me_endpoint.rb
44
+ - app/controllers/api/v1/root.rb
45
+ - app/controllers/api/v1/teams_endpoint.rb
46
+ - app/models/platform/application.rb
47
+ - app/views/account/platform/applications/_application.json.jbuilder
48
+ - app/views/account/platform/applications/_breadcrumbs.html.erb
49
+ - app/views/account/platform/applications/_form.html.erb
50
+ - app/views/account/platform/applications/_index.html.erb
51
+ - app/views/account/platform/applications/_menu_item.html.erb
52
+ - app/views/account/platform/applications/edit.html.erb
53
+ - app/views/account/platform/applications/index.html.erb
54
+ - app/views/account/platform/applications/index.json.jbuilder
55
+ - app/views/account/platform/applications/new.html.erb
56
+ - app/views/account/platform/applications/show.html.erb
57
+ - app/views/account/platform/applications/show.json.jbuilder
58
+ - config/locales/en/api.en.yml
59
+ - config/locales/en/platform/applications.en.yml
60
+ - config/routes.rb
61
+ - lib/bullet_train/api.rb
62
+ - lib/bullet_train/api/engine.rb
63
+ - lib/bullet_train/api/version.rb
64
+ - lib/tasks/bullet_train/api_tasks.rake
65
+ homepage: https://github.com/bullet-train-co/bullet_train-api
66
+ licenses:
67
+ - MIT
68
+ metadata:
69
+ homepage_uri: https://github.com/bullet-train-co/bullet_train-api
70
+ source_code_uri: https://github.com/bullet-train-co/bullet_train-api
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 3.2.22
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Bullet Train API
90
+ test_files: []