atlas_rb 0.0.101 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94b1cf416b2dbd60cd0e87960302dc5bb4be7207576608ecbe521cdb28d20255
4
- data.tar.gz: d3d716929b9d246d761385142858e95e628f4e50510a3c583dd90ae8e70613c4
3
+ metadata.gz: 7f8b62042df9f4d715469ba7cf23dcf352485552aa9d73c55290312c3055800c
4
+ data.tar.gz: d435ed7a4fb953f2d82dd6f304232731802b2e8fe68a5e055fecd51e972c560a
5
5
  SHA512:
6
- metadata.gz: 1c232e3e98c972d7c551106e5befb4b52f0b5befcba7ae15eeaf32ac1f2471062a90f4034a04e63caa3991625b6a5f4ca95de15cc395b0abaca8e62ad92ee5d3
7
- data.tar.gz: 660c2326caa5f323fb83236144f6f41318e3b375d8e1d7a39ab48742c2acc86567686fef8cd2bf01136e91a8a300a53762c1ad9f2d3f449195a592a6dfa43178
6
+ metadata.gz: 3dffc895e6bee5bce6dbe907488a72a240c55b7d5ae5a506bff61d81a451a97490090d576c575fa07cf82ffbaf023109a9938aa66adf872e892b3a2fc37f3e13
7
+ data.tar.gz: 7076d8304048de5f20b8560875fbaddcac8ab29a4c3cf3d37ac54b95c3bac4cb6aff56bc503967ec3a5e41289bf4173055b9d8ced278ac9b63849231e0e09ea2
data/.version CHANGED
@@ -1 +1 @@
1
- 0.0.101
1
+ 1.0.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,131 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 — major restructure: namespace gradient + ambient identity
4
+
5
+ This release reshapes the gem's API surface. Downstream consumers
6
+ (Cerberus) need to update call sites — see the migration section
7
+ below.
8
+
9
+ ### Added
10
+
11
+ - **`AtlasRb.configure { |c| ... }`** — configurable defaults for
12
+ ambient identity:
13
+ - `config.default_nuid` — callable invoked when a resource method
14
+ is called without an explicit `nuid:` kwarg. Lets host apps
15
+ register `-> { Current.nuid }` once instead of threading
16
+ `nuid: Current.nuid` at every call site.
17
+ - `config.default_on_behalf_of` — callable for the
18
+ `On-Behalf-Of:` header, used by acting-as / view-as flows.
19
+ - **`on_behalf_of:` kwarg** on every resource method that already
20
+ took `nuid:`. Sent as the `On-Behalf-Of: NUID <nuid>` header when
21
+ set. Falls through to `config.default_on_behalf_of` when omitted.
22
+ - **`AtlasRb::Admin::*` namespace** — destructive lifecycle ops:
23
+ - `AtlasRb::Admin::Work.destroy` / `.restore`
24
+ - `AtlasRb::Admin::Collection.destroy` / `.restore`
25
+ - `AtlasRb::Admin::Community.destroy` / `.restore`
26
+
27
+ Every `destroy` requires `confirm: :i_understand`. Missing or
28
+ wrong value raises `ArgumentError` before any wire request.
29
+ - **`AtlasRb::System::*` namespace** — system-context calls:
30
+ - `AtlasRb::System::User.find_or_create` (moved from
31
+ `AtlasRb::User.find_or_create`).
32
+ - `AtlasRb::System::NUID` constant — the seeded `:system` fixture's
33
+ NUID (`"000000000"`).
34
+ - **`FaradayHelper#system_connection`** — Faraday factory that
35
+ authenticates with `Rails.application.credentials.atlas_system_token`
36
+ and the system NUID. Never consults the configured defaults. Used
37
+ exclusively by `AtlasRb::System::*`.
38
+
39
+ ### Removed (breaking)
40
+
41
+ - `AtlasRb::Work.destroy`, `AtlasRb::Work.restore` → move to
42
+ `AtlasRb::Admin::Work`.
43
+ - `AtlasRb::Collection.destroy`, `AtlasRb::Collection.restore` →
44
+ move to `AtlasRb::Admin::Collection`.
45
+ - `AtlasRb::Community.destroy`, `AtlasRb::Community.restore` →
46
+ move to `AtlasRb::Admin::Community`.
47
+ - `AtlasRb::User.find_or_create` → moves to
48
+ `AtlasRb::System::User.find_or_create`. The class
49
+ `AtlasRb::User` is gone.
50
+
51
+ ### Changed
52
+
53
+ - `Work.tombstone`, `Collection.tombstone`, `Community.tombstone`
54
+ relax `nuid:` from required-kwarg to `nuid: nil`. The fall-through
55
+ resolution in `FaradayHelper#connection` handles the lookup. Atlas
56
+ still requires a real NUID on the wire for tombstone audit; if
57
+ neither the call site nor the configured default supplies one, the
58
+ request will hit Atlas without a `User:` header and Atlas will
59
+ reject it.
60
+
61
+ ### Migration
62
+
63
+ For consumers (Cerberus piece 6):
64
+
65
+ 1. Register the ambient defaults in `config/initializers/atlas_rb.rb`:
66
+
67
+ ```ruby
68
+ AtlasRb.configure do |config|
69
+ config.default_nuid = -> { Current.nuid }
70
+ config.default_on_behalf_of = -> { Current.on_behalf_of }
71
+ end
72
+ ```
73
+
74
+ 2. Drop `nuid: Current.nuid` from regular call sites:
75
+
76
+ ```ruby
77
+ # Before
78
+ AtlasRb::Work.find(id, nuid: Current.nuid)
79
+ AtlasRb::Blob.create(work_id, path, name, nuid: Current.nuid)
80
+
81
+ # After
82
+ AtlasRb::Work.find(id)
83
+ AtlasRb::Blob.create(work_id, path, name)
84
+ ```
85
+
86
+ Sites that need a *different* NUID than `Current.nuid` keep their
87
+ explicit kwarg — caller value always wins.
88
+
89
+ 3. Rewrite destructive call sites:
90
+
91
+ ```ruby
92
+ # Before
93
+ AtlasRb::Work.destroy(id, nuid: Current.nuid)
94
+ AtlasRb::Work.restore(id, nuid: Current.nuid)
95
+
96
+ # After
97
+ AtlasRb::Admin::Work.destroy(id, confirm: :i_understand)
98
+ AtlasRb::Admin::Work.restore(id)
99
+ ```
100
+
101
+ 4. Rewrite the SSO callback's user-provisioning call:
102
+
103
+ ```ruby
104
+ # Before
105
+ AtlasRb::User.find_or_create(nuid: ..., groups: ...)
106
+
107
+ # After
108
+ AtlasRb::System::User.find_or_create(nuid: ..., groups: ...)
109
+ ```
110
+
111
+ 5. Add the system token to encrypted credentials:
112
+
113
+ ```yaml
114
+ # config/credentials.yml.enc
115
+ atlas_system_token: <value Atlas's require_auth recognises as :system>
116
+ ```
117
+
118
+ This is paired on the Atlas side with
119
+ `Rails.application.credentials.system_token` (Atlas 0.6.20+).
120
+
121
+ ## 0.0.101
122
+
123
+ - Threaded `nuid:` through the remaining gaps in `Work` / `Collection`
124
+ / `Community` / `FileSet` / `Delegate`.
125
+ - Fixed `multipart({})` bug at `file_set.rb:83` — the literal `{}`
126
+ bound to the `nuid` positional arg, so the gem emitted
127
+ `User: NUID {}` on the wire for `FileSet.update`.
128
+
129
+ ## 0.0.100 and earlier
130
+
131
+ See `git log` for pre-1.0 history.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atlas_rb (0.0.101)
4
+ atlas_rb (1.0.0)
5
5
  faraday (~> 2.7)
