hub_kernel-api 0.6.0 → 0.8.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 +4 -4
- data/README.md +10 -4
- data/app/controllers/hub_kernel/api/hub_calls_controller.rb +2 -14
- data/lib/hub_kernel/api/version.rb +1 -1
- data/lib/hub_kernel/api.rb +7 -20
- data/the_local/agents/hub_kernel-api-develop.md +8 -9
- data/the_local/agents/hub_kernel-api-info.md +8 -5
- data/the_local/agents/hub_kernel-api-install.md +15 -12
- data/the_local/interface.yml +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a1ab149c312d3eededfba4646f9903a4113369fed1869f5e9165623d60e05b0d
|
|
4
|
+
data.tar.gz: 0c3f1837992e569bb231859be331eabaf3dfa0d37f7f4494078bed6fb1e8d68e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00c278912444e2bf2ad857e06a48fc16d166e251d2e51ee3a60679e7149eb422c1e49eb46340273a22774104a152b5b1506bd705898484ff20f0a36b036e2377
|
|
7
|
+
data.tar.gz: 8eb8929362a24395413e2191cc40e5f6d99089f13624bcb8b917af814c1bedfd7022aa75ef9541d5beeb7d1ba60c5c5ed0c597f8a87f951f97d0b183a9274144
|
data/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# hub_kernel-api
|
|
2
2
|
|
|
3
3
|
Serves a hub_kernel hub's exposed methods as a JSON API. The host lists the hubs it
|
|
4
|
-
serves, and every call goes through the host's own sign-in, then
|
|
5
|
-
|
|
4
|
+
serves, and every call goes through the host's own sign-in, then the permission check and
|
|
5
|
+
account scope that hub_kernel-interface holds. It depends on hub_kernel-interface alone, not
|
|
6
|
+
on hub_kernel.
|
|
6
7
|
|
|
7
8
|
## Usage
|
|
8
9
|
|
|
@@ -26,8 +27,13 @@ exposes no methods, when two served hubs answer at the same address, or when a s
|
|
|
26
27
|
hub's exposed list has a problem, naming each. Inside `to_prepare` it runs again after
|
|
27
28
|
every code reload.
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
`HubKernel::Api.hubs` reads and writes hub_kernel-interface's one served list,
|
|
31
|
+
`HubKernel::Interface.hubs`, so every interface gem in the host, such as hub_kernel-mcp,
|
|
32
|
+
serves the same hubs at the same names. The list is set once, through either gem.
|
|
33
|
+
|
|
34
|
+
The base controller's own sign-in runs before every call. The permission check and account
|
|
35
|
+
scope must also be set, `HubKernel::Authz.check` and `HubKernel::Context.scope`, as
|
|
36
|
+
hub_kernel-interface's readme describes. Mount the engine:
|
|
31
37
|
|
|
32
38
|
```ruby
|
|
33
39
|
mount HubKernel::Api::Engine => "/api/v1/hubs"
|
|
@@ -8,8 +8,8 @@ module HubKernel
|
|
|
8
8
|
|
|
9
9
|
def answer
|
|
10
10
|
raise ActionController::RoutingError, "Not found" unless asked_with_the_right_verb?
|
|
11
|
-
return refuse_unlisted_values if unlisted_values.any?
|
|
12
11
|
|
|
12
|
+
HubKernel::Interface::CallReasons.refuse_unlisted_values(hub, params[:name], values: values, person: caller_person, account: caller_account)
|
|
13
13
|
render json: { answer: hub.call_exposed(params[:name], values: values, person: caller_person, account: caller_account) }
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -17,23 +17,11 @@ module HubKernel
|
|
|
17
17
|
|
|
18
18
|
def asked_with_the_right_verb? = hub.exposed(params[:name])&.writes == request.post?
|
|
19
19
|
|
|
20
|
-
def refuse_unlisted_values
|
|
21
|
-
raise HubKernel::NotAllowed unless permitted?
|
|
22
|
-
|
|
23
|
-
refused(HubKernel::Refused.new("#{params[:name]} does not take #{unlisted_values.join(", ")}"))
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def permitted? = hub.exposures_for(person: caller_person, account: caller_account).any? { |exposure| exposure.name.to_s == params[:name] }
|
|
27
|
-
|
|
28
|
-
def unlisted_values = values.keys - hub.exposed(params[:name]).takes
|
|
29
|
-
|
|
30
20
|
def values = request.query_parameters.merge(request.request_parameters).deep_symbolize_keys
|
|
31
21
|
|
|
32
22
|
def refused(refusal) = render(json: { error: refusal.message }, status: :unprocessable_content)
|
|
33
23
|
|
|
34
|
-
def missing_record(missing)
|
|
35
|
-
render json: { error: "No #{missing.model.demodulize.underscore.humanize(capitalize: false)} has the id #{missing.id}" }, status: :not_found
|
|
36
|
-
end
|
|
24
|
+
def missing_record(missing) = render(json: { error: HubKernel::Interface::CallReasons.missing_record(missing) }, status: :not_found)
|
|
37
25
|
end
|
|
38
26
|
end
|
|
39
27
|
end
|
data/lib/hub_kernel/api.rb
CHANGED
|
@@ -1,36 +1,23 @@
|
|
|
1
|
-
require "hub_kernel"
|
|
1
|
+
require "hub_kernel-interface"
|
|
2
2
|
require "hub_kernel/api/version"
|
|
3
3
|
require "hub_kernel/api/engine"
|
|
4
4
|
|
|
5
5
|
module HubKernel
|
|
6
6
|
module Api
|
|
7
|
-
|
|
7
|
+
UnservableHubError = HubKernel::Interface::UnservableHubError
|
|
8
8
|
|
|
9
|
-
mattr_accessor :hubs, default: []
|
|
10
9
|
mattr_accessor :base_controller, default: "ActionController::API"
|
|
11
10
|
mattr_accessor :person_method
|
|
12
11
|
mattr_accessor :account_method
|
|
13
12
|
|
|
14
|
-
def self.
|
|
13
|
+
def self.hubs = HubKernel::Interface.hubs
|
|
15
14
|
|
|
16
|
-
def self.
|
|
17
|
-
|
|
18
|
-
raise UnservableHubError, problems.join("\n") if problems.any?
|
|
15
|
+
def self.hubs=(hubs)
|
|
16
|
+
HubKernel::Interface.hubs = hubs
|
|
19
17
|
end
|
|
20
18
|
|
|
21
|
-
def self.
|
|
19
|
+
def self.find(name) = HubKernel::Interface.find(name)
|
|
22
20
|
|
|
23
|
-
def self.
|
|
24
|
-
|
|
25
|
-
def self.unexposed_hubs = served.map(&:last).reject { |hub| hub.respond_to?(:exposures) }.map { |hub| "#{hub.name} exposes no methods to serve" }
|
|
26
|
-
|
|
27
|
-
def self.shared_addresses
|
|
28
|
-
served.group_by(&:first).select { |_address, entries| entries.size > 1 }.map do |address, entries|
|
|
29
|
-
"#{entries.map { |_address, hub| hub.name }.join(" and ")} both answer at #{address}"
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def self.exposure_problems = served.map(&:last).select { |hub| hub.respond_to?(:exposure_problems) }.flat_map(&:exposure_problems)
|
|
34
|
-
private_class_method :served, :unexposed_hubs, :shared_addresses, :exposure_problems
|
|
21
|
+
def self.check! = HubKernel::Interface.check!
|
|
35
22
|
end
|
|
36
23
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: hub_kernel-api-develop
|
|
3
3
|
description: Use PROACTIVELY for calling a served hub over HTTP — listing the methods a caller may call at a hub's address, calling a read with GET, calling a write with POST, sending its values, and reading its answer or error status — MUST BE USED instead of hand-writing a controller or endpoint per hub method, or guessing at the API's responses.
|
|
4
4
|
tools: Read, Write, Edit, Grep
|
|
5
|
-
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel's permission check and account scope
|
|
5
|
+
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel-interface's permission check and account scope
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
This local writes client code against the three endpoints below and follows the steps in
|
|
@@ -11,11 +11,11 @@ order. Where a step names a decision, it asks the developer and does not pick.
|
|
|
11
11
|
## What hub_kernel-api is
|
|
12
12
|
|
|
13
13
|
A Rails engine that answers HTTP calls to the exposed methods of the hubs a host serves,
|
|
14
|
-
each call made after the host's sign-in and checked and scoped by
|
|
15
|
-
|
|
16
|
-
request test that calls those methods, or when working out why a
|
|
17
|
-
Adding the gem, choosing the served hubs and mounting the engine
|
|
18
|
-
local.
|
|
14
|
+
each call made after the host's sign-in and checked and scoped by the permission check and
|
|
15
|
+
account scope that hub_kernel-interface holds. Use this local when writing a front end,
|
|
16
|
+
mobile app, service or request test that calls those methods, or when working out why a
|
|
17
|
+
call answered as it did. Adding the gem, choosing the served hubs and mounting the engine
|
|
18
|
+
belong to the install local.
|
|
19
19
|
|
|
20
20
|
## Interface
|
|
21
21
|
|
|
@@ -32,8 +32,7 @@ Every path is relative to the path the host mounted the engine at, such as
|
|
|
32
32
|
## How to use it
|
|
33
33
|
|
|
34
34
|
1. Find the path the host mounted the API at in its `config/routes.rb`. Every URL
|
|
35
|
-
below starts with it. If the API is not mounted,
|
|
36
|
-
stop and use the install local.
|
|
35
|
+
below starts with it. If the API is not mounted, stop and use the install local.
|
|
37
36
|
|
|
38
37
|
2. Find the hub's address. A hub answers at its module name underscored, so `Supplies`
|
|
39
38
|
answers at `supplies`, unless the host listed it under a name of its own, such as
|
|
@@ -106,6 +105,6 @@ Every path is relative to the path the host mounted the engine at, such as
|
|
|
106
105
|
- The account a call is made for comes from the host's sign-in, never from a value in the
|
|
107
106
|
request.
|
|
108
107
|
- Only the methods a hub exposes are reachable; adding a method to the API means exposing
|
|
109
|
-
it on the hub
|
|
108
|
+
it on the hub, not adding a route.
|
|
110
109
|
- Installing the gem, configuring it and choosing the served hubs are out of scope here;
|
|
111
110
|
they belong to the install local.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: hub_kernel-api-info
|
|
3
3
|
description: Use to learn what hub_kernel-api offers — serving a hub's exposed methods as a JSON API, the served hubs and their addresses, reads and writes, and how sign-in, permission and account scope apply to each call.
|
|
4
4
|
tools: Read
|
|
5
|
-
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel's permission check and account scope
|
|
5
|
+
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel-interface's permission check and account scope
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
This local explains hub_kernel-api and makes no changes.
|
|
@@ -15,10 +15,13 @@ gem answers HTTP calls to their exposed methods and to a listing of them. It add
|
|
|
15
15
|
business logic of its own: every answer is the return value of a method the hub
|
|
16
16
|
already exposes.
|
|
17
17
|
|
|
18
|
+
It depends on hub_kernel-interface alone, not on hub_kernel. hub_kernel-interface
|
|
19
|
+
holds the permission check and the account scope, and the host sets both.
|
|
20
|
+
|
|
18
21
|
Reach for it when a hub's exposed methods need to be called over HTTP, by a mobile
|
|
19
22
|
app, another service or a front end, without writing a controller per method. Each
|
|
20
|
-
call runs the host's own sign-in first, then hub_kernel's permission check
|
|
21
|
-
account scope, so the API never shows a caller more than the app itself would.
|
|
23
|
+
call runs the host's own sign-in first, then hub_kernel-interface's permission check
|
|
24
|
+
and account scope, so the API never shows a caller more than the app itself would.
|
|
22
25
|
|
|
23
26
|
## Interface
|
|
24
27
|
|
|
@@ -40,8 +43,8 @@ This local declares no commands. The surface is split between the other two loca
|
|
|
40
43
|
|
|
41
44
|
## Conventions
|
|
42
45
|
|
|
43
|
-
- **Hub** — a
|
|
44
|
-
methods are reachable; nothing else on the hub is.
|
|
46
|
+
- **Hub** — a module whose methods are declared as exposed through
|
|
47
|
+
hub_kernel-interface. Only exposed methods are reachable; nothing else on the hub is.
|
|
45
48
|
- **Served hub** — a hub the host has listed for the API. A hub that is not served is
|
|
46
49
|
answered as not found, as if it did not exist.
|
|
47
50
|
- **Address** — the name a served hub answers at. By default it is the hub's module
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: hub_kernel-api-install
|
|
3
3
|
description: Use to hook hub_kernel-api into a project — adding the gem, naming the base controller and its person and account methods, listing the served hubs, running the startup check, and mounting the engine.
|
|
4
4
|
tools: Bash, Read, Edit
|
|
5
|
-
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel's permission check and account scope
|
|
5
|
+
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel-interface's permission check and account scope
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
This local follows the steps below exactly and invents none. Where a step names a
|
|
@@ -10,12 +10,13 @@ decision, it asks the developer and does not pick.
|
|
|
10
10
|
|
|
11
11
|
## What hub_kernel-api is
|
|
12
12
|
|
|
13
|
-
A Rails engine that serves the exposed methods of hub_kernel hubs as a JSON API
|
|
13
|
+
A Rails engine that serves the exposed methods of hub_kernel hubs as a JSON API. Hook it
|
|
14
14
|
in when a Rails app needs its hubs callable over HTTP.
|
|
15
15
|
|
|
16
16
|
## Interface
|
|
17
17
|
|
|
18
|
-
- `gem "hub_kernel-api"` — the Gemfile line that adds the gem; it brings
|
|
18
|
+
- `gem "hub_kernel-api"` — the Gemfile line that adds the gem; it brings
|
|
19
|
+
hub_kernel-interface with it, and not hub_kernel.
|
|
19
20
|
- `HubKernel::Api.base_controller=` — the name, as a String, of the host controller the
|
|
20
21
|
API's controllers inherit from; defaults to `"ActionController::API"`.
|
|
21
22
|
- `HubKernel::Api.person_method=` — the name, as a Symbol, of the method on the base
|
|
@@ -37,10 +38,11 @@ in when a Rails app needs its hubs callable over HTTP.
|
|
|
37
38
|
gem "hub_kernel-api"
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
2. Confirm
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
2. Confirm the permission check and account scope that hub_kernel-interface holds are
|
|
42
|
+
already set in the host: `HubKernel::Authz.check` and `HubKernel::Context.scope`.
|
|
43
|
+
Every call is checked and scoped by them. If the host has a hub_kernel-interface
|
|
44
|
+
install local, use it for this. Otherwise stop and ask the developer how they are
|
|
45
|
+
set, and do not set them from guesswork.
|
|
44
46
|
|
|
45
47
|
3. Ask the developer which controller the API inherits from. It must:
|
|
46
48
|
- run the host's sign-in before every action, as a `before_action` that refuses an
|
|
@@ -56,8 +58,7 @@ in when a Rails app needs its hubs callable over HTTP.
|
|
|
56
58
|
4. Ask the developer which hubs to serve and at what address each answers. A hub module
|
|
57
59
|
answers at its module name underscored, so `Supplies` answers at `supplies`. To use a
|
|
58
60
|
different address, the hub is listed as a one-pair Hash, `{ "money" => Billing::Ledger }`.
|
|
59
|
-
Every listed hub must
|
|
60
|
-
an address.
|
|
61
|
+
Every listed hub must expose methods, and no two may share an address.
|
|
61
62
|
|
|
62
63
|
5. Create `config/initializers/hub_kernel_api.rb` with the answers from steps 3 and 4:
|
|
63
64
|
|
|
@@ -88,11 +89,11 @@ in when a Rails app needs its hubs callable over HTTP.
|
|
|
88
89
|
7. Boot the app, for example with `bin/rails runner "puts :ok"`. A
|
|
89
90
|
`HubKernel::Api::UnservableHubError` at boot names each problem:
|
|
90
91
|
- `<Hub> exposes no methods to serve` — the entry is not a hub with exposed methods;
|
|
91
|
-
remove it, or expose methods on it
|
|
92
|
+
remove it, or expose methods on it.
|
|
92
93
|
- `<Hub> and <Hub> both answer at <address>` — give one of them its own address with
|
|
93
94
|
a one-pair Hash.
|
|
94
|
-
- Any other line is a problem with
|
|
95
|
-
|
|
95
|
+
- Any other line is a problem the hub reports with its own list of exposed methods;
|
|
96
|
+
fix it in the hub.
|
|
96
97
|
|
|
97
98
|
## Conventions
|
|
98
99
|
|
|
@@ -102,5 +103,7 @@ in when a Rails app needs its hubs callable over HTTP.
|
|
|
102
103
|
- An edit to the initializer takes effect only after the server restarts.
|
|
103
104
|
- Keep `HubKernel::Api.check!` in the initializer; without it a hub that cannot be served
|
|
104
105
|
is found only when a client calls it.
|
|
106
|
+
- Setting the permission check and account scope is out of scope here; it belongs to
|
|
107
|
+
hub_kernel-interface.
|
|
105
108
|
- Calling the API, its responses and its error statuses are out of scope here; they
|
|
106
109
|
belong to the develop local.
|
data/the_local/interface.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel's permission check and account scope
|
|
1
|
+
scope: hub JSON API — serving a hub_kernel hub's exposed methods as a JSON API in a host Rails app, each call behind the host's own sign-in and hub_kernel-interface's permission check and account scope
|
|
2
2
|
|
|
3
3
|
install:
|
|
4
4
|
- gem "hub_kernel-api"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hub_kernel-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- tylercschneider
|
|
@@ -24,19 +24,19 @@ dependencies:
|
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: 8.1.3
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: hub_kernel
|
|
27
|
+
name: hub_kernel-interface
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0.
|
|
32
|
+
version: '0.6'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.
|
|
39
|
+
version: '0.6'
|
|
40
40
|
description: 'hub_kernel-api gives any hub built on hub_kernel a JSON API: the host
|
|
41
41
|
lists the hubs it serves, and every call goes through the host''s sign-in, permission
|
|
42
42
|
check and account scope.'
|