linked_rails 0.0.1
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/LICENSE +674 -0
- data/README.md +65 -0
- data/Rakefile +34 -0
- data/app/controllers/linked_rails/actions/items_controller.rb +9 -0
- data/app/controllers/linked_rails/bulk_controller.rb +195 -0
- data/app/controllers/linked_rails/current_user_controller.rb +13 -0
- data/app/controllers/linked_rails/enum_values_controller.rb +49 -0
- data/app/controllers/linked_rails/forms_controller.rb +13 -0
- data/app/controllers/linked_rails/manifests_controller.rb +21 -0
- data/app/controllers/linked_rails/menus/items_controller.rb +9 -0
- data/app/controllers/linked_rails/menus/lists_controller.rb +9 -0
- data/app/controllers/linked_rails/not_found_controller.rb +15 -0
- data/app/controllers/linked_rails/ontologies_controller.rb +7 -0
- data/app/models/linked_rails/actions/default_actions/create.rb +60 -0
- data/app/models/linked_rails/actions/default_actions/destroy.rb +45 -0
- data/app/models/linked_rails/actions/default_actions/update.rb +50 -0
- data/app/models/linked_rails/actions/default_actions.rb +17 -0
- data/app/models/linked_rails/actions/item.rb +234 -0
- data/app/models/linked_rails/actions/list.rb +113 -0
- data/app/models/linked_rails/collection/filter.rb +16 -0
- data/app/models/linked_rails/collection/filter_field.rb +30 -0
- data/app/models/linked_rails/collection/filter_option.rb +17 -0
- data/app/models/linked_rails/collection/filterable.rb +92 -0
- data/app/models/linked_rails/collection/infinite_view.rb +98 -0
- data/app/models/linked_rails/collection/iri.rb +74 -0
- data/app/models/linked_rails/collection/iri_mapping.rb +33 -0
- data/app/models/linked_rails/collection/paginated_view.rb +41 -0
- data/app/models/linked_rails/collection/sortable.rb +60 -0
- data/app/models/linked_rails/collection/sorting.rb +72 -0
- data/app/models/linked_rails/collection/view.rb +101 -0
- data/app/models/linked_rails/collection.rb +220 -0
- data/app/models/linked_rails/condition.rb +7 -0
- data/app/models/linked_rails/creative_work.rb +21 -0
- data/app/models/linked_rails/current_user.rb +28 -0
- data/app/models/linked_rails/entry_point.rb +53 -0
- data/app/models/linked_rails/enum_value.rb +33 -0
- data/app/models/linked_rails/form/field/association_input.rb +23 -0
- data/app/models/linked_rails/form/field/checkbox_group.rb +10 -0
- data/app/models/linked_rails/form/field/checkbox_input.rb +10 -0
- data/app/models/linked_rails/form/field/color_input.rb +17 -0
- data/app/models/linked_rails/form/field/date_input.rb +10 -0
- data/app/models/linked_rails/form/field/date_time_input.rb +10 -0
- data/app/models/linked_rails/form/field/email_input.rb +10 -0
- data/app/models/linked_rails/form/field/file_input.rb +10 -0
- data/app/models/linked_rails/form/field/location_input.rb +11 -0
- data/app/models/linked_rails/form/field/markdown_input.rb +10 -0
- data/app/models/linked_rails/form/field/number_input.rb +10 -0
- data/app/models/linked_rails/form/field/password_input.rb +10 -0
- data/app/models/linked_rails/form/field/postal_range_input.rb +10 -0
- data/app/models/linked_rails/form/field/radio_group.rb +10 -0
- data/app/models/linked_rails/form/field/resource_field.rb +23 -0
- data/app/models/linked_rails/form/field/select_input.rb +11 -0
- data/app/models/linked_rails/form/field/slider_input.rb +10 -0
- data/app/models/linked_rails/form/field/text_area_input.rb +10 -0
- data/app/models/linked_rails/form/field/text_input.rb +10 -0
- data/app/models/linked_rails/form/field/toggle_button_group.rb +10 -0
- data/app/models/linked_rails/form/field.rb +117 -0
- data/app/models/linked_rails/form/field_factory.rb +219 -0
- data/app/models/linked_rails/form/group.rb +39 -0
- data/app/models/linked_rails/form/page.rb +31 -0
- data/app/models/linked_rails/form.rb +156 -0
- data/app/models/linked_rails/manifest.rb +102 -0
- data/app/models/linked_rails/media_object.rb +31 -0
- data/app/models/linked_rails/menus/item.rb +92 -0
- data/app/models/linked_rails/menus/list.rb +138 -0
- data/app/models/linked_rails/ontology/base.rb +50 -0
- data/app/models/linked_rails/ontology/class.rb +43 -0
- data/app/models/linked_rails/ontology/property.rb +19 -0
- data/app/models/linked_rails/ontology.rb +34 -0
- data/app/models/linked_rails/property_query.rb +11 -0
- data/app/models/linked_rails/resource.rb +17 -0
- data/app/models/linked_rails/sequence.rb +64 -0
- data/app/models/linked_rails/shacl/node_shape.rb +21 -0
- data/app/models/linked_rails/shacl/property_shape.rb +53 -0
- data/app/models/linked_rails/shacl/shape.rb +33 -0
- data/app/models/linked_rails/web_page.rb +22 -0
- data/app/models/linked_rails/web_site.rb +17 -0
- data/app/models/linked_rails/widget.rb +55 -0
- data/app/policies/linked_rails/actions/item_policy.rb +11 -0
- data/app/policies/linked_rails/actions/list_policy.rb +11 -0
- data/app/policies/linked_rails/collection/view_policy.rb +13 -0
- data/app/policies/linked_rails/collection_policy.rb +41 -0
- data/app/policies/linked_rails/enum_value_policy.rb +32 -0
- data/app/policies/linked_rails/menus/item_policy.rb +11 -0
- data/app/policies/linked_rails/menus/list_policy.rb +11 -0
- data/app/policies/linked_rails/sequence_policy.rb +9 -0
- data/app/serializers/linked_rails/actions/item_serializer.rb +28 -0
- data/app/serializers/linked_rails/collection/filter_field_serializer.rb +12 -0
- data/app/serializers/linked_rails/collection/filter_option_serializer.rb +12 -0
- data/app/serializers/linked_rails/collection/filter_serializer.rb +13 -0
- data/app/serializers/linked_rails/collection/sorting_serializer.rb +13 -0
- data/app/serializers/linked_rails/collection/view_serializer.rb +22 -0
- data/app/serializers/linked_rails/collection_serializer.rb +44 -0
- data/app/serializers/linked_rails/condition_serializer.rb +9 -0
- data/app/serializers/linked_rails/creative_work_serializer.rb +10 -0
- data/app/serializers/linked_rails/current_user_serializer.rb +7 -0
- data/app/serializers/linked_rails/entry_point_serializer.rb +20 -0
- data/app/serializers/linked_rails/enum_value_serializer.rb +12 -0
- data/app/serializers/linked_rails/form/field/association_input_serializer.rb +13 -0
- data/app/serializers/linked_rails/form/field/resource_field_serializer.rb +11 -0
- data/app/serializers/linked_rails/form/field/select_input_serializer.rb +11 -0
- data/app/serializers/linked_rails/form/field_serializer.rb +39 -0
- data/app/serializers/linked_rails/form/group_serializer.rb +14 -0
- data/app/serializers/linked_rails/form/page_serializer.rb +13 -0
- data/app/serializers/linked_rails/form_serializer.rb +9 -0
- data/app/serializers/linked_rails/media_object_serializer.rb +17 -0
- data/app/serializers/linked_rails/menus/item_serializer.rb +35 -0
- data/app/serializers/linked_rails/menus/list_serializer.rb +13 -0
- data/app/serializers/linked_rails/ontology/class_serializer.rb +19 -0
- data/app/serializers/linked_rails/ontology/property_serializer.rb +16 -0
- data/app/serializers/linked_rails/ontology_serializer.rb +8 -0
- data/app/serializers/linked_rails/rdf_error_serializer.rb +8 -0
- data/app/serializers/linked_rails/sequence_serializer.rb +14 -0
- data/app/serializers/linked_rails/shacl/node_shape_serializer.rb +12 -0
- data/app/serializers/linked_rails/shacl/property_shape_serializer.rb +38 -0
- data/app/serializers/linked_rails/shacl/shape_serializer.rb +25 -0
- data/app/serializers/linked_rails/web_page_serializer.rb +10 -0
- data/app/serializers/linked_rails/web_site_serializer.rb +11 -0
- data/app/serializers/linked_rails/widget_serializer.rb +15 -0
- data/config/initializers/inflections.rb +5 -0
- data/lib/generators/linked_rails/install/install_generator.rb +65 -0
- data/lib/generators/linked_rails/install/templates/app_menu_list.rb +41 -0
- data/lib/generators/linked_rails/install/templates/application_action_list.rb +3 -0
- data/lib/generators/linked_rails/install/templates/application_form.rb +3 -0
- data/lib/generators/linked_rails/install/templates/application_menu_list.rb +3 -0
- data/lib/generators/linked_rails/install/templates/application_policy.rb +18 -0
- data/lib/generators/linked_rails/install/templates/application_serializer.rb +5 -0
- data/lib/generators/linked_rails/install/templates/initializer.rb +9 -0
- data/lib/generators/linked_rails/install/templates/locales.yml +12 -0
- data/lib/generators/linked_rails/install/templates/rdf_responder.rb +5 -0
- data/lib/generators/linked_rails/install/templates/rdf_serializers_initializer.rb +5 -0
- data/lib/generators/linked_rails/install/templates/vocab.rb +5 -0
- data/lib/generators/linked_rails/install/templates/vocab.yml +26 -0
- data/lib/generators/linked_rails/model/model_generator.rb +58 -0
- data/lib/generators/linked_rails/model/templates/action_list.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/controller.rb.tt +7 -0
- data/lib/generators/linked_rails/model/templates/create_table_migration.rb.tt +24 -0
- data/lib/generators/linked_rails/model/templates/form.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/menu_list.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/model.rb.tt +15 -0
- data/lib/generators/linked_rails/model/templates/module.rb.tt +7 -0
- data/lib/generators/linked_rails/model/templates/policy.rb.tt +6 -0
- data/lib/generators/linked_rails/model/templates/serializer.rb.tt +9 -0
- data/lib/linked_rails/active_response/controller/collections.rb +43 -0
- data/lib/linked_rails/active_response/controller/crud_defaults.rb +92 -0
- data/lib/linked_rails/active_response/controller/params.rb +51 -0
- data/lib/linked_rails/active_response/controller.rb +37 -0
- data/lib/linked_rails/active_response/responders/rdf.rb +158 -0
- data/lib/linked_rails/cache.rb +35 -0
- data/lib/linked_rails/callable_variable.rb +25 -0
- data/lib/linked_rails/constraints/whitelist.rb +36 -0
- data/lib/linked_rails/controller/authorization.rb +15 -0
- data/lib/linked_rails/controller/error_handling.rb +76 -0
- data/lib/linked_rails/controller.rb +43 -0
- data/lib/linked_rails/engine.rb +7 -0
- data/lib/linked_rails/enhanceable.rb +21 -0
- data/lib/linked_rails/enhancements/actionable/model.rb +71 -0
- data/lib/linked_rails/enhancements/actionable/serializer.rb +25 -0
- data/lib/linked_rails/enhancements/creatable/action.rb +15 -0
- data/lib/linked_rails/enhancements/creatable/controller.rb +15 -0
- data/lib/linked_rails/enhancements/destroyable/action.rb +15 -0
- data/lib/linked_rails/enhancements/destroyable/controller.rb +15 -0
- data/lib/linked_rails/enhancements/destroyable/routing.rb +19 -0
- data/lib/linked_rails/enhancements/indexable/model.rb +10 -0
- data/lib/linked_rails/enhancements/menuable/model.rb +36 -0
- data/lib/linked_rails/enhancements/menuable/serializer.rb +33 -0
- data/lib/linked_rails/enhancements/route_concerns.rb +56 -0
- data/lib/linked_rails/enhancements/singularable/controller.rb +43 -0
- data/lib/linked_rails/enhancements/singularable/model.rb +47 -0
- data/lib/linked_rails/enhancements/singularable/serializer.rb +28 -0
- data/lib/linked_rails/enhancements/tableable/model.rb +28 -0
- data/lib/linked_rails/enhancements/updatable/action.rb +15 -0
- data/lib/linked_rails/enhancements/updatable/controller.rb +15 -0
- data/lib/linked_rails/enhancements/updatable/routing.rb +20 -0
- data/lib/linked_rails/enhancements/updatable/serializer.rb +17 -0
- data/lib/linked_rails/enhancements.rb +22 -0
- data/lib/linked_rails/helpers/delta_helper.rb +86 -0
- data/lib/linked_rails/helpers/ontola_actions_helper.rb +32 -0
- data/lib/linked_rails/helpers/resource_helper.rb +70 -0
- data/lib/linked_rails/iri_mapper.rb +125 -0
- data/lib/linked_rails/middleware/linked_data_params.rb +224 -0
- data/lib/linked_rails/model/collections.rb +82 -0
- data/lib/linked_rails/model/dirty.rb +82 -0
- data/lib/linked_rails/model/enhancements.rb +61 -0
- data/lib/linked_rails/model/filtering.rb +89 -0
- data/lib/linked_rails/model/indexable.rb +51 -0
- data/lib/linked_rails/model/iri.rb +121 -0
- data/lib/linked_rails/model/iri_mapping.rb +69 -0
- data/lib/linked_rails/model/serialization.rb +88 -0
- data/lib/linked_rails/model/sorting.rb +20 -0
- data/lib/linked_rails/model.rb +68 -0
- data/lib/linked_rails/params_parser.rb +93 -0
- data/lib/linked_rails/policy/attribute_conditions.rb +53 -0
- data/lib/linked_rails/policy.rb +189 -0
- data/lib/linked_rails/rdf_error.rb +36 -0
- data/lib/linked_rails/renderers.rb +46 -0
- data/lib/linked_rails/routes.rb +108 -0
- data/lib/linked_rails/serializer.rb +137 -0
- data/lib/linked_rails/translate.rb +176 -0
- data/lib/linked_rails/version.rb +5 -0
- data/lib/linked_rails/vocab.rb +81 -0
- data/lib/linked_rails.rb +86 -0
- data/lib/nill_class_renderer.rb +3 -0
- data/lib/rails/welcome_controller.rb +45 -0
- data/lib/tasks/linked_rails_tasks.rake +6 -0
- metadata +416 -0
data/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# LinkedRails
|
|
2
|
+
LinkedRails is a gem for Ruby on Rails that helps you create a Linked Data application in a matter of seconds.
|
|
3
|
+
|
|
4
|
+
It includes among other things:
|
|
5
|
+
* Linked data serialization to Turtle, JSON-LD, N-Triples and more using [rdf-serializers](https://github.com/ontola/rdf-serializers)
|
|
6
|
+
* Controller abstraction using [active_response](https://github.com/ontola/active_response)
|
|
7
|
+
* Serialization of forms
|
|
8
|
+
* Serialization of collections using the [Activity Streams spec](https://www.w3.org/ns/activitystreams)
|
|
9
|
+
* Serialization of menus
|
|
10
|
+
* Communicating actions to be executed by the frontend using Exec Actions header
|
|
11
|
+
* Rendering errors as RDF
|
|
12
|
+
* Parsing linked data graphs as params
|
|
13
|
+
|
|
14
|
+
## Work in progress
|
|
15
|
+
This gem is an extraction from an existing app. Tests are not yet sufficient but will be extended soon.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
Add this line to your application's Gemfile:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
gem 'linked_rails'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
And then execute:
|
|
25
|
+
```bash
|
|
26
|
+
$ bundle
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or install it yourself as:
|
|
30
|
+
```bash
|
|
31
|
+
$ gem install linked_rails
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Getting started
|
|
35
|
+
|
|
36
|
+
Add the following lines to application.rb to enable params parsing
|
|
37
|
+
```
|
|
38
|
+
module MyApp
|
|
39
|
+
class Application < Rails::Application
|
|
40
|
+
[...]
|
|
41
|
+
config.middleware.use LinkedRails::Middleware::LinkedDataParams
|
|
42
|
+
[...]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Add the following line to your models
|
|
48
|
+
```
|
|
49
|
+
LinkedRails::Model
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Add the following line to your controllers
|
|
53
|
+
```
|
|
54
|
+
LinkedRails::Controller
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Add the following line to your serializers
|
|
58
|
+
```
|
|
59
|
+
LinkedRails::Serializer
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Add the following line to your policies
|
|
63
|
+
```
|
|
64
|
+
LinkedRails::Policy
|
|
65
|
+
```
|
data/Rakefile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require 'rdoc/task'
|
|
10
|
+
|
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
13
|
+
rdoc.title = 'LinkedRails'
|
|
14
|
+
rdoc.options << '--line-numbers'
|
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
|
20
|
+
load 'rails/tasks/engine.rake'
|
|
21
|
+
|
|
22
|
+
load 'rails/tasks/statistics.rake'
|
|
23
|
+
|
|
24
|
+
require 'bundler/gem_tasks'
|
|
25
|
+
|
|
26
|
+
require 'rake/testtask'
|
|
27
|
+
|
|
28
|
+
Rake::TestTask.new(:test) do |t|
|
|
29
|
+
t.libs << 'test'
|
|
30
|
+
t.pattern = 'test/**/*_test.rb'
|
|
31
|
+
t.verbose = false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
task default: :test
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'benchmark'
|
|
4
|
+
|
|
5
|
+
module LinkedRails
|
|
6
|
+
class BulkController < ApplicationController # rubocop:disable Metrics/ClassLength
|
|
7
|
+
REQUEST_HEADERS = %w[HTTP_ACCEPT_LANGUAGE HTTP_AUTHORIZATION HTTP_FORWARDED HTTP_HOST HTTP_REFERER HTTP_USER_AGENT
|
|
8
|
+
HTTP_WEBSITE_IRI HTTP_X_DEVICE_ID HTTP_X_FORWARDED_FOR HTTP_X_FORWARDED_HOST
|
|
9
|
+
HTTP_X_FORWARDED_PROTO HTTP_X_FORWARDED_SSL HTTP_X_REAL_IP].freeze
|
|
10
|
+
|
|
11
|
+
def show
|
|
12
|
+
render json: authorized_resources
|
|
13
|
+
|
|
14
|
+
print_timings
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def authorized_resource(opts)
|
|
20
|
+
return response_for_wrong_host(opts) if wrong_host?(opts[:iri])
|
|
21
|
+
|
|
22
|
+
include = opts[:include].to_s == 'true'
|
|
23
|
+
|
|
24
|
+
response_from_request(include, RDF::URI(opts[:iri]))
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
handle_resource_error(opts, e)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def authorized_resources
|
|
30
|
+
@authorized_resources ||=
|
|
31
|
+
params
|
|
32
|
+
.require(:resources)
|
|
33
|
+
.map { |param| param.permit(:include, :iri) }
|
|
34
|
+
.map(&method(:timed_authorized_resource))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def handle_resource_error(opts, error)
|
|
38
|
+
log_resource_error(error)
|
|
39
|
+
status = error_status(error)
|
|
40
|
+
body = error_body(status, error, opts[:iri]) if opts[:include].to_s == 'true'
|
|
41
|
+
|
|
42
|
+
resource_response(
|
|
43
|
+
opts[:iri],
|
|
44
|
+
body: body,
|
|
45
|
+
status: status
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def error_body(status, error, iri)
|
|
50
|
+
resource_body(error_resource(status, error, iri))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def log_resource_error(error)
|
|
54
|
+
return unless log_resource_error?(error)
|
|
55
|
+
|
|
56
|
+
Rails.logger.error(error)
|
|
57
|
+
Rails.logger.error(error.backtrace.join("\n"))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def log_resource_error?(error)
|
|
61
|
+
!Rails.env.production? && error_status(error) >= 500
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def print_timings
|
|
65
|
+
Rails.logger.debug(
|
|
66
|
+
"\n CPU system user+system real inc status cache iri\n" \
|
|
67
|
+
"#{timings.join("\n")}\n" \
|
|
68
|
+
" User: #{current_user.class}(#{current_user.id})"
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def require_doorkeeper_token?
|
|
73
|
+
false
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def resource_body(resource)
|
|
77
|
+
return if resource.nil?
|
|
78
|
+
|
|
79
|
+
serializer_options = RDF::Serializers::Renderers.transform_opts(
|
|
80
|
+
{include: resource&.try(:preview_includes)},
|
|
81
|
+
serializer_params
|
|
82
|
+
)
|
|
83
|
+
RDF::Serializers.serializer_for(resource).new(resource, serializer_options).send(:render_hndjson)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def resource_response_body(iri, rack_body, status)
|
|
87
|
+
return rack_body.body if rack_body.is_a?(ActionDispatch::Response::RackBody)
|
|
88
|
+
|
|
89
|
+
error_body(status, StandardError.new(I18n.t("linked_rails.status.#{status}")), iri)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def resource_request(iri)
|
|
93
|
+
env = resource_request_env(iri)
|
|
94
|
+
req = ActionDispatch::Request.new(env)
|
|
95
|
+
req.path_info = ActionDispatch::Journey::Router::Utils.normalize_path(req.path_info)
|
|
96
|
+
req.env['Current-User'] = current_user
|
|
97
|
+
req.env['Doorkeeper-Token'] = doorkeeper_token
|
|
98
|
+
|
|
99
|
+
req
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def resource_request_env(iri)
|
|
103
|
+
path = sanitized_relative_path(iri.dup)
|
|
104
|
+
opts = resource_request_headers(iri)
|
|
105
|
+
Rack::MockRequest.env_for(path, opts)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def resource_request_headers(iri)
|
|
109
|
+
fullpath = iri.query.blank? ? iri.path : "#{iri.path}?#{iri.query}"
|
|
110
|
+
|
|
111
|
+
request.env.slice(*REQUEST_HEADERS).merge(
|
|
112
|
+
'HTTP_ACCEPT' => 'application/hex+x-ndjson',
|
|
113
|
+
'HTTP_OPERATOR_ARG_GRAPH' => 'true',
|
|
114
|
+
'ORIGINAL_FULLPATH' => fullpath
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def resource_response(iri, **opts)
|
|
119
|
+
{
|
|
120
|
+
body: nil,
|
|
121
|
+
cache: :private,
|
|
122
|
+
iri: iri,
|
|
123
|
+
status: 404
|
|
124
|
+
}.merge(opts)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def response_for_wrong_host(opts)
|
|
128
|
+
iri = opts[:iri]
|
|
129
|
+
term = term_from_vocab(iri)
|
|
130
|
+
return resource_response(iri) unless term
|
|
131
|
+
|
|
132
|
+
ontology_term_response(iri, term, opts[:include])
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def term_from_vocab(iri)
|
|
136
|
+
vocab = Vocab.for(iri)
|
|
137
|
+
tag = iri.split(vocab.to_s).last
|
|
138
|
+
vocab[tag]
|
|
139
|
+
rescue NoMethodError
|
|
140
|
+
nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def ontology_term_response(iri, term, include)
|
|
144
|
+
resource_response(
|
|
145
|
+
iri,
|
|
146
|
+
body: include ? resource_body(LinkedRails.ontology_property_class.new(iri: term)) : nil,
|
|
147
|
+
cache: :public,
|
|
148
|
+
language: I18n.locale,
|
|
149
|
+
status: 200
|
|
150
|
+
)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def response_from_request(include, iri) # rubocop:disable Metrics/AbcSize
|
|
154
|
+
status, headers, rack_body = Rails.application.routes.router.serve(resource_request(iri))
|
|
155
|
+
cache_from_header = headers['Cache-Control']&.squish&.presence
|
|
156
|
+
|
|
157
|
+
resource_response(
|
|
158
|
+
iri.to_s,
|
|
159
|
+
body: include ? resource_response_body(iri, rack_body, status) : nil,
|
|
160
|
+
cache: %w[no-cache private public].include?(cache_from_header.to_s.downcase) ? cache_from_header : :private,
|
|
161
|
+
language: response_language(headers),
|
|
162
|
+
status: status
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def response_language(headers)
|
|
167
|
+
headers['Content-Language'] || I18n.locale
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def sanitized_relative_path(iri) # rubocop:disable Metrics/AbcSize
|
|
171
|
+
iri.path = "#{iri.path}/" unless iri.path&.ends_with?('/')
|
|
172
|
+
uri = URI(LinkedRails.iri.path.present? ? iri.to_s.split("#{LinkedRails.iri.path}/").last : iri)
|
|
173
|
+
|
|
174
|
+
[uri.path, uri.query].compact.join('?')
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def timings
|
|
178
|
+
@timings ||= []
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def timed_authorized_resource(resource)
|
|
182
|
+
res = nil
|
|
183
|
+
time = Benchmark.measure { res = authorized_resource(resource) }
|
|
184
|
+
unless Rails.env.production?
|
|
185
|
+
include = resource[:include].to_s.ljust(5)
|
|
186
|
+
timings << "#{time.to_s[0..-2]} - #{include} #{res[:status]} #{res[:cache]} #{resource[:iri]}"
|
|
187
|
+
end
|
|
188
|
+
res
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def wrong_host?(iri)
|
|
192
|
+
!iri.starts_with?(LinkedRails.iri)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LinkedRails
|
|
4
|
+
class CurrentUserController < LinkedRails.controller_parent_class
|
|
5
|
+
active_response :show
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def current_resource
|
|
10
|
+
@current_resource ||= LinkedRails.current_user_class.new(user: current_user)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LinkedRails
|
|
4
|
+
class EnumValuesController < LinkedRails.controller_parent_class
|
|
5
|
+
active_response :index
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def enum_options!
|
|
10
|
+
serializer_class!.enum_options(params[:attribute]) || raise(ActiveRecord::RecordNotFound)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def requested_resource
|
|
14
|
+
return super unless action_name == 'index'
|
|
15
|
+
|
|
16
|
+
@requested_resource ||= LinkedRails::Sequence.new(
|
|
17
|
+
enum_options!.values,
|
|
18
|
+
id: index_iri,
|
|
19
|
+
scope: LinkedRails::EnumValuePolicy::Scope
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def model_class
|
|
24
|
+
@model_class ||= self.class.linked_models.detect do |klass|
|
|
25
|
+
klass.to_s == ([params[:module]].compact + [params[:klass]&.singularize]).join('/').classify
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def model_class!
|
|
30
|
+
model_class || raise(ActiveRecord::RecordNotFound)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def serializer_class
|
|
34
|
+
@serializer_class ||= RDF::Serializers.serializer_for(model_class!)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def serializer_class!
|
|
38
|
+
serializer_class || raise(ActiveRecord::RecordNotFound)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class << self
|
|
42
|
+
def linked_models
|
|
43
|
+
@linked_models ||= ObjectSpace.each_object(Class).select do |c|
|
|
44
|
+
c.included_modules.include?(LinkedRails::Model)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LinkedRails
|
|
4
|
+
class ManifestsController < LinkedRails.controller_parent_class
|
|
5
|
+
def show
|
|
6
|
+
render json: current_resource.web_manifest
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def tenant
|
|
10
|
+
render json: {
|
|
11
|
+
iri_prefix: LinkedRails.iri.host
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def current_resource
|
|
18
|
+
@current_resource ||= LinkedRails.manifest_class.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LinkedRails
|
|
4
|
+
class NotFoundController < LinkedRails.controller_parent_class
|
|
5
|
+
def show
|
|
6
|
+
handle_error(ActionController::RoutingError.new('Route not found'))
|
|
7
|
+
rescue ActionController::UnknownFormat
|
|
8
|
+
head 404
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def authorize_action; end
|
|
14
|
+
end
|
|
15
|
+
end
|