6
6
  faraday-follow_redirects (~> 0.3.0)
7
7
  faraday-multipart (~> 1)
data/README.md CHANGED
@@ -23,22 +23,77 @@ Then `bundle install`, or install standalone with `gem install atlas_rb`.
23
23
 
24
24
  ## Configuration
25
25
 
26
- Every request reads two environment variables:
26
+ ### Environment variables
27
+
28
+ Every regular-path request reads two environment variables:
27
29
 
28
30
  | Variable | Purpose |
29
31
  |---------------|---------------------------------------------------------------|
30
32
  | `ATLAS_URL` | Base URL of the Atlas API (e.g. `https://atlas.example.edu`). |
31
- | `ATLAS_TOKEN` | Bearer token used in the `Authorization` header. |
32
-
33
- User-scoped calls (currently only `AtlasRb::Authentication`) additionally
34
- accept an NUID — the Northeastern University ID — which is forwarded in a
35
- `User: NUID <nuid>` header.
33
+ | `ATLAS_TOKEN` | Bearer token used in the `Authorization` header. |
36
34
 
37
35
  ```ruby
38
36
  ENV["ATLAS_URL"] = "https://atlas.example.edu"
39
37
  ENV["ATLAS_TOKEN"] = "..."
40
38
  ```
41
39
 
