atlas_rb 1.6.1 → 1.6.3
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/.version +1 -1
- data/Gemfile.lock +1 -1
- data/lib/atlas_rb/person.rb +111 -0
- data/lib/atlas_rb/system.rb +58 -0
- data/lib/atlas_rb.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 63326317e9bb9abcd730807bdfe9870d24685da7fec108474f676198ed1de200
|
|
4
|
+
data.tar.gz: 16a31a4c9708699c92f4651714594a3ead821a882cc4e958b0ae81a86b0c5146
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6236b86dd4a2b0c2c8740fb9479a9584a59fe1303464b7731ae955e0ceb5489e920d7a119d1bac6afb1535933310b7ccecee74d3da6a865a6bdb755a38a9c095
|
|
7
|
+
data.tar.gz: 0c80e8c9f82b3a05ba5560e703db3da1c1c10ceae61dd95a06c3e8368fa07a503e8a12bcb66d2ae5d0ed398af7386d54943cad754f319ef31dd9669149e8c490
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.6.
|
|
1
|
+
1.6.3
|
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AtlasRb
|
|
4
|
+
# A neutral curatorial identity in Atlas, distinct from the auth-side users
|
|
5
|
+
# directory. A Person correlates the several `users` rows that share a NUID
|
|
6
|
+
# and carries the authoritative, librarian-editable `display_name` (the SSO
|
|
7
|
+
# `users.name` is frequently wrong and is clobbered on every login), plus
|
|
8
|
+
# community affiliations.
|
|
9
|
+
#
|
|
10
|
+
# Addressed by NUID, not NOID — the NUID is the correlation key consumers
|
|
11
|
+
# hold. So the positional `id` argument below is the person's **NUID**, and
|
|
12
|
+
# the `nuid:` / `on_behalf_of:` keywords keep their usual gem meaning (the
|
|
13
|
+
# acting principal). The one exception is {.create}, whose `nuid:` keyword is
|
|
14
|
+
# the *new person's* NUID (matching the gap's signature); the acting principal
|
|
15
|
+
# there comes from the ambient `AtlasRb.config.default_nuid`.
|
|
16
|
+
#
|
|
17
|
+
# Create / update / affiliation writes are :system + admin on the server; a
|
|
18
|
+
# non-privileged caller gets a 403.
|
|
19
|
+
class Person < Resource
|
|
20
|
+
ROUTE = "/people/"
|
|
21
|
+
|
|
22
|
+
# Fetch a Person by NUID.
|
|
23
|
+
#
|
|
24
|
+
# @param id [String] the person's NUID.
|
|
25
|
+
# @param nuid [String, nil] acting principal (signed into the assertion sub).
|
|
26
|
+
# @param on_behalf_of [String, nil] acting-as target.
|
|
27
|
+
# @return [AtlasRb::Mash] the unwrapped `"person"` object.
|
|
28
|
+
def self.find(id, nuid: nil, on_behalf_of: nil)
|
|
29
|
+
AtlasRb::Mash.new(JSON.parse(
|
|
30
|
+
connection({}, nuid, on_behalf_of: on_behalf_of).get(ROUTE + id)&.body
|
|
31
|
+
))["person"]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Batch-resolve people to their authoritative display_name in one call
|
|
35
|
+
# (supersedes the SSO users directory's resolve). Unresolved NUIDs drop.
|
|
36
|
+
#
|
|
37
|
+
# @param nuids [Array<String>] the NUIDs to resolve.
|
|
38
|
+
# @param nuid [String, nil] acting principal.
|
|
39
|
+
# @param on_behalf_of [String, nil] acting-as target.
|
|
40
|
+
# @return [Array<AtlasRb::Mash>] one unwrapped `"person"` per resolved NUID.
|
|
41
|
+
def self.resolve(nuids, nuid: nil, on_behalf_of: nil)
|
|
42
|
+
JSON.parse(
|
|
43
|
+
connection({ nuids: Array(nuids).join(",") }, nuid, on_behalf_of: on_behalf_of).get(ROUTE)&.body
|
|
44
|
+
)["people"].map { |entry| AtlasRb::Mash.new(entry["person"]) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Create a Person. One Person per NUID — a duplicate NUID is a 409.
|
|
48
|
+
#
|
|
49
|
+
# @param nuid [String] the **new person's** NUID (the subject, not the actor).
|
|
50
|
+
# @param display_name [String] authoritative display name.
|
|
51
|
+
# @param bio [String, nil]
|
|
52
|
+
# @param orcid [String, nil]
|
|
53
|
+
# @param title [String, nil]
|
|
54
|
+
# @param on_behalf_of [String, nil] acting-as target (the acting principal
|
|
55
|
+
# itself comes from the ambient AtlasRb.config.default_nuid).
|
|
56
|
+
# @return [AtlasRb::Mash] the unwrapped `"person"` object.
|
|
57
|
+
def self.create(nuid:, display_name:, bio: nil, orcid: nil, title: nil, on_behalf_of: nil)
|
|
58
|
+
body = { nuid: nuid, display_name: display_name, bio: bio, orcid: orcid, title: title }.compact
|
|
59
|
+
AtlasRb::Mash.new(JSON.parse(
|
|
60
|
+
connection({}, nil, on_behalf_of: on_behalf_of).post(ROUTE, JSON.dump(body))&.body
|
|
61
|
+
))["person"]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Edit a Person's authority fields. NUID is immutable and not patchable.
|
|
65
|
+
# Only supplied fields are changed.
|
|
66
|
+
#
|
|
67
|
+
# @param id [String] the person's NUID.
|
|
68
|
+
# @param display_name [String, nil]
|
|
69
|
+
# @param bio [String, nil]
|
|
70
|
+
# @param orcid [String, nil]
|
|
71
|
+
# @param title [String, nil]
|
|
72
|
+
# @param nuid [String, nil] acting principal.
|
|
73
|
+
# @param on_behalf_of [String, nil] acting-as target.
|
|
74
|
+
# @return [AtlasRb::Mash] the unwrapped, updated `"person"` object.
|
|
75
|
+
def self.update(id, display_name: nil, bio: nil, orcid: nil, title: nil, nuid: nil, on_behalf_of: nil)
|
|
76
|
+
body = { display_name: display_name, bio: bio, orcid: orcid, title: title }.compact
|
|
77
|
+
AtlasRb::Mash.new(JSON.parse(
|
|
78
|
+
connection({}, nuid, on_behalf_of: on_behalf_of).patch(ROUTE + id, JSON.dump(body))&.body
|
|
79
|
+
))["person"]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Add a community affiliation (idempotent; audited server-side).
|
|
83
|
+
#
|
|
84
|
+
# @param id [String] the person's NUID.
|
|
85
|
+
# @param community_id [String] the community's NOID.
|
|
86
|
+
# @param nuid [String, nil] acting principal.
|
|
87
|
+
# @param on_behalf_of [String, nil] acting-as target.
|
|
88
|
+
# @return [AtlasRb::Mash] the unwrapped `"person"` object, with the updated
|
|
89
|
+
# `affiliated_community_ids`.
|
|
90
|
+
def self.add_affiliation(id, community_id, nuid: nil, on_behalf_of: nil)
|
|
91
|
+
AtlasRb::Mash.new(JSON.parse(
|
|
92
|
+
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
93
|
+
.post(ROUTE + id + "/affiliations", JSON.dump(community_id: community_id))&.body
|
|
94
|
+
))["person"]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Remove a community affiliation (tolerant; audited server-side).
|
|
98
|
+
#
|
|
99
|
+
# @param id [String] the person's NUID.
|
|
100
|
+
# @param community_id [String] the community's NOID.
|
|
101
|
+
# @param nuid [String, nil] acting principal.
|
|
102
|
+
# @param on_behalf_of [String, nil] acting-as target.
|
|
103
|
+
# @return [AtlasRb::Mash] the unwrapped `"person"` object.
|
|
104
|
+
def self.remove_affiliation(id, community_id, nuid: nil, on_behalf_of: nil)
|
|
105
|
+
AtlasRb::Mash.new(JSON.parse(
|
|
106
|
+
connection({}, nuid, on_behalf_of: on_behalf_of)
|
|
107
|
+
.delete(ROUTE + id + "/affiliations/" + community_id)&.body
|
|
108
|
+
))["person"]
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AtlasRb
|
|
4
|
+
# System-context callers — see {AtlasRb::System::User} for the namespace
|
|
5
|
+
# rationale (separate bearer token, hard-pinned `User:` header, the class
|
|
6
|
+
# itself as the carve-out marker).
|
|
7
|
+
#
|
|
8
|
+
# Beyond user provisioning, the namespace exposes Atlas's operational,
|
|
9
|
+
# `:system`-gated maintenance actions. These are not user operations — they
|
|
10
|
+
# never appear on the human CRUD surface — so they ride the system path.
|
|
11
|
+
module System
|
|
12
|
+
extend AtlasRb::FaradayHelper
|
|
13
|
+
|
|
14
|
+
# Re-project a single resource's Solr doc from Atlas's current
|
|
15
|
+
# Postgres/OCFL state. Solr-only on the server — no lifecycle transition,
|
|
16
|
+
# no audit event, no optimistic-lock bump. The purpose-built lever for
|
|
17
|
+
# refreshing a stale projection after an indexer ships or changes (e.g.
|
|
18
|
+
# the catalog's `classification_ssim` "Content" facet), without abusing
|
|
19
|
+
# `AtlasRb::Work.complete` to nudge Solr as a finalize side effect.
|
|
20
|
+
#
|
|
21
|
+
# Idempotent. Authenticates as the Atlas `:system` fixture via
|
|
22
|
+
# {FaradayHelper#system_connection}, so there is no way to issue it as a
|
|
23
|
+
# regular user.
|
|
24
|
+
#
|
|
25
|
+
# @param id [String] the NOID of any resource (Work, Collection,
|
|
26
|
+
# Community, FileSet, ...).
|
|
27
|
+
# @return [Faraday::Response] the raw response. Status `204` on success;
|
|
28
|
+
# `404` if the id does not resolve.
|
|
29
|
+
#
|
|
30
|
+
# @example Refresh one drifted Work after a new indexer shipped
|
|
31
|
+
# AtlasRb::System.reindex("neu:abc123")
|
|
32
|
+
def self.reindex(id)
|
|
33
|
+
system_connection.post("/resources/#{id}/reindex")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Re-project a resource AND its full descendant subtree — descendant
|
|
37
|
+
# containers (Collection/Community) plus the Works beneath them, a superset
|
|
38
|
+
# of Atlas's re-parent cascade so Work-level projections refresh too. Same
|
|
39
|
+
# Solr-only, side-effect-free semantics as {.reindex}.
|
|
40
|
+
#
|
|
41
|
+
# Synchronous on the server: rooted at a Collection it refreshes that
|
|
42
|
+
# Collection's contents; rooted at the top Community it backfills the whole
|
|
43
|
+
# repository. For a pathologically large subtree, root lower or drive the
|
|
44
|
+
# cascade in chunks (repeated calls) rather than relying on Atlas to grow a
|
|
45
|
+
# job runner — bulk orchestration lives in the consumer.
|
|
46
|
+
#
|
|
47
|
+
# @param id [String] the NOID of the subtree root.
|
|
48
|
+
# @return [Integer] the number of resources re-projected (the server's
|
|
49
|
+
# `reindexed` count).
|
|
50
|
+
#
|
|
51
|
+
# @example Backfill a Collection's contents after an indexer change
|
|
52
|
+
# AtlasRb::System.reindex_subtree("neu:collection1") # => 42
|
|
53
|
+
def self.reindex_subtree(id)
|
|
54
|
+
response = system_connection.post("/resources/#{id}/reindex_subtree")
|
|
55
|
+
JSON.parse(response.body)["reindexed"]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/atlas_rb.rb
CHANGED
|
@@ -22,11 +22,13 @@ require_relative "atlas_rb/file_set"
|
|
|
22
22
|
require_relative "atlas_rb/blob"
|
|
23
23
|
require_relative "atlas_rb/delegate"
|
|
24
24
|
require_relative "atlas_rb/compilation"
|
|
25
|
+
require_relative "atlas_rb/person"
|
|
25
26
|
require_relative "atlas_rb/user"
|
|
26
27
|
require_relative "atlas_rb/admin"
|
|
27
28
|
require_relative "atlas_rb/admin/work"
|
|
28
29
|
require_relative "atlas_rb/admin/collection"
|
|
29
30
|
require_relative "atlas_rb/admin/community"
|
|
31
|
+
require_relative "atlas_rb/system"
|
|
30
32
|
require_relative "atlas_rb/system/user"
|
|
31
33
|
require_relative "atlas_rb/audit_event"
|
|
32
34
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: atlas_rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.6.
|
|
4
|
+
version: 1.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cliff
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -147,7 +147,9 @@ files:
|
|
|
147
147
|
- lib/atlas_rb/mash.rb
|
|
148
148
|
- lib/atlas_rb/middleware/raise_on_resource_error.rb
|
|
149
149
|
- lib/atlas_rb/middleware/raise_on_stale_resource.rb
|
|
150
|
+
- lib/atlas_rb/person.rb
|
|
150
151
|
- lib/atlas_rb/resource.rb
|
|
152
|
+
- lib/atlas_rb/system.rb
|
|
151
153
|
- lib/atlas_rb/system/user.rb
|
|
152
154
|
- lib/atlas_rb/user.rb
|
|
153
155
|
- lib/atlas_rb/version.rb
|