linked_rails 0.0.4.pre.g2c53724b3 → 0.0.4.pre.g72bb595fe

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd12e0d41b6952dd04ab95017853a047956c45bd0e37f5e39f7b54f389e27d7c
4
- data.tar.gz: 9bd13ba226e886b1853331f7390574da70e6753dd0f1526a5e71a3ff0addd6d6
3
+ metadata.gz: 7810fdc42df9533cc1828c33aec04953486145ee0c744607b01b5f514d67dcb0
4
+ data.tar.gz: 9056187a625becc1c3e4c234ae7b06b77e77f0d4d3bdcb5d6c24b1249e1e21a9
5
5
  SHA512:
6
- metadata.gz: 774df3da980d69c98c27557bff628b1cfa00b25d64c522a65fc63b748c16dbefc88038743907425c51e9f2fe3e117eb178372c5b022ca1d03a1f4c4223c808ba
7
- data.tar.gz: 37f483fd315b0c590efe77164f7fd5edfc7c5c5a85d91f9582d25a9259ca4872d64e03b1c5f38aa32bef5ce76c3a69463bba675f03d36b30211add53a9600cb3
6
+ metadata.gz: d294b57b181d6995d88ee5967c61d9bd5c69a2a1e3dc6843848032c4f9ee36c7c762d2f163022e97cdd35219bc6d395392b0af9863ab7f0a4dcb924f5c4358ef
7
+ data.tar.gz: 880a18f47ab624f736ab12421c3ea8c6a4810f9602149d35efca16e5edb21e9563280bfbe9721acf0860a5c7a2602632a0f7056ca5cd7b207e9e4c7582da9f5c
@@ -21,8 +21,11 @@ module LinkedRails
21
21
  return response_for_wrong_host(opts) if wrong_host?(opts[:iri])
22
22
 
23
23
  include = opts[:include].to_s == 'true'
24
+ resource = LinkedRails.iri_mapper.resource_from_iri(request_path_to_url(opts[:iri]), user_context)
24
25
 
25
- response_from_request(include, RDF::URI(opts[:iri]))
26
+ return response_from_request(include, RDF::URI(opts[:iri])) if resource.blank?
27
+
28
+ response_from_resource(include, opts[:iri], resource)
26
29
  rescue StandardError => e
27
30
  handle_resource_error(opts, e)
28
31
  end
@@ -84,6 +87,13 @@ module LinkedRails
84
87
  false
85
88
  end
86
89
 
90
+ def resource_cache_control(cacheable, status, resource_policy)
91
+ return :private unless status == 200 && cacheable
92
+ return 'no-cache' unless resource_policy.try(:public_resource?)
93
+
94
+ :public
95
+ end
96
+
87
97
  def resource_params(param)
88
98
  params = param.permit(:include, :iri)
89
99
  params[:iri] = URI(params[:iri])
@@ -131,6 +141,12 @@ module LinkedRails
131
141
  }.merge(opts)
132
142
  end
133
143
 
144
+ def resource_status(resource_policy)
145
+ raise(LinkedRails::Errors::Forbidden.new(query: :show?)) unless resource_policy.show?
146
+
147
+ 200
148
+ end
149
+
134
150
  def response_for_wrong_host(opts)
135
151
  iri = opts[:iri]
136
152
  term = term_from_vocab(iri)
@@ -139,6 +155,23 @@ module LinkedRails
139
155
  ontology_term_response(iri, term, opts[:include])
140
156
  end
141
157
 
158
+ def response_from_resource(include, iri, resource)
159
+ resource_policy = policy(resource)
160
+ status = resource_status(resource_policy)
161
+
162
+ resource_response(
163
+ iri,
164
+ body: response_from_resource_body(include, iri, resource, status),
165
+ cache: resource_cache_control(resource.try(:cacheable?), status, resource_policy),
166
+ language: I18n.locale,
167
+ status: status
168
+ )
169
+ end
170
+
171
+ def response_from_resource_body(include, _iri, resource, status)
172
+ include && status == 200 ? resource_body(resource) : nil
173
+ end
174
+
142
175
  def term_from_vocab(iri)
143
176
  vocab = Vocab.for(iri)
144
177
  tag = iri.to_s.split(vocab.to_s).last
@@ -5,6 +5,7 @@ require 'pundit'
5
5
  module LinkedRails
6
6
  class Form # rubocop:disable Metrics/ClassLength
