web-connect 0.1.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.
- checksums.yaml +7 -0
- data/README.md +1 -0
- data/Rakefile +3 -0
- data/lib/netfira/web_connect/components/checksum.rb +19 -0
- data/lib/netfira/web_connect/components/guid.rb +11 -0
- data/lib/netfira/web_connect/components/octa_word.rb +73 -0
- data/lib/netfira/web_connect/components.rb +1 -0
- data/lib/netfira/web_connect/configuration.rb +33 -0
- data/lib/netfira/web_connect/db_schema/20140514_support.rb +38 -0
- data/lib/netfira/web_connect/db_schema/20140515_alpha.rb +106 -0
- data/lib/netfira/web_connect/events.rb +14 -0
- data/lib/netfira/web_connect/migration/base_methods.rb +59 -0
- data/lib/netfira/web_connect/migration/refinements.rb +16 -0
- data/lib/netfira/web_connect/migration.rb +101 -0
- data/lib/netfira/web_connect/model/record/digests.rb +24 -0
- data/lib/netfira/web_connect/model/record/events.rb +35 -0
- data/lib/netfira/web_connect/model/record/file_record.rb +79 -0
- data/lib/netfira/web_connect/model/record/materialization.rb +59 -0
- data/lib/netfira/web_connect/model/record/relations.rb +51 -0
- data/lib/netfira/web_connect/model/record/sendable.rb +29 -0
- data/lib/netfira/web_connect/model/record/serializer.rb +56 -0
- data/lib/netfira/web_connect/model/record/translated_string.rb +42 -0
- data/lib/netfira/web_connect/model/record/translation.rb +58 -0
- data/lib/netfira/web_connect/model/record/translations.rb +63 -0
- data/lib/netfira/web_connect/model/record/tree.rb +13 -0
- data/lib/netfira/web_connect/model/record.rb +132 -0
- data/lib/netfira/web_connect/model/relation/events.rb +34 -0
- data/lib/netfira/web_connect/model/relation.rb +67 -0
- data/lib/netfira/web_connect/model/support.rb +13 -0
- data/lib/netfira/web_connect/model.rb +33 -0
- data/lib/netfira/web_connect/models/image.rb +48 -0
- data/lib/netfira/web_connect/models/order.rb +5 -0
- data/lib/netfira/web_connect/models/order_line.rb +13 -0
- data/lib/netfira/web_connect/models/support/setting.rb +31 -0
- data/lib/netfira/web_connect/models/support/shop/settings.rb +42 -0
- data/lib/netfira/web_connect/models/support/shop.rb +22 -0
- data/lib/netfira/web_connect/models/support/table.rb +5 -0
- data/lib/netfira/web_connect/models.rb +73 -0
- data/lib/netfira/web_connect/rack_app/action.rb +66 -0
- data/lib/netfira/web_connect/rack_app/action_helpers/data_types.rb +22 -0
- data/lib/netfira/web_connect/rack_app/action_helpers/env_importer.rb +59 -0
- data/lib/netfira/web_connect/rack_app/action_helpers/env_methods.rb +23 -0
- data/lib/netfira/web_connect/rack_app/actions/version_1/not_supported.rb +11 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/checksums.rb +14 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/commit/records.rb +45 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/commit/relations.rb +48 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/commit.rb +33 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/files.rb +21 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/info.rb +18 -0
- data/lib/netfira/web_connect/rack_app/actions/version_8/settings.rb +79 -0
- data/lib/netfira/web_connect/rack_app/exceptions/http_exception.rb +44 -0
- data/lib/netfira/web_connect/rack_app/exceptions.rb +6 -0
- data/lib/netfira/web_connect/rack_app.rb +56 -0
- data/lib/netfira/web_connect/request_filter.rb +66 -0
- data/lib/netfira/web_connect/schema/table.rb +58 -0
- data/lib/netfira/web_connect/schema.rb +22 -0
- data/lib/netfira/web_connect/version.rb +5 -0
- data/lib/netfira/web_connect.rb +82 -0
- data/lib/netfira.rb +10 -0
- data/lib/web_connect.rb +1 -0
- metadata +246 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'active_support/core_ext/object/deep_dup'
|
3
|
+
|
4
|
+
module Netfira::WebConnect
|
5
|
+
class Models::Shop::Settings
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def initialize(proxy)
|
9
|
+
@proxy = proxy
|
10
|
+
@models = proxy.map{ |model| [model.key.to_sym, model] }.to_h
|
11
|
+
@hash = @models.map{ |key, model| [key, model.typed_value]}.to_h
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@hash[key.to_sym]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
key = key.to_sym
|
20
|
+
model = @models[key] ||= @proxy.new(key: key.to_s)
|
21
|
+
model.typed_value = value
|
22
|
+
model.save!
|
23
|
+
@hash[key] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
@hash.deep_dup
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(key)
|
31
|
+
key = key.to_sym
|
32
|
+
return false unless @models[key]
|
33
|
+
@models[key].destroy!
|
34
|
+
@models.delete key
|
35
|
+
@hash.delete key
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
delegate [:count, :length, :size, :each, :map] => :@hash
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Netfira::WebConnect
|
2
|
+
class Models::Shop < Model::Support
|
3
|
+
|
4
|
+
has_many :setting_models, class_name: Models::Setting.name, inverse_of: :shop
|
5
|
+
|
6
|
+
def settings
|
7
|
+
@settings ||= Settings.new(setting_models)
|
8
|
+
end
|
9
|
+
|
10
|
+
def reload
|
11
|
+
@settings = nil
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def locale
|
16
|
+
settings[:locale] || Netfira::WebConnect.system_locale
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
require_relative 'shop/settings'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Netfira::WebConnect
|
4
|
+
module Models
|
5
|
+
|
6
|
+
def self.materialize
|
7
|
+
|
8
|
+
# Scrap any existing definitions
|
9
|
+
Models.constants.each do |name|
|
10
|
+
klass = Models.const_get(name)
|
11
|
+
Models.__send__ :remove_const, name if klass < Model::Record || klass < Model::Relation
|
12
|
+
end
|
13
|
+
|
14
|
+
# Load pre-defined models
|
15
|
+
Dir[File.expand_path('../models/*.rb', __FILE__)].each { |p| load p }
|
16
|
+
|
17
|
+
table_names = []
|
18
|
+
tables_to_localize = []
|
19
|
+
tables_to_relate = []
|
20
|
+
|
21
|
+
Model.connection.tables.reject{|x| x == Netfira::WebConnect.schema_migrations_table_name }.each do |table_name|
|
22
|
+
unprefixed_table_name = unprefix_table_name(table_name)
|
23
|
+
if unprefixed_table_name.nil? or unprefixed_table_name[0] == '_'
|
24
|
+
next
|
25
|
+
elsif l10n_table_name? table_name
|
26
|
+
tables_to_localize << l10n_table_owner_name(unprefixed_table_name)
|
27
|
+
elsif unprefixed_table_name =~ /\A(.+)_to_(.+)\z/
|
28
|
+
tables_to_relate << [$1, $2]
|
29
|
+
else
|
30
|
+
table_names << unprefixed_table_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
table_props = Models::Table.all.map{ |model| [model.name, model] }.to_h
|
35
|
+
|
36
|
+
table_names.each do |name|
|
37
|
+
props = table_props[name]
|
38
|
+
next unless props
|
39
|
+
Model::Record.materialize name.camelize.singularize,
|
40
|
+
tables_to_localize.include?(name),
|
41
|
+
props
|
42
|
+
end
|
43
|
+
|
44
|
+
tables_to_relate.each do |names|
|
45
|
+
Model::Relation.materialize *names.map{ |x| x.camelize.singularize }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.unprefix_table_name(name)
|
53
|
+
return unless name.starts_with? Netfira::WebConnect.db_table_prefix.to_s
|
54
|
+
@prefix_range ||= (Netfira::WebConnect.db_table_prefix.length)..-1
|
55
|
+
name[@prefix_range]
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.l10n_table_name?(name)
|
59
|
+
@l10n_suffix ||= Netfira::WebConnect.db_table_l10n_suffix.to_s
|
60
|
+
@l10n_suffix_range ||= (-@l10n_suffix.length)..-1
|
61
|
+
@l10n_suffix == name[@l10n_suffix_range]
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.l10n_table_owner_name(name)
|
65
|
+
name[@l10n_table_name_range ||= 0..(-@l10n_suffix.length - 1)] if l10n_table_name? name
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
require_relative 'models/support/setting'
|
72
|
+
require_relative 'models/support/shop'
|
73
|
+
require_relative 'models/support/table'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
|
4
|
+
#todo needs comment
|
5
|
+
module Netfira::WebConnect
|
6
|
+
class RackApp::Action
|
7
|
+
include RackApp::Exceptions::HttpExceptions
|
8
|
+
|
9
|
+
def self.action_classes
|
10
|
+
@action_classes ||= find_action_classes
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.latest_version
|
14
|
+
@latest_version ||= action_classes.keys.max
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create(action, version = nil)
|
18
|
+
version ||= latest_version
|
19
|
+
klass = nil
|
20
|
+
until klass or version < 1
|
21
|
+
klass = (action_classes[version] || {})[action] # todo needs explination or to be rewritten to be easily readable
|
22
|
+
version -= 1
|
23
|
+
end
|
24
|
+
klass and klass.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@headers = ActiveSupport::HashWithIndifferentAccess.new
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def self.find_action_classes
|
34
|
+
action_classes = {}
|
35
|
+
|
36
|
+
# Loop through all constants in this class's namespace
|
37
|
+
constants.each do |constant|
|
38
|
+
|
39
|
+
# Match Version# constants (modules containing actions)
|
40
|
+
if constant =~ /\AVersion(\d+)\z/
|
41
|
+
|
42
|
+
# The module containing the actions
|
43
|
+
mod = const_get(constant)
|
44
|
+
|
45
|
+
# A hash of actions, e.g. :commit => Action::Version8::Commit
|
46
|
+
action_classes[$1.to_i] = Hash[mod.constants.map do |name|
|
47
|
+
mod.const_get(name)
|
48
|
+
end.select do |klass|
|
49
|
+
klass < self
|
50
|
+
end.map do |klass|
|
51
|
+
[klass.name.demodulize.underscore.to_sym, klass]
|
52
|
+
end]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
action_classes
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Load action helpers
|
63
|
+
Dir[File.expand_path('../action_helpers/*.rb', __FILE__)].each{ |f| require f }
|
64
|
+
|
65
|
+
# Pre load all action classes in all versions
|
66
|
+
Dir[File.expand_path('../actions/version_*/*.rb', __FILE__)].each{ |f| require f }
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Netfira::WebConnect
|
2
|
+
class RackApp::Action
|
3
|
+
|
4
|
+
def class_for_record_type(type)
|
5
|
+
class_for_type type, Model::Record
|
6
|
+
end
|
7
|
+
|
8
|
+
def class_for_relation_type(type)
|
9
|
+
class_for_type type, Model::Relation
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def class_for_type(type, superclass)
|
15
|
+
raise BadRequest, 'No data type specified' if type.nil?
|
16
|
+
klass = Models.const_defined?(type) && Models.const_get(type)
|
17
|
+
raise BadRequest, 'Invalid or unknown data type' unless klass && klass < superclass
|
18
|
+
klass
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Netfira::WebConnect
|
2
|
+
class RackApp::Action
|
3
|
+
|
4
|
+
def import_env(env)
|
5
|
+
@env = env
|
6
|
+
|
7
|
+
# Parse the environment
|
8
|
+
request = Rack::Request.new env
|
9
|
+
|
10
|
+
# Authentication
|
11
|
+
authenticator = Netfira::WebConnect.authenticator
|
12
|
+
if authenticator.respond_to? :call
|
13
|
+
shop_name = env['HTTP_X_SHOP_NAME']
|
14
|
+
password = request['pw'] || env['HTTP_X_PASSWORD']
|
15
|
+
|
16
|
+
# Basic auth
|
17
|
+
auth = Rack::Auth::Basic::Request.new(env)
|
18
|
+
if auth.provided? && auth.basic?
|
19
|
+
shop_name ||= auth.username
|
20
|
+
password ||= auth.credentials[1]
|
21
|
+
end
|
22
|
+
|
23
|
+
result = authenticator.call shop_name, password
|
24
|
+
raise Unauthorized unless result
|
25
|
+
header :x_vary_password, result if String === result
|
26
|
+
@shop = Netfira::WebConnect::Models::Shop.find_or_create_by(name: shop_name)
|
27
|
+
|
28
|
+
elsif authenticator.nil?
|
29
|
+
@shop = Netfira::WebConnect.anonymous_shop
|
30
|
+
else
|
31
|
+
raise 'Authenticator is not callable'
|
32
|
+
end
|
33
|
+
|
34
|
+
# The request verb (PUT, GET, POST etc)
|
35
|
+
@verb = request.request_method.downcase.to_sym
|
36
|
+
|
37
|
+
# Query string
|
38
|
+
@query_string = request.GET
|
39
|
+
|
40
|
+
# The X-Timeout header
|
41
|
+
timeout = env['HTTP_X_TIMEOUT']
|
42
|
+
@timeout = timeout.to_i if timeout
|
43
|
+
|
44
|
+
# Path components
|
45
|
+
if env['PATH_INFO'] =~ /\A\/\d+\/[^\/]+\/(.+)\z/
|
46
|
+
@path = $1.split('/').map{ |x| Rack::Utils.unescape x }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Input
|
50
|
+
if put? or post?
|
51
|
+
@input = request.body
|
52
|
+
@input = StringIO.new(@input.read.unpack('m').first) if env['CONTENT_ENCODING'] == 'base64'
|
53
|
+
@input = JSON.parse @input.read if request.media_type == 'application/json'
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Netfira::WebConnect
|
2
|
+
class RackApp::Action
|
3
|
+
|
4
|
+
attr_reader :timeout, :input, :path, :verb, :shop, :headers, :query_string, :env
|
5
|
+
|
6
|
+
# This method sets a response header, e.g.header 'Content-Type', 'text/plain'
|
7
|
+
def header(name, value)
|
8
|
+
name = name.to_s.split(/[- _]/).map(&:capitalize).join('-').to_sym
|
9
|
+
if value
|
10
|
+
headers[name] = value
|
11
|
+
else
|
12
|
+
headers.delete name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# These methods tell you if a given verb was used, e.g. post?
|
17
|
+
%w[get post put delete].each do |verb|
|
18
|
+
define_method(:"#{verb}?") { self.verb.to_s == verb }
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Netfira::WebConnect::RackApp
|
2
|
+
module Action::Version8
|
3
|
+
class Checksums < Action
|
4
|
+
def call
|
5
|
+
raise MethodNotAllowed unless get?
|
6
|
+
|
7
|
+
klass = class_for_record_type(query_string['type'])
|
8
|
+
checksums = klass.where(shop_id: shop.id).map{ |record| [record.origin_id, record.digest]}.to_h
|
9
|
+
|
10
|
+
{checksums: checksums}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Netfira::WebConnect
|
2
|
+
module RackApp::Action::Version8
|
3
|
+
class Commit
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def commit_records(records)
|
8
|
+
records.each do |class_name, attribute_sets|
|
9
|
+
klass = class_for_record_type(class_name)
|
10
|
+
attribute_sets.each do |attributes|
|
11
|
+
update_record klass, attributes
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_record(klass, attributes)
|
17
|
+
origin_key = attributes[klass.origin_key.to_s.camelize(:lower)]
|
18
|
+
raise BadRequest, "#{klass.name.demodulize} sent with no #{klass.origin_key}" unless origin_key
|
19
|
+
record = klass.find_or_initialize_by_origin_id(shop, origin_key)
|
20
|
+
attributes.each do |key, value|
|
21
|
+
key = key.underscore
|
22
|
+
next if key == origin_key
|
23
|
+
if key == 'checksum' && klass < Model::Record::FileRecord
|
24
|
+
request_file klass, attributes['fileName'] if record.checksum != value
|
25
|
+
next
|
26
|
+
end
|
27
|
+
record.write_with_type_casting(key.to_sym, value) or raise BadRequest, "#{klass.name.demodulize.pluralize} don't have #{key} fields"
|
28
|
+
end
|
29
|
+
record.save or raise InternalServerError, record.errors
|
30
|
+
complete_record record
|
31
|
+
end
|
32
|
+
|
33
|
+
def complete_record(record)
|
34
|
+
list = complete[:records][record.class.name.demodulize] ||= {}
|
35
|
+
list[record.origin_id.to_s] = record.digest
|
36
|
+
end
|
37
|
+
|
38
|
+
def request_file(klass, file_name)
|
39
|
+
list = files_to_send[klass.name.demodulize] ||= []
|
40
|
+
list << file_name unless list.include? file_name
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Netfira::WebConnect::RackApp
|
2
|
+
module Action::Version8
|
3
|
+
class Commit
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def commit_relations(relations)
|
8
|
+
relations.each do |class_name, relation_sets|
|
9
|
+
klass = class_for_relation_type class_name.sub('&', 'To')
|
10
|
+
relation_sets.each do |relation|
|
11
|
+
update_relation klass, relation
|
12
|
+
complete_relation class_name, relation
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def update_relation(klass, relation)
|
18
|
+
|
19
|
+
# Make a hash of models => IDs, e.g. {Product => '123', Image => 'file.jpg'}
|
20
|
+
origin_ids = [relation['a'], relation['b']].each_with_index.map do |origin_id, index|
|
21
|
+
[klass.related_classes[index], origin_id]
|
22
|
+
end.to_h
|
23
|
+
|
24
|
+
if relation['x']
|
25
|
+
relate_records origin_ids
|
26
|
+
else
|
27
|
+
unrelate_records origin_ids
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def relate_records(origin_ids)
|
32
|
+
records = origin_ids.map{ |k, id| k.find_or_create_by_origin_id shop, id }
|
33
|
+
records[0] << records[1]
|
34
|
+
end
|
35
|
+
|
36
|
+
def unrelate_records(origin_ids)
|
37
|
+
records = origin_ids.map{ |k, id| k.find_by_origin_id shop, id }.reject(&:nil?)
|
38
|
+
records[0].delete records[1] if records.size == 2
|
39
|
+
end
|
40
|
+
|
41
|
+
def complete_relation(class_name, relation)
|
42
|
+
list = complete[:relations][class_name] ||= []
|
43
|
+
list << relation
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Netfira::WebConnect::RackApp
|
2
|
+
module Action::Version8
|
3
|
+
class Commit < Action
|
4
|
+
|
5
|
+
def call
|
6
|
+
raise MethodNotAllowed unless verb == :post
|
7
|
+
commit_records input['records'] if input['records']
|
8
|
+
commit_relations input['relations'] if input['relations']
|
9
|
+
{
|
10
|
+
complete: complete,
|
11
|
+
filesToSend: files_to_send
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def files_to_send
|
18
|
+
@files_to_send ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def complete
|
22
|
+
@complete ||= {
|
23
|
+
records: {},
|
24
|
+
relations: {}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require_relative 'commit/records'
|
33
|
+
require_relative 'commit/relations'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Netfira::WebConnect::RackApp
|
2
|
+
module Action::Version8
|
3
|
+
class Files < Action
|
4
|
+
def call
|
5
|
+
raise MethodNotAllowed unless post?
|
6
|
+
klass = class_for_record_type(path[0])
|
7
|
+
raise BadRequest, "You can't upload files for that data type" unless klass < Netfira::WebConnect::Model::Record::FileRecord
|
8
|
+
|
9
|
+
file_name = path[1]
|
10
|
+
raise BadRequest, 'You must specify a file name' unless file_name.length > 0
|
11
|
+
|
12
|
+
file = klass.find_or_initialize_by_origin_id(shop, file_name)
|
13
|
+
file << input
|
14
|
+
file.file_name = file_name
|
15
|
+
|
16
|
+
file.save or raise InternalServerError, file.errors
|
17
|
+
{}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Netfira::WebConnect::RackApp
|
2
|
+
module Action::Version8
|
3
|
+
class Info < Action
|
4
|
+
def call
|
5
|
+
{
|
6
|
+
info: {
|
7
|
+
apiVersion: Action.latest_version,
|
8
|
+
libVersion: Netfira::WebConnect::VERSION,
|
9
|
+
schema: Netfira::WebConnect.schema,
|
10
|
+
customFields: false,
|
11
|
+
acceptableRequestTypes: env['WC_ACCEPTABLE_REQUEST_TYPES'] || ['unpacked'],
|
12
|
+
locale: shop.locale
|
13
|
+
}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class Netfira::WebConnect::RackApp
|
2
|
+
module Action::Version8
|
3
|
+
class Settings < Action
|
4
|
+
def call
|
5
|
+
key = path && path.first
|
6
|
+
if key
|
7
|
+
handle_single key
|
8
|
+
else
|
9
|
+
handle_multiple
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def handle_single(key)
|
16
|
+
case verb
|
17
|
+
when :put, :post then update_single key
|
18
|
+
when :get then get_single key
|
19
|
+
when :delete then delete_single key
|
20
|
+
else raise MethodNotAllowed
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_single(key)
|
25
|
+
if input.respond_to? :read
|
26
|
+
setting = shop.setting_models.find_or_initialize_by(key: key)
|
27
|
+
setting.value = input.read
|
28
|
+
setting.content_type = env['CONTENT_TYPE'] || 'application/x-octet-stream'
|
29
|
+
setting.save
|
30
|
+
else
|
31
|
+
shop.settings[key] = input
|
32
|
+
end
|
33
|
+
{}
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_single(key)
|
37
|
+
setting = shop.setting_models.find_by(key: key)
|
38
|
+
raise NotFound unless setting
|
39
|
+
# if setting.content_type == 'application/json'
|
40
|
+
# JSON.parse(setting.value, quirks_mode: true)
|
41
|
+
# else
|
42
|
+
header 'Content-Type', setting.content_type
|
43
|
+
setting.value
|
44
|
+
# end
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete_single(key)
|
48
|
+
shop.setting_models.where(key: key).destroy_all
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
|
52
|
+
def handle_multiple
|
53
|
+
case verb
|
54
|
+
when :put, :post then update_multiple
|
55
|
+
when :get then get_all
|
56
|
+
when :delete then delete_all
|
57
|
+
else raise MethodNotAllowed
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_multiple
|
62
|
+
input.each do |key, value|
|
63
|
+
shop.settings[key] = value.unpack('m').first
|
64
|
+
end
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_all
|
69
|
+
{settings: shop.setting_models.map{ |model| [model.key, [model.value.b].pack('m0')] }.to_h}
|
70
|
+
end
|
71
|
+
|
72
|
+
def delete_all
|
73
|
+
shop.setting_models.destroy_all
|
74
|
+
{}
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rack/utils'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Netfira::WebConnect::RackApp::Exceptions
|
5
|
+
|
6
|
+
class HttpException < Base
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :status, :code, :category
|
11
|
+
attr_reader :headers
|
12
|
+
end
|
13
|
+
|
14
|
+
def_delegators :'self.class', :status, :code, :category
|
15
|
+
|
16
|
+
def initialize(*args, &block)
|
17
|
+
super *args, &block
|
18
|
+
@headers = self.class.headers.dup
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :headers
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
module HttpExceptions
|
26
|
+
|
27
|
+
Rack::Utils::HTTP_STATUS_CODES.each do |code, status|
|
28
|
+
next if status == 'Unassigned'
|
29
|
+
const_set status.gsub(/[ -](\w)/){$1.upcase}.sub(/ .*/, ''), (Class.new(HttpException) do
|
30
|
+
|
31
|
+
@status = status
|
32
|
+
@code = code
|
33
|
+
@category = code / 100
|
34
|
+
|
35
|
+
@headers = {}
|
36
|
+
|
37
|
+
end)
|
38
|
+
end
|
39
|
+
|
40
|
+
Unauthorized.headers['WWW-Authenticate'] = 'Basic realm="Authentication required"'
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|