cli: prevent missing delegate being added

It's necessary for a delegate's references to be present, e.g.
verification, calculating of canonical data, etc.

To ensure that a user does not get themselves into a state where they
have added a delegate without their references, prevent adding a
delegate to the identity document if their `rad/sigrefs` is not
present.

As well as this, it ensures that if there is a `rad/sigrefs` that it
has the default branch -- since it's possible for a peer to have created
`rad/sigrefs` through COBs without a default branch.

This change meant that the `rad-id` tests required the test scenarios
to be set up with all nodes having each other's references. A test
case to add a missing delegate was also added to `rad-id.md`.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
Fintan Halpenny 2023-11-24 15:42:51 +00:00 committed by cloudhead
parent bb5fb5e9d9
commit 0af233cceb
No known key found for this signature in database
4 changed files with 205 additions and 75 deletions

View File

@ -7,12 +7,12 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Bob" --des
$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji $ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi.. ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi..
✓ Fetched repository from 1 seed(s) ✓ Fetched repository from 1 seed(s)
$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --description "" --delegate did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn --no-confirm $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --description "" --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --no-confirm
✓ Identity revision 9e5aceb50f9307ddcb29923dbaeb5ccbfd07766c created ✓ Identity revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 created
╭────────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Eve │ │ Title Add Eve │
│ Revision 9e5aceb50f9307ddcb29923dbaeb5ccbfd07766c │ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3
│ Blob 4c7fd4c7b7d7fd5d7088a7c952556fab99a034e9 │ Blob 74581605d1f75396c331487a10ca61c4815ed685
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │ │ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
│ State active │ │ State active │
│ Quorum no │ │ Quorum no │
@ -34,7 +34,7 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --des
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
- "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk" - "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk", + "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk",
+ "did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn" + "did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z"
], ],
"threshold": 2 "threshold": 2
} }
@ -43,16 +43,17 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --des
``` ~alice ``` ~alice
$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji $ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkt67…v4N1tRk.. ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkt67…v4N1tRk..
✓ Fetched repository from 1 seed(s) ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkux1…nVhib7Z..
✓ Fetched repository from 2 seed(s)
$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates $ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates
did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice) did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob) did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
$ rad id accept 9e5aceb50f9307ddcb29923dbaeb5ccbfd07766c --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm $ rad id accept 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
✓ Revision 9e5aceb50f9307ddcb29923dbaeb5ccbfd07766c accepted ✓ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 accepted
╭────────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Eve │ │ Title Add Eve │
│ Revision 9e5aceb50f9307ddcb29923dbaeb5ccbfd07766c │ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3
│ Blob 4c7fd4c7b7d7fd5d7088a7c952556fab99a034e9 │ Blob 74581605d1f75396c331487a10ca61c4815ed685
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │ │ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
│ State accepted │ │ State accepted │
│ Quorum yes │ │ Quorum yes │
@ -63,12 +64,12 @@ $ rad id accept 9e5aceb50f9307ddcb29923dbaeb5ccbfd07766c --repo rad:z42hL2jL4XNk
$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates $ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates
did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice) did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob) did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z (eve)
``` ```
``` ~alice ``` ~alice
$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Make private" --description "" --visibility private --no-confirm -q $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Make private" --description "" --visibility private --no-confirm -q
efb8cdd368b9745396f832386f9c7d46988f6bd5 e6bf10593b78384eb2b281cbb18a605668a6d1f7
``` ```
We can list all revisions: We can list all revisions:
@ -78,8 +79,8 @@ $ rad id list
╭────────────────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Status Created │ │ ● ID Title Author Status Created │
├────────────────────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────────────────┤
│ ● efb8cdd Make private alice (you) active now │ │ ● e6bf105 Make private alice (you) active now │
│ ● 9e5aceb Add Eve bob z6Mkt67…v4N1tRk accepted now │ │ ● 3cd3c7f Add Eve bob z6Mkt67…v4N1tRk accepted now │
│ ● 069e7d5 Add Bob alice (you) accepted now │ │ ● 069e7d5 Add Bob alice (you) accepted now │
│ ● 0656c21 Initial revision alice (you) accepted now │ │ ● 0656c21 Initial revision alice (you) accepted now │
╰────────────────────────────────────────────────────────────────────────────────╯ ╰────────────────────────────────────────────────────────────────────────────────╯
@ -88,24 +89,24 @@ $ rad id list
Despite being a delegate, Bob can't edit or redact Alice's revision: Despite being a delegate, Bob can't edit or redact Alice's revision:
``` ~bob (fail) ``` ~bob (fail)
$ rad id redact efb8cdd368b9745396f832386f9c7d46988f6bd5 $ rad id redact e6bf10593b78384eb2b281cbb18a605668a6d1f7
[..] [..]
``` ```
``` ~bob (fail) ``` ~bob (fail)
$ rad id edit --title "Boo!" --description "Boo!" efb8cdd368b9745396f832386f9c7d46988f6bd5 $ rad id edit --title "Boo!" --description "Boo!" e6bf10593b78384eb2b281cbb18a605668a6d1f7
[..] [..]
``` ```
Alice can edit: Alice can edit:
``` ~alice ``` ~alice
$ rad id edit --title "Make private" --description "Privacy is cool." efb8cdd368b9745396f832386f9c7d46988f6bd5 $ rad id edit --title "Make private" --description "Privacy is cool." e6bf10593b78384eb2b281cbb18a605668a6d1f7
✓ Revision efb8cdd368b9745396f832386f9c7d46988f6bd5 edited ✓ Revision e6bf10593b78384eb2b281cbb18a605668a6d1f7 edited
$ rad id show efb8cdd368b9745396f832386f9c7d46988f6bd5 $ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
╭────────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────╮
│ Title Make private │ │ Title Make private │
│ Revision efb8cdd368b9745396f832386f9c7d46988f6bd5 │ Revision e6bf10593b78384eb2b281cbb18a605668a6d1f7
│ Blob 79bc5c39103e811a3c9f11744f9a4029f063a5de │ Blob c533865b2846ca6c5b4436ec6872257293380c3b
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │ │ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State active │ │ State active │
│ Quorum no │ │ Quorum no │
@ -114,7 +115,7 @@ $ rad id show efb8cdd368b9745396f832386f9c7d46988f6bd5
├────────────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────────┤
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │ │ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
│ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │ │ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │
│ ? did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn │ ? did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z eve
╰────────────────────────────────────────────────────────────────────────╯ ╰────────────────────────────────────────────────────────────────────────╯
@@ -1,15 +1,18 @@ @@ -1,15 +1,18 @@
@ -129,7 +130,7 @@ $ rad id show efb8cdd368b9745396f832386f9c7d46988f6bd5
"delegates": [ "delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk", "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk",
"did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn" "did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z"
], ],
- "threshold": 2 - "threshold": 2
+ "threshold": 2, + "threshold": 2,
@ -142,29 +143,29 @@ $ rad id show efb8cdd368b9745396f832386f9c7d46988f6bd5
And she can redact her revision: And she can redact her revision:
``` ~alice ``` ~alice
$ rad id redact efb8cdd368b9745396f832386f9c7d46988f6bd5 $ rad id redact e6bf10593b78384eb2b281cbb18a605668a6d1f7
✓ Revision efb8cdd368b9745396f832386f9c7d46988f6bd5 redacted ✓ Revision e6bf10593b78384eb2b281cbb18a605668a6d1f7 redacted
``` ```
``` ~alice (fail) ``` ~alice (fail)
$ rad id show efb8cdd368b9745396f832386f9c7d46988f6bd5 $ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
✗ Error: revision `efb8cdd368b9745396f832386f9c7d46988f6bd5` not found ✗ Error: revision `e6bf10593b78384eb2b281cbb18a605668a6d1f7` not found
``` ```
Finally, Alice can also propose to remove Bob: Finally, Alice can also propose to remove Bob:
``` ~alice ``` ~alice
$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Remove Bob" --description "" --rescind did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Remove Bob" --description "" --rescind did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm
✓ Identity revision faf5fb018803d2883e9906bb9c08b6ec83aa55dd created ✓ Identity revision 8ba242a80bc1181f41f9ea7a19286038c7948994 created
╭────────────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────╮
│ Title Remove Bob │ │ Title Remove Bob │
│ Revision faf5fb018803d2883e9906bb9c08b6ec83aa55dd │ Revision 8ba242a80bc1181f41f9ea7a19286038c7948994
│ Blob 7109c1c201c223dd4e9fdb10f7330dc6f0310258 │ Blob 254d62de237117e7d7b9ceff85c47f5e3b610c1e
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │ │ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State active │ │ State active │
│ Quorum no │ │ Quorum no │
├────────────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────────┤
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │ │ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
│ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │ │ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │
│ ? did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn │ ? did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z eve
╰────────────────────────────────────────────────────────────────────────╯ ╰────────────────────────────────────────────────────────────────────────╯
@@ -1,15 +1,14 @@ @@ -1,15 +1,14 @@
@ -179,7 +180,7 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Remove Bob" --
"delegates": [ "delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
- "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk", - "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk",
"did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn" "did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z"
], ],
"threshold": 2 "threshold": 2
} }

