bullet_train-api 1.0.0

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