40
+ ### Ambient identity (`default_nuid` / `default_on_behalf_of`)
41
+
42
+ Every resource method that talks to Atlas accepts a `nuid:` kwarg (the
43
+ acting user) and an `on_behalf_of:` kwarg (the user the call is being
44
+ made *for*, used by acting-as / view-as flows). Both are forwarded as
45
+ `User: NUID <nuid>` and `On-Behalf-Of: NUID <nuid>` headers
46
+ respectively.
47
+
48
+ Rather than threading them at every call site, register callables
49
+ once on app boot and let the gem read them as defaults:
50
+
51
+ ```ruby
52
+ # config/initializers/atlas_rb.rb (Rails)
53
+ AtlasRb.configure do |config|
54
+ config.default_nuid = -> { Current.nuid }
55
+ config.default_on_behalf_of = -> { Current.on_behalf_of }
56
+ end
57
+ ```
58
+
59
+ The lambdas run **at request time** in whatever thread / fiber is
60
+ making the call, so they pick up per-request `Current.*` values that
61
+ `ApplicationController` set up via Devise + Rails 7's
62
+ `ActiveSupport::CurrentAttributes`. Background jobs work the same way
63
+ (ActiveJob ↔ CurrentAttributes integration restores the values on
64
+ `perform`).
65
+
66
+ Caller-passed kwargs always win over the configured defaults:
67
+
68
+ ```ruby
69
+ # Uses Current.nuid:
70
+ AtlasRb::Work.find("w-789")
71
+
72
+ # Uses "X" — explicit kwarg overrides the default:
73
+ AtlasRb::Work.find("w-789", nuid: "X")
74
+ ```
75
+
76
+ If neither the call site nor the registered default supplies a value,
77
+ no header is sent (legacy bearer-only path preserved).
78
+
79
+ ### System-path credentials
80
+
81
+ Calls under `AtlasRb::System::*` (currently just SSO user provisioning)
82
+ authenticate as the seeded Atlas `:system` fixture, not as a real user.
83
+ They use a **separate** bearer token, looked up from
84
+ `Rails.application.credentials.atlas_system_token`. Storing it in
85
+ encrypted credentials rather than `ENV` halves the blast radius of a
86
+ `.env` leak — the user token and the system token can't both leak
87
+ through the same channel.
88
+
89
+ ```yaml
90
+ # config/credentials.yml.enc (Cerberus side)
91
+ atlas_system_token: <token-Atlas-side-recognises-as-:system>
92
+ ```
93
+
94
+ The system NUID itself is hardcoded as `AtlasRb::System::NUID =
95
+ "000000000"`, matching Atlas's seeded `:system` fixture row.
96
+
42
97
  ## Resource hierarchy
43
98
 