View File

@ -10,24 +10,24 @@ command. For now, since we are the only delegate, and `treshold` is `1`, we
can update the identity ourselves. can update the identity ourselves.
Let's add Bob as a delegate using their DID, Let's add Bob as a delegate using their DID,
`did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn`, and update the `did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk`, and update the
threshold to `2`. threshold to `2`.
``` ```
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn --threshold 2 $ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --threshold 2
✓ Identity revision 07829cdd1993295cd6be18de6219fead428b4a5e created ✓ Identity revision 0ca42d376bd566631083c8913cf86bec722da392 created
╭───────────────────────────────────────────────────────────────────╮ ╭────────────────────────────────────────────────────────────────────────
│ Title Add Bob │ │ Title Add Bob
│ Revision 07829cdd1993295cd6be18de6219fead428b4a5e │ Revision 0ca42d376bd566631083c8913cf86bec722da392
│ Blob 7109c1c201c223dd4e9fdb10f7330dc6f0310258 │ Blob 053541ba7b90534b35dd8718e0ceaa408979b02b
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │ │ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
│ State accepted │ │ State accepted
│ Quorum yes │ │ Quorum yes
│ │
│ Add Bob as a delegate │ │ Add Bob as a delegate
├───────────────────────────────────────────────────────────────────┤ ├────────────────────────────────────────────────────────────────────────
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) │ │ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰───────────────────────────────────────────────────────────────────╯ ╰────────────────────────────────────────────────────────────────────────
@@ -1,13 +1,14 @@ @@ -1,13 +1,14 @@
{ {
@ -41,7 +41,7 @@ $ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delega
"delegates": [ "delegates": [
- "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" - "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn" + "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
], ],
- "threshold": 1 - "threshold": 1
+ "threshold": 2 + "threshold": 2
@ -56,7 +56,7 @@ the delegates and threshold:
"delegates": [ "delegates": [
- "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" - "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", + "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn" + "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
], ],
... ...
- "threshold": 1 - "threshold": 1
@ -85,7 +85,7 @@ $ rad inspect --identity
}, },
"delegates": [ "delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi", "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn" "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
], ],
"threshold": 2 "threshold": 2
} }
@ -94,16 +94,16 @@ $ rad inspect --identity
We can also look at the document's COB directly: We can also look at the document's COB directly:
``` ```
$ rad cob show --object 0656c217f917c3e06234771e9ecae53aba5e173e --type xyz.radicle.id --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji $ rad cob show --object 0656c217f917c3e06234771e9ecae53aba5e173e --type xyz.radicle.id --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
commit 07829cdd1993295cd6be18de6219fead428b4a5e commit 0ca42d376bd566631083c8913cf86bec722da392
parent 0656c217f917c3e06234771e9ecae53aba5e173e parent 0656c217f917c3e06234771e9ecae53aba5e173e
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000 date Thu, 15 Dec 2022 17:28:04 +0000
{ {
"blob": "7109c1c201c223dd4e9fdb10f7330dc6f0310258", "blob": "053541ba7b90534b35dd8718e0ceaa408979b02b",
"description": "Add Bob as a delegate", "description": "Add Bob as a delegate",
"parent": "0656c217f917c3e06234771e9ecae53aba5e173e", "parent": "0656c217f917c3e06234771e9ecae53aba5e173e",
"signature": "z3sne3sdReZ4AtgxQmn7R1pQnz7E9ZEUoRfCJDJ8ytgnBMFW4DJqRHuBz2h1NK4QdGEy3QCpyVoJKfE95tNoivXwz", "signature": "z3AyzixN2eWLtRfQWowtBXwWyRH3iJ8oJ25W6KFYFw5ANLntbzfavge15muNU6AVAUkxSxQvgg9yh2gupbUecavQY",
"title": "Add Bob", "title": "Add Bob",
"type": "revision" "type": "revision"
} }
@ -126,14 +126,24 @@ Note that once a revision is accepted, it can't be edited, redacted or otherwise
acted upon: acted upon:
``` (fail) ``` (fail)
$ rad id redact 07829cdd1993295cd6be18de6219fead428b4a5e $ rad id redact 0ca42d376bd566631083c8913cf86bec722da392
✗ Error: [..] ✗ Error: [..]
``` ```
``` (fail) ``` (fail)
$ rad id reject 07829cdd1993295cd6be18de6219fead428b4a5e $ rad id reject 0ca42d376bd566631083c8913cf86bec722da392
✗ Error: [..] ✗ Error: [..]
``` ```
``` (fail) ``` (fail)
$ rad id accept 07829cdd1993295cd6be18de6219fead428b4a5e $ rad id accept 0ca42d376bd566631083c8913cf86bec722da392
✗ Error: [..] ✗ Error: [..]
``` ```
If we attempt to add a delegate that we do not have locally, then we
will be told that they are missing in our repository:
``` (fail)
$ rad id update --title "Add Eve" --description "Add Eve as a delegate" --delegate did:key:z6MkedTZGJGqgQ2py2b8kGecfxdt2yRdHWF6JpaZC47fovFn
✗ Error: failed to verify delegates for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
✗ Error: missing delegate z6MkedT…47fovFn in local storage
✗ Error: fatal: refusing to update identity document
```

