beyond_canvas 0.14.0.pre → 0.16.0.pre

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