44
99
  ```
@@ -60,6 +115,37 @@ Community → Collection → Work
60
115
  | `AtlasRb::Resource` | Generic resolver and permissions lookup. |
61
116
  | `AtlasRb::Reset` | Test-only — wipes Atlas state via `GET /reset`. |
62
117
 
118
+ ## Namespace gradient: regular / Admin / System
119
+
120
+ Operations are split across three namespaces, calibrated to the blast
121
+ radius and the kind of authentication they need:
122
+
123
+ | Namespace | What it does | Auth | Friction |
124
+ |----------------------|------------------------------------------------------------------------------------|-----------------------------------------------------|---------------------------------------|
125
+ | `AtlasRb::*` | Regular CRUD (find / list / create / update / tombstone / metadata, etc.) | User token (`ATLAS_TOKEN`) + acting user's NUID | None — these are the daily-use paths. |
126
+ | `AtlasRb::Admin::*` | Hard delete (`destroy`) and un-tombstone (`restore`) for Work / Collection / Community. | Same as regular — a real operator is acting. | `destroy` requires `confirm: :i_understand`. |
127
+ | `AtlasRb::System::*` | System-context provisioning (currently just SSO user find-or-create). | System token (`Rails.application.credentials.atlas_system_token`) + `User: NUID 000000000`. | The namespace itself is the marker — there is no way to call these as a non-system principal. |
128
+
129
+ ```ruby
130
+ # Regular daily use — picks up Current.nuid via the configured default:
131
+ AtlasRb::Work.find("w-789")
132
+ AtlasRb::Work.tombstone("w-789") # withdrawal (reversible)
133
+
134
+ # Operator-only, with a friction marker:
135
+ AtlasRb::Admin::Work.destroy("w-789", confirm: :i_understand)
136
+ AtlasRb::Admin::Work.restore("w-789")
137
+
138
+ # System-only — authenticates as Atlas's :system fixture:
139
+ AtlasRb::System::User.find_or_create(
140
+ nuid: "001234567",
141
+ groups: ["northeastern:staff", "drs:editors"]
142
+ )
143
+ ```
144
+
145
+ The `AtlasRb::System::*` path never consults `AtlasRb.config.default_nuid`
146
+ or `default_on_behalf_of` — there is no ambient user context on system
147
+ calls.
148
+
63
149
  ### A note on `create` argument shapes
64
150
 
65
151
  The CRUD-twin classes look the same but pass different parent IDs:
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ module Admin
5
+ # Destructive lifecycle operations on a {AtlasRb::Collection}.
6
+ #
7
+ # See {AtlasRb::Admin} for the rationale behind the namespace and the
8
+ # `confirm: :i_understand` friction marker.
9
+ class Collection
10
+ extend AtlasRb::FaradayHelper
11
+
12
+ # Atlas REST endpoint prefix.
13
+ # @api private
14
+ ROUTE = "/collections/"
15
+
16
+ # Hard-delete a Collection.
17
+ #
18
+ # Unrecoverable — prefer {AtlasRb::Collection.tombstone} for
19
+ # user-visible withdrawal. Operator-only.
20
+ #
21
+ # @param id [String] the Collection ID.
22
+ # @param confirm [Symbol] must be `:i_understand`. Any other value
23
+ # raises `ArgumentError`.
24
+ # @param nuid [String, nil] optional acting user's NUID.
25
+ # @param on_behalf_of [String, nil] optional `On-Behalf-Of` NUID.
26
+ # @return [Faraday::Response] the raw delete response.
27
+ # @raise [ArgumentError] if `confirm:` is missing or not the
28
+ # sentinel value.
29
+ #
30
+ # @example
31
+ # AtlasRb::Admin::Collection.destroy("col-456", confirm: :i_understand)
32
+ def self.destroy(id, confirm:, nuid: nil, on_behalf_of: nil)
33
+ unless confirm == :i_understand
34
+ raise ArgumentError,
35
+ "AtlasRb::Admin::Collection.destroy requires confirm: :i_understand"
36
+ end
37
+ connection({}, nuid, on_behalf_of: on_behalf_of).delete(ROUTE + id)
38
+ end
39
+
40
+ # Restore a previously-tombstoned Collection.
41
+ #
42
+ # @param id [String] the Collection ID.
43
+ # @param nuid [String, nil] optional acting user's NUID.
44
+ # @param on_behalf_of [String, nil] optional `On-Behalf-Of` NUID.
45
+ # @return [Faraday::Response] the raw response.
46
+ #
47
+ # @example
48
+ # AtlasRb::Admin::Collection.restore("col-456")
49
+ def self.restore(id, nuid: nil, on_behalf_of: nil)
50
+ connection({}, nuid, on_behalf_of: on_behalf_of).post(ROUTE + id + '/restore')
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ module Admin
5
+ # Destructive lifecycle operations on a {AtlasRb::Community}.
6
+ #
7
+ # See {AtlasRb::Admin} for the rationale behind the namespace and the
8
+ # `confirm: :i_understand` friction marker.
9
+ class Community
10
+ extend AtlasRb::FaradayHelper
11
+
12
+ # Atlas REST endpoint prefix.
13
+ # @api private
14
+ ROUTE = "/communities/"
15
+
16
+ # Hard-delete a Community.
17
+ #
18
+ # Unrecoverable — prefer {AtlasRb::Community.tombstone} for
19
+ # user-visible withdrawal. Operator-only.
20
+ #
21
+ # @param id [String] the Community ID.
22
+ # @param confirm [Symbol] must be `:i_understand`. Any other value
23
+ # raises `ArgumentError`.
24
+ # @param nuid [String, nil] optional acting user's NUID.
25
+ # @param on_behalf_of [String, nil] optional `On-Behalf-Of` NUID.
26
+ # @return [Faraday::Response] the raw delete response.
27
+ # @raise [ArgumentError] if `confirm:` is missing or not the
28
+ # sentinel value.
29
+ #
30
+ # @example
31
+ # AtlasRb::Admin::Community.destroy("c-123", confirm: :i_understand)
32
+ def self.destroy(id, confirm:, nuid: nil, on_behalf_of: nil)
33
+ unless confirm == :i_understand
34
+ raise ArgumentError,
35
+ "AtlasRb::Admin::Community.destroy requires confirm: :i_understand"
36
+ end
37
+ connection({}, nuid, on_behalf_of: on_behalf_of).delete(ROUTE + id)
38
+ end
39
+
40
+ # Restore a previously-tombstoned Community.
41
+ #
42
+ # @param id [String] the Community ID.
43
+ # @param nuid [String, nil] optional acting user's NUID.
44
+ # @param on_behalf_of [String, nil] optional `On-Behalf-Of` NUID.
45
+ # @return [Faraday::Response] the raw response.
46
+ #
47
+ # @example
48
+ # AtlasRb::Admin::Community.restore("c-123")
49
+ def self.restore(id, nuid: nil, on_behalf_of: nil)
50
+ connection({}, nuid, on_behalf_of: on_behalf_of).post(ROUTE + id + '/restore')
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ module Admin
5
+ # Destructive lifecycle operations on a {AtlasRb::Work}.
6
+ #
7
+ # See {AtlasRb::Admin} for the rationale behind the namespace and the
8
+ # `confirm: :i_understand` friction marker.
9
+ class Work
10
+ extend AtlasRb::FaradayHelper
11
+
12
+ # Atlas REST endpoint prefix.
13
+ # @api private
14
+ ROUTE = "/works/"
15
+
16
+ # Hard-delete a Work.
17
+ #
18
+ # Removes the Work, its FileSets, and their Blobs from Atlas
19
+ # storage. Unrecoverable — prefer {AtlasRb::Work.tombstone} for
20
+ # the user-visible withdrawal path. This is operator-only.
21
+ #
22
+ # @param id [String] the Work ID.
23
+ # @param confirm [Symbol] must be `:i_understand`. Any other value
24
+ # (including the kwarg being omitted) raises `ArgumentError`.
25
+ # @param nuid [String, nil] optional acting user's NUID. Falls
26
+ # through to {AtlasRb.config}.default_nuid when omitted.
27
+ # @param on_behalf_of [String, nil] optional NUID for the
28
+ # `On-Behalf-Of` header. Falls through to
29
+ # {AtlasRb.config}.default_on_behalf_of when omitted.
30
+ # @return [Faraday::Response] the raw delete response.
31
+ # @raise [ArgumentError] if `confirm:` is missing or not the
32
+ # sentinel value.
33
+ #
34
+ # @example
35
+ # AtlasRb::Admin::Work.destroy("w-789", confirm: :i_understand)
36
+ def self.destroy(id, confirm:, nuid: nil, on_behalf_of: nil)
37
+ unless confirm == :i_understand
38
+ raise ArgumentError,
39
+ "AtlasRb::Admin::Work.destroy requires confirm: :i_understand"
40
+ end
41
+ connection({}, nuid, on_behalf_of: on_behalf_of).delete(ROUTE + id)
42
+ end
43
+
44
+ # Restore a previously-tombstoned Work.
45
+ #
46
+ # Reverses a withdrawal: search and show pages stop returning a
47
+ # withdrawn stub. Operator-only; typically driven from a Rails
48
+ # console or a future admin panel after the library has decided a
49
+ # withdrawn Work should come back.
50
+ #
51
+ # @param id [String] the Work ID.
52
+ # @param nuid [String, nil] optional acting user's NUID. Falls
53
+ # through to {AtlasRb.config}.default_nuid when omitted.
54
+ # @param on_behalf_of [String, nil] optional NUID for the
55
+ # `On-Behalf-Of` header. Falls through to
56
+ # {AtlasRb.config}.default_on_behalf_of when omitted.
57
+ # @return [Faraday::Response] the raw response.
58
+ #
59
+ # @example
60
+ # AtlasRb::Admin::Work.restore("w-789")
61
+ def self.restore(id, nuid: nil, on_behalf_of: nil)
62
+ connection({}, nuid, on_behalf_of: on_behalf_of).post(ROUTE + id + '/restore')
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ # Operator-only destructive lifecycle operations.
5
+ #
6
+ # Houses methods whose blast radius warrants more friction than the
7
+ # regular CRUD surface: `destroy` (hard delete — content and metadata
8
+ # are unrecoverable) and `restore` (un-tombstone — reverses a withdraw,
9
+ # typically driven from a Rails console session or a future admin UI).
10
+ #
11
+ # ## Why a separate namespace
12
+ #
13
+ # The class itself is the marker: `AtlasRb::Admin::Work.destroy(...)`
14
+ # is structurally distinct from `AtlasRb::Work.update(...)`. Mass-edits
15
+ # and code-search across a consumer codebase can quickly find every
16
+ # destructive call site by grepping `AtlasRb::Admin::`.
17
+ #
18
+ # ## `confirm: :i_understand`
19
+ #
20
+ # Every `destroy` method requires a `confirm: :i_understand` kwarg.
21
+ # Forgetting (or misspelling) it raises `ArgumentError` before any
22
+ # request goes out. The value is arbitrary — the point is that
23
+ # boilerplate-generated or copy-pasted call sites can't accidentally
24
+ # delete production data. `restore` does **not** require the marker;
25
+ # restoring tombstoned content is reversible (by tombstoning again)
26
+ # so the same friction isn't warranted.
27
+ module Admin
28
+ end
29
+ end
data/lib/atlas_rb/blob.rb CHANGED
@@ -20,14 +20,19 @@ module AtlasRb
20
20
  # @param nuid [String, nil] optional acting user's NUID, forwarded as the
21
21
  # `User:` header. Required for cerberus-token requests; legacy bearer
22
22
  # tokens still resolve without it.
23
+ # @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
24
+ # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
25
+ # omitted.
23
26
  # @return [Hash] the `"blob"` object, already unwrapped — typically
24
27
  # includes `"id"`, `"original_filename"`, `"size"`, and a download URL.
25
28
  #
26
29
  # @example
27
30
  # AtlasRb::Blob.find("b-321")
28
31
  # # => { "id" => "b-321", "original_filename" => "scan.pdf", ... }
29
- def self.find(id, nuid: nil)
30
- AtlasRb::Mash.new(JSON.parse(connection({}, nuid).get(ROUTE + id)&.body))['blob']
32
+ def self.find(id, nuid: nil, on_behalf_of: nil)
33
+ AtlasRb::Mash.new(JSON.parse(
34
+ connection({}, nuid, on_behalf_of: on_behalf_of).get(ROUTE + id)&.body
35
+ ))['blob']
31
36
  end
32
37
 
33
38
  # Stream the Blob's binary content through a caller-supplied block.
@@ -41,6 +46,9 @@ module AtlasRb
41
46
  # @param nuid [String, nil] optional acting user's NUID, forwarded as the
42
47
  # `User:` header. Required for cerberus-token requests; legacy bearer
43
48
  # tokens still resolve without it.
49
+ # @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
50
+ # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
51
+ # omitted.
44
52
  # @yieldparam chunk [String] the next chunk of binary data.
45
53
  # @return [Hash] the response headers from `GET /files/<id>/content`.
46
54
  #
@@ -49,9 +57,9 @@ module AtlasRb
49
57
  # headers = AtlasRb::Blob.content("b-321") { |chunk| f.write(chunk) }
50
58
  # puts headers["content-type"]
51
59
  # end
52
- def self.content(id, nuid: nil, &chunk_handler)
60
+ def self.content(id, nuid: nil, on_behalf_of: nil, &chunk_handler)
53
61
  headers = {}
54
- connection({}, nuid).get("#{ROUTE}#{id}/content") do |req|
62
+ connection({}, nuid, on_behalf_of: on_behalf_of).get("#{ROUTE}#{id}/content") do |req|
55
63
  req.options.on_data = proc do |chunk, _bytes_received, env|
56
64
  headers = env.response_headers if headers.empty? && env
57
65
  chunk_handler.call(chunk)
@@ -77,6 +85,9 @@ module AtlasRb
77
85
  # @param nuid [String, nil] optional acting user's NUID, forwarded as the
78
86
  # `User:` header. Required for cerberus-token requests; legacy bearer
79
87
  # tokens still resolve without it.
88
+ # @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
89
+ # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
90
+ # omitted.
80
91
  # @return [Hash] the created `"blob"` payload, including its `"id"`.
81
92
  #
82
93
  # @example
@@ -87,7 +98,7 @@ module AtlasRb
87
98
  # key = SecureRandom.uuid
88
99
  # AtlasRb::Blob.create("w-789", "/tmp/upload.tmp", "thesis.pdf",
89
100
  # idempotency_key: key)
90
- def self.create(id, blob_path, original_filename, idempotency_key: nil, nuid: nil)
101
+ def self.create(id, blob_path, original_filename, idempotency_key: nil, nuid: nil, on_behalf_of: nil)
91
102
  payload = { work_id: id,
92
103
  original_filename: original_filename,
93
104
  binary: Faraday::Multipart::FilePart.new(File.open(blob_path),
@@ -95,7 +106,8 @@ module AtlasRb
95
106
  File.basename(blob_path)) }
96
107
 
97
108
  AtlasRb::Mash.new(JSON.parse(
98
- multipart(nuid, idempotency_key: idempotency_key).post(ROUTE, payload)&.body
109
+ multipart(nuid, on_behalf_of: on_behalf_of, idempotency_key: idempotency_key)
110
+ .post(ROUTE, payload)&.body
99
111
  ))['blob']
100
112
  end
101
113
 
@@ -105,12 +117,15 @@ module AtlasRb
105
117
  # @param nuid [String, nil] optional acting user's NUID, forwarded as the
106
118
  # `User:` header. Required for cerberus-token requests; legacy bearer
107
119
  # tokens still resolve without it.
120
+ # @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
121
+ # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
122
+ # omitted.
108
123
  # @return [Faraday::Response] the raw delete response.
109
124
  #
110
125
  # @example
111
126
  # AtlasRb::Blob.destroy("b-321")
112
- def self.destroy(id, nuid: nil)
113
- connection({}, nuid).delete(ROUTE + id)
127
+ def self.destroy(id, nuid: nil, on_behalf_of: nil)
128
+ connection({}, nuid, on_behalf_of: on_behalf_of).delete(ROUTE + id)
114
129
  end
115
130
 
116
131
  # Replace the bytes of an existing Blob in-place.
@@ -124,15 +139,20 @@ module AtlasRb
124
139
  # @param nuid [String, nil] optional acting user's NUID, forwarded as the
125
140
  # `User:` header. Required for cerberus-token requests; legacy bearer
126
141
  # tokens still resolve without it.
142
+ # @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
143
+ # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
144
+ # omitted.
127
145
  # @return [Hash] the parsed JSON response from the patch.
128
146
  #
129
147
  # @example
130
148
  # AtlasRb::Blob.update("b-321", "/tmp/revised.pdf")
131
- def self.update(id, blob_path, nuid: nil)
149
+ def self.update(id, blob_path, nuid: nil, on_behalf_of: nil)
132
150
  payload = { binary: Faraday::Multipart::FilePart.new(File.open(blob_path),
133
151
  "application/octet-stream",
134
152
  File.basename(blob_path)) }
135
- AtlasRb::Mash.new(JSON.parse(multipart(nuid).patch(ROUTE + id, payload)&.body))
153
+ AtlasRb::Mash.new(JSON.parse(
154
+ multipart(nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, payload)&.body
155
+ ))
136
156
  end
137
157
  end
138
158
  end