View File

@ -6,7 +6,8 @@ use nonempty::NonEmpty;
use radicle::cob::identity::{self, IdentityMut, Revision, RevisionId}; use radicle::cob::identity::{self, IdentityMut, Revision, RevisionId};
use radicle::identity::{doc, Identity, Visibility}; use radicle::identity::{doc, Identity, Visibility};
use radicle::prelude::{Did, Doc, Id, Signer}; use radicle::prelude::{Did, Doc, Id, Signer};
use radicle::storage::{ReadStorage as _, WriteRepository}; use radicle::storage::refs;
use radicle::storage::{ReadRepository, ReadStorage as _, WriteRepository};
use radicle::{cob, Profile}; use radicle::{cob, Profile};
use radicle_crypto::Verified; use radicle_crypto::Verified;
use radicle_surf::diff::Diff; use radicle_surf::diff::Diff;
@ -356,6 +357,14 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
"at lease one delegate must be present for the identity to be valid" "at lease one delegate must be present for the identity to be valid"
))?; ))?;
if let Some(errs) = verify_delegates(&proposal.delegates, &repo)? {
term::error(format!("failed to verify delegates for {rid}"));
for e in errs {
e.print();
}
anyhow::bail!("fatal: refusing to update identity document");
}
for (id, key, val) in payload { for (id, key, val) in payload {
if let Some(ref mut payload) = proposal.payload.get_mut(&id) { if let Some(ref mut payload) = proposal.payload.get_mut(&id) {
if let Some(obj) = payload.as_object_mut() { if let Some(obj) = payload.as_object_mut() {
@ -643,3 +652,54 @@ fn print_diff(
} }
Ok(()) Ok(())
} }
enum VerificationError {
Missing(Did),
MissingDefaultBranch {
branch: radicle::git::RefString,
did: Did,
},
}
impl VerificationError {
fn print(&self) {
match self {
VerificationError::Missing(did) => term::error(format!(
"missing delegate {} in local storage",
term::format::did(did)
)),
VerificationError::MissingDefaultBranch { branch, did } => term::error(format!(
"missing {} for {} in local storage",
term::format::secondary(branch),
term::format::did(did)
)),
}
}
}
fn verify_delegates<S>(
dids: &NonEmpty<Did>,
repo: &S,
) -> anyhow::Result<Option<Vec<VerificationError>>>
where
S: ReadRepository,
{
let (canonical, _) = repo.canonical_head()?;
let mut errors = Vec::with_capacity(dids.len());
for did in dids {
match refs::SignedRefsAt::load((*did).into(), repo)? {
None => {
errors.push(VerificationError::Missing(*did));
}
Some(refs::SignedRefsAt { sigrefs, .. }) => {
if sigrefs.get(&canonical).is_none() {
errors.push(VerificationError::MissingDefaultBranch {
branch: canonical.to_ref_string(),
did: *did,
})
}
}
}
}
Ok((!errors.is_empty()).then_some(errors))
}

View File

@ -255,20 +255,6 @@ fn rad_checkout() {
#[test] #[test]
fn rad_id() { fn rad_id() {
let mut environment = Environment::new();
let profile = environment.profile("alice");
let working = tempfile::tempdir().unwrap();
let home = &profile.home;
// Setup a test repository.
fixtures::repository(working.path());
test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
test("examples/rad-id.md", working.path(), Some(home), []).unwrap();
}
#[test]
fn rad_id_multi_delegate() {
let mut environment = Environment::new(); let mut environment = Environment::new();
let alice = environment.node(Config::test(Alias::new("alice"))); let alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob"))); let bob = environment.node(Config::test(Alias::new("bob")));
@ -288,10 +274,11 @@ fn rad_id_multi_delegate() {
.unwrap(); .unwrap();
let mut alice = alice.spawn(); let mut alice = alice.spawn();
let mut bob = bob.spawn(); let bob = bob.spawn();
bob.handle.track_repo(acme, Scope::All).unwrap(); alice.handle.track_repo(acme, Scope::All).unwrap();
alice.connect(&bob).converge([&bob]); alice.connect(&bob).converge([&bob]);
let events = alice.handle.events();
test( test(
"examples/rad-clone.md", "examples/rad-clone.md",
@ -300,6 +287,74 @@ fn rad_id_multi_delegate() {
[], [],
) )
.unwrap(); .unwrap();
alice.has_inventory_of(&acme, &bob.id);
// Alice must have Bob to try add them as a delegate
events
.wait(
|e| matches!(e, Event::RefsFetched { .. }).then_some(()),
time::Duration::from_secs(6),
)
.unwrap();
test(
"examples/rad-id.md",
working.join("alice"),
Some(&alice.home),
[],
)
.unwrap();
}
#[test]
fn rad_id_multi_delegate() {
let mut environment = Environment::new();
let alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob")));
let eve = environment.node(Config::test(Alias::new("eve")));
let working = tempfile::tempdir().unwrap();
let working = working.path();
let acme = Id::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
// Setup a test repository.
fixtures::repository(working.join("alice"));
test(
"examples/rad-init.md",
working.join("alice"),
Some(&alice.home),
[],
)
.unwrap();
let mut alice = alice.spawn();
let mut bob = bob.spawn();
let mut eve = eve.spawn();
alice.handle.track_repo(acme, Scope::All).unwrap();
bob.handle.track_node(eve.id, None).unwrap();
alice.connect(&bob).converge([&bob]);
eve.connect(&alice).converge([&alice]);
test(
"examples/rad-clone.md",
working.join("bob"),
Some(&bob.home),
[],
)
.unwrap();
bob.has_inventory_of(&acme, &alice.id);
alice.has_inventory_of(&acme, &bob.id);
test(
"examples/rad-clone-all.md",
working.join("eve"),
Some(&eve.home),
[],
)
.unwrap();
eve.has_inventory_of(&acme, &bob.id);
alice.has_inventory_of(&acme, &eve.id);
// TODO: Have formula with two connected nodes and a tracked project. // TODO: Have formula with two connected nodes and a tracked project.
@ -340,9 +395,8 @@ fn rad_id_conflict() {
.unwrap(); .unwrap();
let mut alice = alice.spawn(); let mut alice = alice.spawn();
let mut bob = bob.spawn(); let bob = bob.spawn();
bob.handle.track_repo(acme, Scope::All).unwrap();
alice.connect(&bob).converge([&bob]); alice.connect(&bob).converge([&bob]);
test( test(
@ -352,6 +406,7 @@ fn rad_id_conflict() {
[], [],
) )
.unwrap(); .unwrap();
alice.has_inventory_of(&acme, &bob.id);
formula(&environment.tmp(), "examples/rad-id-conflict.md") formula(&environment.tmp(), "examples/rad-id-conflict.md")
.unwrap() .unwrap()
@ -1553,6 +1608,7 @@ fn git_push_diverge() {
let alice = environment.node(Config::test(Alias::new("alice"))); let alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob"))); let bob = environment.node(Config::test(Alias::new("bob")));
let working = environment.tmp().join("working"); let working = environment.tmp().join("working");
let acme = Id::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
fixtures::repository(working.join("alice")); fixtures::repository(working.join("alice"));
@ -1576,6 +1632,7 @@ fn git_push_diverge() {
[], [],
) )
.unwrap(); .unwrap();
alice.has_inventory_of(&acme, &bob.id);
formula(&environment.tmp(), "examples/git/git-push-diverge.md") formula(&environment.tmp(), "examples/git/git-push-diverge.md")
.unwrap() .unwrap()
@ -1599,6 +1656,7 @@ fn rad_push_and_pull_patches() {
let alice = environment.node(Config::test(Alias::new("alice"))); let alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob"))); let bob = environment.node(Config::test(Alias::new("bob")));
let working = environment.tmp().join("working"); let working = environment.tmp().join("working");
let acme = Id::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
fixtures::repository(working.join("alice")); fixtures::repository(working.join("alice"));
@ -1624,6 +1682,7 @@ fn rad_push_and_pull_patches() {
[], [],
) )
.unwrap(); .unwrap();
alice.has_inventory_of(&acme, &bob.id);
formula(&environment.tmp(), "examples/rad-push-and-pull-patches.md") formula(&environment.tmp(), "examples/rad-push-and-pull-patches.md")
.unwrap() .unwrap()