7
7
  include LinkedRails::Model
8
+ include LinkedRails::Model::Cacheable
8
9
 
9
10
  class_attribute :abstract_form, :pages, :model_class
10
11
 
@@ -5,15 +5,11 @@ module LinkedRails
5
5
  include ActiveModel::Model
6
6
  include LinkedRails::Model
7
7
 
8
- MANIFEST_KEY = 'cache:Manifest'
9
- CACHE_DB = ENV.fetch('PERSISTENT_REDIS_DATABASE', '6')
10
-
11
8
  def save
12
- Redis.new(db: CACHE_DB).hset(
13
- MANIFEST_KEY,
14
- {
15
- [LinkedRails.iri] => web_manifest.to_json
16
- }
9
+ Storage.hset(
10
+ :persistent,
11
+ :manifest,
12
+ LinkedRails.iri.to_s => web_manifest.to_json
17
13
  )
18
14
  end
19
15
 
@@ -162,5 +158,25 @@ module LinkedRails
162
158
  def tracking
163
159
  []
164
160
  end
161
+
162
+ class << self
163
+ def destroy(iri)
164
+ Storage.hdel(:persistent, :manifest, iri)
165
+ end
166
+
167
+ def move(from, to)
168
+ Storage.hset(
169
+ :persistent,
170
+ :redirect_prefix,
171
+ from => to
172
+ )
173
+
174
+ data = Storage.hget(:persistent, :manifest, from)
175
+
176
+ Storage.hset(:persistent, :manifest, to, data) if data
177
+
178
+ destroy(from)
179
+ end
180
+ end
165
181
  end
166
182
  end
@@ -26,7 +26,7 @@ module LinkedRails
26
26
  end
27
27
 
28
28
  def menus
29
- @menus ||= available_menus.map(&method(:memoised_menu_item))
29
+ @menus ||= available_menus.map(&method(:memoized_menu_item))
30
30
  end
31
31
 
32
32
  def menu(tag)
@@ -4,6 +4,7 @@ module LinkedRails
4
4
  class Ontology
5
5
  include ActiveModel::Model
6
6
  include LinkedRails::Model
7
+ include LinkedRails::Model::Cacheable
7
8
 
8
9
  def classes
9
10
  @classes ||= LinkedRails.linked_models.map do |klass|
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class FormPolicy < LinkedRails.policy_parent_class
5
+ def show?
6
+ true
7
+ end
8
+
9
+ def public_resource?
10
+ true
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class OntologyPolicy < LinkedRails.policy_parent_class
5
+ def show?
6
+ true
7
+ end
8
+
9
+ def public_resource?
10
+ true
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ class InvalidationStreamWorker < ActiveJob::Base
5
+ def perform(type, iri, resource_type)
6
+ entry = {
7
+ type: type,
8
+ resource: iri,
9
+ resourceType: resource_type
10
+ }
11
+ id = Storage.xadd(:stream, LinkedRails.cache_stream, entry)
12
+
13
+ raise('No message id returned, implies failure') if id.blank?
14
+ end
15
+ end
16
+ end
@@ -11,6 +11,8 @@ en:
11
11
  update:
12
12
  label: "Edit"
13
13
  success: 'Updated successfully'
14
+ errors:
15
+ access_denied: "You're not authorized for this action. (%{action})"
14
16
  linked_rails:
15
17
  status:
16
18
  400: "Error in request"
@@ -6,6 +6,10 @@ module LinkedRails
6
6
  extend ActiveSupport::Concern
7
7
  include ActiveSupport::Rescuable
8
8
 
9
+ included do
10
+ rescue_from LinkedRails::Errors::Forbidden, with: :handle_error
11
+ end
12
+
9
13
  private
10
14
 
11
15
  def add_error_snackbar(error)
@@ -69,6 +73,7 @@ module LinkedRails
69
73
  'Doorkeeper::Errors::InvalidGrantReuse' => 422,
70
74
  'LinkedRails::Auth::Errors::Expired' => 410,
71
75
  'LinkedRails::Auth::Errors::Unauthorized' => 401,
76
+ 'LinkedRails::Errors::Forbidden' => 403,
72
77
  'Pundit::NotAuthorizedError' => 403
73
78
  }
