beyond_canvas 0.14.0.pre → 0.16.0.pre

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -6
  3. data/app/assets/images/icons/checkbox_checked.svg +1 -0
  4. data/app/assets/images/icons/checkbox_unchecked.svg +1 -0
  5. data/app/assets/images/icons/radiobutton_checked.svg +1 -0
  6. data/app/assets/images/icons/radiobutton_unchecked.svg +1 -0
  7. data/app/assets/javascripts/beyond_canvas/base.js +248 -87
  8. data/app/assets/stylesheets/beyond_canvas/base.scss +3 -0
  9. data/app/assets/stylesheets/beyond_canvas/components/_containers.scss +37 -0
  10. data/app/assets/stylesheets/beyond_canvas/components/_inputs.scss +47 -1
  11. data/app/assets/stylesheets/beyond_canvas/settings/_breakpoints.scss +6 -0
  12. data/app/assets/stylesheets/beyond_canvas/settings/_variables.scss +24 -0
  13. data/app/assets/stylesheets/beyond_canvas/utilities/_functions.scss +15 -0
  14. data/app/controllers/beyond_canvas/authentications_controller.rb +62 -0
  15. data/app/controllers/concerns/beyond_canvas/authentication.rb +24 -0
  16. data/app/controllers/concerns/beyond_canvas/request_validation.rb +1 -1
  17. data/app/controllers/concerns/beyond_canvas/resource_management.rb +33 -0
  18. data/app/form_builders/beyond_canvas/form_builder.rb +65 -8
  19. data/app/javascript/beyond_canvas/base.js +3 -6
  20. data/app/javascript/beyond_canvas/initializers/buttons.js +21 -39
  21. data/app/javascript/beyond_canvas/initializers/flash.js +5 -14
  22. data/app/javascript/beyond_canvas/initializers/functions.js +41 -0
  23. data/app/javascript/beyond_canvas/initializers/inputs.js +3 -8
  24. data/app/views/beyond_canvas/authentications/new.html.erb +18 -0
  25. data/config/locales/en.yml +4 -0
  26. data/config/routes.rb +6 -0
  27. data/lib/beyond_canvas.rb +22 -2
  28. data/lib/beyond_canvas/configuration.rb +4 -1
  29. data/lib/beyond_canvas/engine.rb +4 -0
  30. data/lib/beyond_canvas/models/authentication.rb +66 -0
  31. data/lib/beyond_canvas/models/shop.rb +28 -0
  32. data/lib/beyond_canvas/models/utils.rb +55 -0
  33. data/lib/beyond_canvas/parameter_sanitizer.rb +43 -0
  34. data/lib/beyond_canvas/rails/routes.rb +21 -0
  35. data/lib/beyond_canvas/version.rb +1 -1
  36. data/lib/generators/beyond_canvas/auth_model/auth_model_generator.rb +50 -0
  37. data/lib/generators/beyond_canvas/auth_model/templates/migration.erb +20 -0
  38. data/lib/generators/beyond_canvas/auth_model/templates/model.erb +5 -0
  39. data/lib/generators/beyond_canvas/controller/controller_generator.rb +20 -0
  40. data/lib/generators/beyond_canvas/controller/templates/controller.erb +37 -0
  41. data/lib/generators/beyond_canvas/install/install_generator.rb +15 -5
  42. data/lib/generators/beyond_canvas/install/templates/beyond_canvas.rb.erb +11 -0
  43. data/lib/generators/beyond_canvas/views/views_generator.rb +19 -0
  44. metadata +58 -6
