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.
- checksums.yaml +4 -4
- data/README.md +0 -6
- data/app/assets/images/icons/checkbox_checked.svg +1 -0
- data/app/assets/images/icons/checkbox_unchecked.svg +1 -0
- data/app/assets/images/icons/radiobutton_checked.svg +1 -0
- data/app/assets/images/icons/radiobutton_unchecked.svg +1 -0
- data/app/assets/javascripts/beyond_canvas/base.js +248 -87
- data/app/assets/stylesheets/beyond_canvas/base.scss +3 -0
- data/app/assets/stylesheets/beyond_canvas/components/_containers.scss +37 -0
- data/app/assets/stylesheets/beyond_canvas/components/_inputs.scss +47 -1
- data/app/assets/stylesheets/beyond_canvas/settings/_breakpoints.scss +6 -0
- data/app/assets/stylesheets/beyond_canvas/settings/_variables.scss +24 -0
- data/app/assets/stylesheets/beyond_canvas/utilities/_functions.scss +15 -0
- data/app/controllers/beyond_canvas/authentications_controller.rb +62 -0
- data/app/controllers/concerns/beyond_canvas/authentication.rb +24 -0
- data/app/controllers/concerns/beyond_canvas/request_validation.rb +1 -1
- data/app/controllers/concerns/beyond_canvas/resource_management.rb +33 -0
- data/app/form_builders/beyond_canvas/form_builder.rb +65 -8
- data/app/javascript/beyond_canvas/base.js +3 -6
- data/app/javascript/beyond_canvas/initializers/buttons.js +21 -39
- data/app/javascript/beyond_canvas/initializers/flash.js +5 -14
- data/app/javascript/beyond_canvas/initializers/functions.js +41 -0
- data/app/javascript/beyond_canvas/initializers/inputs.js +3 -8
- data/app/views/beyond_canvas/authentications/new.html.erb +18 -0
- data/config/locales/en.yml +4 -0
- data/config/routes.rb +6 -0
- data/lib/beyond_canvas.rb +22 -2
- data/lib/beyond_canvas/configuration.rb +4 -1
- data/lib/beyond_canvas/engine.rb +4 -0
- data/lib/beyond_canvas/models/authentication.rb +66 -0
- data/lib/beyond_canvas/models/shop.rb +28 -0
- data/lib/beyond_canvas/models/utils.rb +55 -0
- data/lib/beyond_canvas/parameter_sanitizer.rb +43 -0
- data/lib/beyond_canvas/rails/routes.rb +21 -0
- data/lib/beyond_canvas/version.rb +1 -1
- data/lib/generators/beyond_canvas/auth_model/auth_model_generator.rb +50 -0
- data/lib/generators/beyond_canvas/auth_model/templates/migration.erb +20 -0
- data/lib/generators/beyond_canvas/auth_model/templates/model.erb +5 -0
- data/lib/generators/beyond_canvas/controller/controller_generator.rb +20 -0
- data/lib/generators/beyond_canvas/controller/templates/controller.erb +37 -0
- data/lib/generators/beyond_canvas/install/install_generator.rb +15 -5
- data/lib/generators/beyond_canvas/install/templates/beyond_canvas.rb.erb +11 -0
- data/lib/generators/beyond_canvas/views/views_generator.rb +19 -0
- 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>
|
data/config/routes.rb
CHANGED
@@ -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
|
data/lib/beyond_canvas.rb
CHANGED
@@ -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,
|
18
|
-
autoload :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!
|
data/lib/beyond_canvas/engine.rb
CHANGED
@@ -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
|
@@ -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,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
|