74
79
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Errors
5
+ class Forbidden < StandardError
6
+ attr_reader :query, :record, :policy, :action
7
+
8
+ # @param [Hash] options
9
+ # @option options [String] query The action of the request
10
+ # @option options [ActiveRecord::Base] record The record that was requested
11
+ # @option options [Policy] policy The policy that raised the exception
12
+ # @option options [String] message Override the default error message
13
+ # @return [String] the message
14
+ def initialize(**options)
15
+ @query = options.fetch(:query).to_s
16
+ @record = options[:record]
17
+ @policy = options[:policy]
18
+ @action = @query[-1] == '?' ? @query[0..-2] : @query
19
+ @message = options[:message]
20
+
21
+ raise StandardError if @query.blank? && @message.blank?
22
+
23
+ super(@message || default_message)
24
+ end
25
+
26
+ private
27
+
28
+ def default_message
29
+ I18n.t(
30
+ "pundit.#{@policy.class.to_s.underscore}.#{@query}",
31
+ action: @action,
32
+ default: I18n.t('errors.access_denied')
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors/forbidden'
@@ -46,6 +46,13 @@ module LinkedRails
46
46
 
47
47
  private
48
48
 
49
+ def request_path_to_url(path)
50
+ return path unless path.present? && URI(path).relative?
51
+
52
+ port = [80, 443].include?(request.port) ? nil : request.port
53
+ URI::Generic.new(request.scheme, nil, request.host, port, nil, path, nil, nil, nil).to_s
54
+ end
55
+
49
56
  def build_new_resource
50
57
  controller_class.build_new(user_context: user_context)
51
58
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LinkedRails
4
+ module Model
5
+ module Cacheable
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ if respond_to?(:after_commit)
10
+ after_commit :publish_create, on: :create, if: :should_publish_changes
11
+ after_commit :publish_update, on: :update, if: :should_publish_changes
12
+ after_commit :publish_delete, on: :destroy, if: :should_publish_changes
13
+ end
14
+ end
15
+
16
+ def cacheable?
17
+ true
18
+ end
19
+
20
+ def publish_create
21
+ publish_message('io.ontola.transactions.Created')
22
+ end
23
+
24
+ def publish_update
25
+ publish_message('io.ontola.transactions.Updated')
26
+ end
27
+
28
+ def publish_delete
29
+ publish_message('io.ontola.transactions.Deleted')
30
+ end
31
+
32
+ private
33
+
34
+ def publish_message(type)
35
+ LinkedRails::InvalidationStreamWorker.perform_now(type, iri.to_s, self.class.iri.to_s)
36
+ rescue StandardError
37
+ LinkedRails::InvalidationStreamWorker.perform_later(type, iri.to_s, self.class.iri.to_s)
38
+ end
39
+
40
+ def should_publish_changes
41
+ cacheable? && !Rails.env.test?
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'model/actionable'
4
+ require_relative 'model/cacheable'
4
5
  require_relative 'model/collections'
5
6
  require_relative 'model/dirty'
6
7
  require_relative 'model/enhancements'
@@ -46,6 +46,10 @@ module LinkedRails
46
46
  self.class.policy_class
47
47
  end
48
48
 
49
+ def public_resource?
50
+ false
51
+ end
52
+
49
53
  def show?
50
54
  false
51
55
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redis'
4
+
5
+ module LinkedRails
6
+ class Storage
7
+ REDIS_DB = {
8
+ cache: LinkedRails.cache_redis_database,
9
+ persistent: LinkedRails.persistent_redis_database,
10
+ stream: LinkedRails.stream_redis_database
11
+ }.freeze
12
+ KEYS = {
13
+ manifest: 'cache:Manifest',
14
+ redirect_exact: 'cache:Redirect:Exact',
15
+ redirect_prefix: 'cache:Redirect:Prefix'
16
+ }.freeze
17
+
18
+ class << self
19
+ %i[xadd].each do |method|
20
+ define_method(method) do |db, *args|
21
+ Redis.new(db: REDIS_DB.fetch(db)).send(method, *args)
22
+ end
23
+ end
24
+
25
+ %i[hset hdel hget].each do |method|
26
+ define_method(method) do |db, key, *args|
27
+ Redis.new(db: REDIS_DB.fetch(db)).send(method, KEYS.fetch(key), *args)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/linked_rails.rb CHANGED
@@ -22,6 +22,10 @@ module LinkedRails
22
22
 
23
23
  mattr_accessor :whitelisted_spi_ips
24
24
  mattr_writer :host, :scheme
25
+ mattr_accessor :persistent_redis_database, default: ENV['PERSISTENT_REDIS_DATABASE'].presence || 6
26
+ mattr_accessor :stream_redis_database, default: ENV['STREAM_REDIS_DATABASE'].presence || 7
27
+ mattr_accessor :cache_redis_database, default: ENV['CACHE_REDIS_DATABASE'].presence || 8
28
+ mattr_accessor :cache_stream, default: ENV['CACHE_STREAM'].presence || 'transactions'
25
29
 
26
30
  def self.configurable_class(parent, klass, default: nil, reader: nil) # rubocop:disable Metrics/AbcSize
27
31
  method = :"#{[parent, klass.to_s.downcase].compact.join('_')}_class"
@@ -84,6 +88,7 @@ ActiveSupport::Inflector.inflections do |inflect|
84
88
  inflect.acronym 'SHACL'
85
89
  end
86
90
 
91
+ require 'linked_rails/errors'
87
92
  require 'linked_rails/uri_template'
88
93
  require 'linked_rails/vocab'
89
94
  require 'linked_rails/cache'
@@ -101,3 +106,4 @@ require 'linked_rails/routes'
101
106
  require 'linked_rails/serializer'
102
107
  require 'linked_rails/translate'
103
108
  require 'linked_rails/railtie'
109
+ require 'linked_rails/storage'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linked_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.pre.g2c53724b3
4
+ version: 0.0.4.pre.g72bb595fe
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arthur Dingemans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-02 00:00:00.000000000 Z
11
+ date: 2022-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_response
@@ -299,8 +299,10 @@ files:
299
299
  - app/policies/linked_rails/collection/view_policy.rb
300
300
  - app/policies/linked_rails/collection_policy.rb
301
301
  - app/policies/linked_rails/enum_value_policy.rb
302
+ - app/policies/linked_rails/form_policy.rb
302
303
  - app/policies/linked_rails/menus/item_policy.rb
303
304
  - app/policies/linked_rails/menus/list_policy.rb
305
+ - app/policies/linked_rails/ontology_policy.rb
304
306
  - app/policies/linked_rails/sequence_policy.rb
305
307
  - app/serializers/linked_rails/actions/item_serializer.rb
306
308
  - app/serializers/linked_rails/actions/object_serializer.rb
@@ -338,6 +340,7 @@ files:
338
340
  - app/serializers/linked_rails/web_page_serializer.rb
339
341
  - app/serializers/linked_rails/web_site_serializer.rb
340
342
  - app/serializers/linked_rails/widget_serializer.rb
343
+ - app/workers/linked_rails/invalidation_stream_worker.rb
341
344
  - config/initializers/inflections.rb
342
345
  - lib/generators/linked_rails/install/install_generator.rb
343
346
  - lib/generators/linked_rails/install/templates/README
@@ -387,6 +390,8 @@ files:
387
390
  - lib/linked_rails/enhancements/destroyable/controller.rb
388
391
  - lib/linked_rails/enhancements/updatable/controller.rb
389
392
  - lib/linked_rails/enhancements/updatable/serializer.rb
393
+ - lib/linked_rails/errors.rb
394
+ - lib/linked_rails/errors/forbidden.rb
390
395
  - lib/linked_rails/helpers/delta_helper.rb
391
396
  - lib/linked_rails/helpers/ontola_actions_helper.rb
392
397
  - lib/linked_rails/helpers/resource_helper.rb
@@ -395,6 +400,7 @@ files:
395
400
  - lib/linked_rails/middleware/linked_data_params.rb
396
401
  - lib/linked_rails/model.rb
397
402
  - lib/linked_rails/model/actionable.rb
403
+ - lib/linked_rails/model/cacheable.rb
398
404
  - lib/linked_rails/model/collections.rb
399
405
  - lib/linked_rails/model/dirty.rb
400
406
  - lib/linked_rails/model/enhancements.rb
@@ -418,6 +424,7 @@ files:
418
424
  - lib/linked_rails/serializer/actionable.rb
419
425
  - lib/linked_rails/serializer/menuable.rb
420
426
  - lib/linked_rails/serializer/singularable.rb
427
+ - lib/linked_rails/storage.rb
421
428
  - lib/linked_rails/test_methods.rb
422
429
  - lib/linked_rails/translate.rb
423
430
  - lib/linked_rails/types/iri_type.rb