@@ -1,4 +1,4 @@
1
- (function($) {
1
+ (function ($) {
2
2
  const onDOMReady = function () {
3
3
  $('input[type="file"]').each(function () {
4
4
  var $input = $(this),
@@ -9,10 +9,7 @@
9
9
  var fileName = '';
10
10
 
11
11
  if (this.files && this.files.length > 1)
12
- fileName = (this.getAttribute('data-multiple-caption') || '').replace(
13
- '{count}',
14
- this.files.length
15
- );
12
+ fileName = (this.getAttribute('data-multiple-caption') || '').replace('{count}', this.files.length);
16
13
  else if (e.target.value) fileName = e.target.value.split('\\').pop();
17
14
 
18
15
  if (fileName)
@@ -33,7 +30,5 @@
33
30
  });
34
31
  };
35
32
 
36
- $(document)
37
- .ready(onDOMReady)
38
- .on('ready page:load turbolinks:load', onDOMReady);
33
+ $(document).on('ready page:load turbolinks:load', onDOMReady);
39
34
  })(jQuery);
@@ -0,0 +1,18 @@
1
+ <div class='card card--padding'>
2
+
3
+ <%= form_for(resource, as: resource_name) do |f| %>
4
+
5
+ <h2 class='card__headline'>Install <%= BeyondCanvas.configuration.site_title %> in your shop</h2>
6
+
7
+ <%= f.hidden_field :code, value: params[:code] || resource.code %>
8
+ <%= f.hidden_field :signature, value: params[:signature] || resource.signature %>
9
+ <%= f.hidden_field :return_url, value: params[:return_url] || resource.return_url %>
10
+ <%= f.hidden_field :api_url, value: params[:api_url] || resource.api_url %>
11
+ <%= f.hidden_field :access_token_url, value: params[:access_token_url] || resource.access_token_url %>
12
+
13
+ <div class='form__actions--spaced'>
14
+ <%= f.button 'Save', type: :submit, class: 'button__solid--primary' %>
15
+ </div>
16
+
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,4 @@
1
+ en:
2
+ beyond_canvas:
3
+ authentications:
4
+ failure: Shop could not be saved
@@ -2,4 +2,10 @@
2
2
 
3
3
  BeyondCanvas::Engine.routes.draw do
4
4
  put '/locale', to: 'system#update_locale', as: :update_locale
5
+
6
+ def create_default_routes(resource_name)
7
+ resources resource_name, controller: 'authentications', except: :destroy
8
+ end
9
+
10
+ create_default_routes(BeyondCanvas.auth_model.pluralize.to_sym) unless BeyondCanvas.use_rails_app_controller
5
11
  end
@@ -12,10 +12,30 @@ require 'http/accept'
12
12
  require 'premailer/rails'
13
13
 
14
14
  require 'beyond_api'
15
+ require 'attr_encrypted'
16
+ require 'blind_index'
15
17
 
16
18
  module BeyondCanvas # :nodoc:
17
- autoload :AssetRegistration, 'beyond_canvas/asset_registration'
18
- autoload :Configuration, 'beyond_canvas/configuration'
19
+ autoload :AssetRegistration, 'beyond_canvas/asset_registration'
20
+ autoload :Configuration, 'beyond_canvas/configuration'
21
+
22
+ module Models # :nodoc:
23
+ autoload :Authentication, 'beyond_canvas/models/authentication'
24
+ autoload :Shop, 'beyond_canvas/models/shop'
25
+ autoload :Utils, 'beyond_canvas/models/utils'
26
+ end
27
+
28
+ autoload :ParameterSanitizer, 'beyond_canvas/parameter_sanitizer'
29
+
30
+ mattr_accessor :use_rails_app_controller
31
+ @@use_rails_app_controller = false # rubocop:disable Style/ClassVars
32
+
33
+ mattr_accessor :auth_model
34
+ @@auth_model = 'shop' # rubocop:disable Style/ClassVars
35
+
36
+ def self.use_rails_app_controller=(value)
37
+ @use_rails_app_controller = value
38
+ end
19
39
 
20
40
  class << self
21
41
  def configuration
@@ -2,7 +2,7 @@
2
2
 
3
3
  module BeyondCanvas
4
4
  class Configuration # :nodoc:
5
- attr_accessor :site_title, :site_logo, :favicon, :skip_webpacker
5
+ attr_accessor :site_title, :site_logo, :favicon, :skip_webpacker, :encryption_key, :blind_index_key, :namespace
6
6
 
7
7
  include AssetRegistration
8
8
 
@@ -11,6 +11,9 @@ module BeyondCanvas
11
11
  @site_logo = nil
12
12
  @favicon = nil
13
13
  @skip_webpacker = false
14
+ @encryption_key = nil
15
+ @blind_index_key = nil
16
+ @namespace = '/'
14
17
  end
15
18
 
16
19
  def setup!
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'beyond_canvas/rails/routes'
4
+
3
5
  module BeyondCanvas
4
6
  class Engine < ::Rails::Engine # :nodoc:
5
7
  isolate_namespace BeyondCanvas
@@ -15,7 +17,9 @@ module BeyondCanvas
15
17
 
16
18
  config.before_initialize do
17
19
  ActiveSupport.on_load :action_controller do
20
+ include ::BeyondCanvas::Authentication
18
21
  include ::BeyondCanvas::LocaleManagement
22
+ include ::BeyondCanvas::ResourceManagement
19
23
  include ::BeyondCanvas::RequestValidation
20
24
  include ::BeyondCanvas::StatusCodes
21
25
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module Models
5
+ module Authentication # :nodoc:
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ attr_accessor :code, :signature, :access_token_url
10
+
11
+ ##############################################################################
12
+ # Encrypted attribute configuration
13
+ ##############################################################################
14
+
15
+ attr_encrypted :beyond_api_url, key: [BeyondCanvas.configuration.encryption_key].pack('H*')
16
+ attr_encrypted :beyond_access_token, key: [BeyondCanvas.configuration.encryption_key].pack('H*')
17
+ attr_encrypted :beyond_refresh_token, key: [BeyondCanvas.configuration.encryption_key].pack('H*')
18
+
19
+ blind_index :beyond_api_url, key: [BeyondCanvas.configuration.blind_index_key].pack('H*')
20
+
21
+ ##############################################################################
22
+ # Validations
23
+ ##############################################################################
24
+
25
+ # Callback url params
26
+
27
+ validates :code,
28
+ presence: true,
29
+ on: :create
30
+ validates :signature,
31
+ presence: true,
32
+ on: :create
33
+ validates :access_token_url,
34
+ presence: true,
35
+ on: :create
36
+
37
+ # Database fields
38
+
39
+ validates :beyond_api_url,
40
+ presence: true
41
+ validates :beyond_access_token,
42
+ presence: true,
43
+ unless: -> { encrypted_beyond_access_token_was.blank? }
44
+ validates :beyond_refresh_token,
45
+ presence: true,
46
+ unless: -> { encrypted_beyond_refresh_token_was.blank? }
47
+
48
+ ##############################################################################
49
+ # Instance methods
50
+ ##############################################################################
51
+
52
+ #
53
+ # Get and save access_token and refresh_token using the authentication code
54
+ # NOTE: This method is used during the shop creation, as it is the only point
55
+ # we know about the authentication code
56
+ #
57
+ def authenticate
58
+ session = BeyondApi::Session.new(api_url: beyond_api_url)
59
+ session.token.create(code)
60
+ update(beyond_access_token: session.access_token,
61
+ beyond_refresh_token: session.refresh_token)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module Models
5
+ module Shop # :nodoc:
6
+ extend ActiveSupport::Concern
7
+ include BeyondCanvas::Models::Authentication
8
+ include BeyondCanvas::Models::Utils
9
+
10
+ included do
11
+ attr_accessor :api_url, :return_url
12
+
13
+ ##############################################################################
14
+ # Validations
15
+ ##############################################################################
16
+
17
+ # Callback url params
18
+
19
+ validates :api_url,
20
+ presence: true,
21
+ on: :create
22
+ validates :return_url,
23
+ presence: true,
24
+ on: :create
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ module Models
5
+ module Utils # :nodoc:
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ ##############################################################################
10
+ # Instance methods
11
+ ##############################################################################
12
+
13
+ #
14
+ # Generates a new access_token and refresh_token
15
+ #
16
+ def refresh_token
17
+ beyond_session = BeyondApi::Session.new(api_url: beyond_api_url, refresh_token: beyond_refresh_token)
18
+ beyond_session.token.refresh
19
+
20
+ update(beyond_access_token: beyond_session.access_token,
21
+ beyond_refresh_token: beyond_session.refresh_token)
22
+ end
23
+
24
+ #
25
+ # Generates a new access_token and refresh_token if they have expired
26
+ #
27
+ def refresh_token_if_needed
28
+ token_timestamp = JWT.decode(beyond_access_token, nil, false).first['exp']
29
+ current_timestamp = DateTime.now.to_i
30
+ return unless token_timestamp - current_timestamp <= 3600
31
+
32
+ refresh_token
33
+ end
34
+
35
+ #
36
+ # Returns a BeyondApi::Session object with api_url, access_token and refresh_token attributes
37
+ #
38
+ def to_session
39
+ BeyondApi::Session.new(api_url: beyond_api_url,
40
+ access_token: beyond_access_token,
41
+ refresh_token: beyond_refresh_token)
42
+ end
43
+
44
+ ##############################################################################
45
+ # Class methods
46
+ ##############################################################################
47
+
48
+ def self.find_session(id)
49
+ shop = find(id)
50
+ shop.to_session
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BeyondCanvas
4
+ class ParameterSanitizer # :nodoc:
5
+ DEFAULT_PERMITTED_ATTRIBUTES = %i[code signature return_url api_url access_token_url].freeze
6
+
7
+ def initialize(resource_name, params)
8
+ @params = params
9
+ @resource_name = resource_name
10
+ @permitted = DEFAULT_PERMITTED_ATTRIBUTES
11
+ end
12
+
13
+ def sanitize
14
+ permit_keys(default_params)
15
+ end
16
+
17
+ def permit(*keys)
18
+ @permitted.concat(keys)
19
+ end
20
+
21
+ private
22
+
23
+ def default_params
24
+ if hashable_resource_params?
25
+ @params.fetch(@resource_name)
26
+ else
27
+ empty_params
28
+ end
29
+ end
30
+
31
+ def hashable_resource_params?
32
+ @params[@resource_name].respond_to?(:permit)
33
+ end
34
+
35
+ def empty_params
36
+ ActionController::Parameters.new({})
37
+ end
38
+
39
+ def permit_keys(parameters)
40
+ parameters.permit(*@permitted)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module Routing
5
+ class Mapper # :nodoc:
6
+ def beyond_canvas_for(*resources)
7
+ mount BeyondCanvas::Engine => BeyondCanvas.configuration.namespace
8
+
9
+ resource_name, options = resources
10
+ BeyondCanvas.auth_model = resource_name.to_s.singularize
11
+ BeyondCanvas.use_rails_app_controller = options.present? && options[:controller].present?
12
+
13
+ set_routes(resource_name, options[:controller]) if BeyondCanvas.use_rails_app_controller
14
+ end
15
+
16
+ def set_routes(resource_name, controller)
17
+ resources resource_name, controller: controller
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BeyondCanvas
4
- VERSION = '0.14.0.pre'
4
+ VERSION = '0.16.0.pre'
5
5
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/active_record'
4
+
5
+ module BeyondCanvas
6
+ module Generators
7
+ class AuthModelGenerator < ActiveRecord::Generators::Base # :nodoc:
8
+ desc 'Generates a model with the given name and provides a method to authenticate in Beyond Backend'
9
+
10
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
11
+
12
+ source_root File.expand_path('templates', __dir__)
13
+
14
+ def copy_beyond_canvas_migration
15
+ migration_path = File.join('db', 'migrate')
16
+ migration_template 'migration.erb',
17
+ "#{migration_path}/beyond_canvas_create_#{table_name}.rb",
18
+ migration_version: migration_version
19
+ end
20
+
21
+ def generate_model
22
+ template 'model.erb', File.join('app', 'models', "#{file_path}.rb")
23
+ end
24
+
25
+ private
26
+
27
+ def rails5_and_up?
28
+ Rails::VERSION::MAJOR >= 5
29
+ end
30
+
31
+ def migration_version
32
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]" if rails5_and_up?
33
+ end
34
+
35
+ def migration_data
36
+ <<RUBY
37
+ t.string :encrypted_beyond_api_url, null: false
38
+ t.string :encrypted_beyond_api_url_iv, null: false
39
+ t.string :beyond_api_url_bidx, null: false
40
+
41
+ t.text :encrypted_beyond_access_token, null: true
42
+ t.text :encrypted_beyond_access_token_iv, null: true
43
+
44
+ t.text :encrypted_beyond_refresh_token, null: true
45
+ t.text :encrypted_beyond_refresh_token_iv, null: true
46
+ RUBY
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BeyondCanvasCreate<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :<%= table_name %><%= primary_key_type %> do |t|
6
+ <%= migration_data -%>
7
+
8
+ <% attributes.each do |attribute| -%>
9
+ t.<%= attribute.type %> :<%= attribute.name %>
10
+ <% end -%>
11
+
12
+ t.timestamps null: false
13
+ end
14
+
15
+ add_index :<%= table_name %>, :encrypted_beyond_api_url_iv, unique: true
16
+ add_index :<%= table_name %>, :beyond_api_url_bidx, unique: true
17
+ add_index :<%= table_name %>, :encrypted_beyond_access_token_iv, unique: true
18
+ add_index :<%= table_name %>, :encrypted_beyond_refresh_token_iv, unique: true
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= file_path.classify %> < ApplicationRecord
4
+ include BeyondCanvas::Models::Shop
5
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/active_record'
4
+
5
+ module BeyondCanvas
6
+ module Generators
7
+ class ControllerGenerator < Rails::Generators::Base # :nodoc:
8
+ desc 'Creates an inherited Beyond Canvas controller in the app/controllers folder'
9
+
10
+ argument :scope, required: true, desc: 'The scope to create the controller, e.g. shops, users'
11
+
12
+ source_root File.expand_path('templates', __dir__)
13
+
14
+ def create_controller
15
+ template 'controller.erb',
16
+ "app/controllers/#{scope}_controller.rb"
17
+ end
18
+ end
19
+ end
20
+ end