tangled
alpha
login
or
join now
8bit.lol
/
pegasus
forked from
futur.blue/pegasus
0
fork
atom
objective categorical abstract machine language personal data server
0
fork
atom
overview
issues
pulls
pipelines
Preserve existing non-PDS rotation keys in migration
futur.blue
2 months ago
a871067c
5d2164aa
verified
This commit was signed with the committer's
known signature
.
futur.blue
SSH Key Fingerprint:
SHA256:QHGqHWNpqYyw9bt8KmPuJIyeZX9SZewBZ0PR1COtKQ0=
+128
-138
2 changed files
expand all
collapse all
unified
split
pegasus
lib
api
account_
migrate.ml
identity
getRecommendedDidCredentials.ml
+125
-136
pegasus/lib/api/account_/migrate.ml
···
1574
1574
~handle:state.handle ~old_pds:state.old_pds
1575
1575
"Please enter the PLC token from your email"
1576
1576
else
1577
1577
-
(* Get our recommended credentials *)
1577
1577
+
(* new rotation keys = current rotation keys - old PDS key(s) + new PDS key *)
1578
1578
+
let%lwt old_pds_keys =
1579
1579
+
match%lwt
1580
1580
+
get_remote_recommended_credentials
1581
1581
+
~pds_endpoint:state.old_pds ~access_jwt:state.access_jwt
1582
1582
+
with
1583
1583
+
| Ok creds ->
1584
1584
+
Lwt.return creds.rotation_keys
1585
1585
+
| Error e ->
1586
1586
+
Dream.warning (fun log ->
1587
1587
+
log
1588
1588
+
"migration %s: failed to get old PDS \
1589
1589
+
credentials: %s"
1590
1590
+
state.did e ) ;
1591
1591
+
Lwt.return []
1592
1592
+
in
1593
1593
+
let%lwt current_keys =
1594
1594
+
match%lwt get_plc_rotation_keys ~did:state.did with
1595
1595
+
| Ok keys ->
1596
1596
+
Lwt.return keys
1597
1597
+
| Error _ ->
1598
1598
+
Lwt.return []
1599
1599
+
in
1600
1600
+
(* remove old PDS key(s) from current keys *)
1601
1601
+
let keys_to_preserve =
1602
1602
+
List.filter
1603
1603
+
(fun k -> not (List.mem k old_pds_keys))
1604
1604
+
current_keys
1605
1605
+
in
1606
1606
+
(* construct recommended credentials *)
1578
1607
match%lwt
1579
1608
get_recommended_did_credentials state.did ctx.db
1609
1609
+
~extra_rotation_keys:keys_to_preserve
1580
1610
with
1581
1611
| Error e ->
1582
1612
render_error ~step:"enter_plc_token" ~did:state.did
1583
1613
~handle:state.handle ~old_pds:state.old_pds
1584
1614
("Failed to get credentials: " ^ e)
1585
1585
-
| Ok base_credentials -> (
1586
1586
-
(* new rotation keys = current rotation keys - old PDS key(s) + new PDS key *)
1587
1587
-
let%lwt merged_credentials =
1588
1588
-
let%lwt old_pds_keys =
1589
1589
-
match%lwt
1590
1590
-
get_remote_recommended_credentials
1591
1591
-
~pds_endpoint:state.old_pds
1592
1592
-
~access_jwt:state.access_jwt
1593
1593
-
with
1594
1594
-
| Ok creds ->
1595
1595
-
Lwt.return creds.rotation_keys
1596
1596
-
| Error e ->
1597
1597
-
Dream.warning (fun log ->
1598
1598
-
log
1599
1599
-
"migration %s: failed to get old PDS \
1600
1600
-
credentials: %s"
1601
1601
-
state.did e ) ;
1602
1602
-
Lwt.return []
1603
1603
-
in
1604
1604
-
let%lwt current_keys =
1605
1605
-
match%lwt get_plc_rotation_keys ~did:state.did with
1606
1606
-
| Ok keys ->
1607
1607
-
Lwt.return keys
1608
1608
-
| Error _ ->
1609
1609
-
Lwt.return []
1610
1610
-
in
1611
1611
-
(* remove old PDS key(s) from current keys *)
1612
1612
-
let preserved_keys =
1613
1613
-
List.filter
1614
1614
-
(fun k -> not (List.mem k old_pds_keys))
1615
1615
-
current_keys
1616
1616
-
in
1617
1617
-
(* then add in new key *)
1618
1618
-
let merged_keys =
1619
1619
-
preserved_keys @ base_credentials.rotation_keys
1620
1620
-
|> List.sort_uniq String.compare
1621
1621
-
in
1622
1622
-
Lwt.return
1623
1623
-
{base_credentials with rotation_keys= merged_keys}
1624
1624
-
in
1625
1625
-
(* get old pds to sign plc operation *)
1615
1615
+
| Ok credentials -> (
1616
1616
+
(* get old pds to sign plc operation *)
1617
1617
+
match%lwt
1618
1618
+
sign_plc_operation ~pds_endpoint:state.old_pds
1619
1619
+
~access_jwt:state.access_jwt ~token:plc_token
1620
1620
+
~credentials
1621
1621
+
with
1622
1622
+
| Error e ->
1623
1623
+
render_error ~step:"enter_plc_token" ~did:state.did
1624
1624
+
~handle:state.handle ~old_pds:state.old_pds
1625
1625
+
("Failed to sign PLC operation: " ^ e)
1626
1626
+
| Ok signed_operation -> (
1627
1627
+
(* submit plc operation *)
1626
1628
match%lwt
1627
1627
-
sign_plc_operation ~pds_endpoint:state.old_pds
1628
1628
-
~access_jwt:state.access_jwt ~token:plc_token
1629
1629
-
~credentials:merged_credentials
1629
1629
+
submit_plc_operation ~did:state.did ~handle:state.handle
1630
1630
+
~operation:signed_operation ctx.db
1630
1631
with
1631
1632
| Error e ->
1632
1633
render_error ~step:"enter_plc_token" ~did:state.did
1633
1634
~handle:state.handle ~old_pds:state.old_pds
1634
1634
-
("Failed to sign PLC operation: " ^ e)
1635
1635
-
| Ok signed_operation -> (
1636
1636
-
(* submit plc operation *)
1637
1637
-
match%lwt
1638
1638
-
submit_plc_operation ~did:state.did
1639
1639
-
~handle:state.handle ~operation:signed_operation
1640
1640
-
ctx.db
1641
1641
-
with
1642
1642
-
| Error e ->
1643
1643
-
render_error ~step:"enter_plc_token" ~did:state.did
1644
1644
-
~handle:state.handle ~old_pds:state.old_pds
1645
1645
-
("Failed to submit PLC operation: " ^ e)
1646
1646
-
| Ok () ->
1647
1647
-
(* log account status before activation *)
1648
1648
-
let%lwt () =
1635
1635
+
("Failed to submit PLC operation: " ^ e)
1636
1636
+
| Ok () ->
1637
1637
+
(* log account status before activation *)
1638
1638
+
let%lwt () =
1639
1639
+
match%lwt
1640
1640
+
check_local_account_status ~did:state.did
1641
1641
+
with
1642
1642
+
| Ok status ->
1643
1643
+
Dream.info (fun log ->
1644
1644
+
log
1645
1645
+
"migration %s: activating account, \
1646
1646
+
imported_blobs=%d/%d"
1647
1647
+
state.did status.imported_blobs
1648
1648
+
status.expected_blobs ) ;
1649
1649
+
Lwt.return_unit
1650
1650
+
| Error e ->
1651
1651
+
Dream.warning (fun log ->
1652
1652
+
log
1653
1653
+
"migration %s: failed to check status \
1654
1654
+
before activation: %s"
1655
1655
+
state.did e ) ;
1656
1656
+
Lwt.return_unit
1657
1657
+
in
1658
1658
+
(* activate the account *)
1659
1659
+
let%lwt () = activate_account state.did ctx.db in
1660
1660
+
let%lwt () = Session.log_in_did ctx.req state.did in
1661
1661
+
let%lwt () = clear_migration_state ctx.req in
1662
1662
+
(* try deactivating old account with current token, refresh if expired *)
1663
1663
+
let%lwt deactivation_result =
1664
1664
+
match%lwt
1665
1665
+
deactivate_old_account ~pds_endpoint:state.old_pds
1666
1666
+
~access_jwt:state.access_jwt
1667
1667
+
with
1668
1668
+
| Ok () ->
1669
1669
+
Lwt.return_ok ()
1670
1670
+
| Error e
1671
1671
+
when Util.str_contains ~affix:"401" e
1672
1672
+
|| Util.str_contains ~affix:"Unauthorized" e
1673
1673
+
-> (
1649
1674
match%lwt
1650
1650
-
check_local_account_status ~did:state.did
1675
1675
+
refresh_session ~pds_endpoint:state.old_pds
1676
1676
+
~refresh_jwt:state.refresh_jwt
1651
1677
with
1652
1652
-
| Ok status ->
1653
1653
-
Dream.info (fun log ->
1654
1654
-
log
1655
1655
-
"migration %s: activating account, \
1656
1656
-
imported_blobs=%d/%d"
1657
1657
-
state.did status.imported_blobs
1658
1658
-
status.expected_blobs ) ;
1659
1659
-
Lwt.return_unit
1660
1660
-
| Error e ->
1661
1661
-
Dream.warning (fun log ->
1662
1662
-
log
1663
1663
-
"migration %s: failed to check status \
1664
1664
-
before activation: %s"
1665
1665
-
state.did e ) ;
1666
1666
-
Lwt.return_unit
1667
1667
-
in
1668
1668
-
(* activate the account *)
1669
1669
-
let%lwt () = activate_account state.did ctx.db in
1670
1670
-
let%lwt () = Session.log_in_did ctx.req state.did in
1671
1671
-
let%lwt () = clear_migration_state ctx.req in
1672
1672
-
(* try deactivating old account with current token, refresh if expired *)
1673
1673
-
let%lwt deactivation_result =
1674
1674
-
match%lwt
1675
1675
-
deactivate_old_account
1676
1676
-
~pds_endpoint:state.old_pds
1677
1677
-
~access_jwt:state.access_jwt
1678
1678
-
with
1679
1679
-
| Ok () ->
1680
1680
-
Lwt.return_ok ()
1681
1681
-
| Error e
1682
1682
-
when Util.str_contains ~affix:"401" e
1683
1683
-
|| Util.str_contains ~affix:"Unauthorized"
1684
1684
-
e -> (
1685
1685
-
match%lwt
1686
1686
-
refresh_session ~pds_endpoint:state.old_pds
1687
1687
-
~refresh_jwt:state.refresh_jwt
1688
1688
-
with
1689
1689
-
| Ok tokens ->
1690
1690
-
deactivate_old_account
1691
1691
-
~pds_endpoint:state.old_pds
1692
1692
-
~access_jwt:tokens.access_jwt
1693
1693
-
| Error refresh_err ->
1694
1694
-
Lwt.return_error
1695
1695
-
(Printf.sprintf
1696
1696
-
"Token expired and refresh failed: %s"
1697
1697
-
refresh_err ) )
1698
1698
-
| Error e ->
1699
1699
-
Lwt.return_error e
1700
1700
-
in
1701
1701
-
let ( old_account_deactivated
1702
1702
-
, old_account_deactivation_error ) =
1703
1703
-
match deactivation_result with
1704
1704
-
| Ok () ->
1705
1705
-
(true, None)
1706
1706
-
| Error e ->
1707
1707
-
Dream.warning (fun log ->
1708
1708
-
log
1709
1709
-
"migration %s: failed to deactivate \
1710
1710
-
old account: %s"
1711
1711
-
state.did e ) ;
1712
1712
-
(false, Some e)
1713
1713
-
in
1714
1714
-
Util.render_html ~title:"Migrate Account"
1715
1715
-
(module Frontend.MigratePage)
1716
1716
-
~props:
1717
1717
-
(make_props ~step:"complete" ~did:state.did
1718
1718
-
~handle:state.handle
1719
1719
-
~blobs_imported:state.blobs_imported
1720
1720
-
~blobs_failed:state.blobs_failed
1721
1721
-
~old_account_deactivated
1722
1722
-
?old_account_deactivation_error
1723
1723
-
~message:
1724
1724
-
"Your account has been successfully \
1725
1725
-
migrated!"
1726
1726
-
() ) ) ) ) )
1678
1678
+
| Ok tokens ->
1679
1679
+
deactivate_old_account
1680
1680
+
~pds_endpoint:state.old_pds
1681
1681
+
~access_jwt:tokens.access_jwt
1682
1682
+
| Error refresh_err ->
1683
1683
+
Lwt.return_error
1684
1684
+
(Printf.sprintf
1685
1685
+
"Token expired and refresh failed: %s"
1686
1686
+
refresh_err ) )
1687
1687
+
| Error e ->
1688
1688
+
Lwt.return_error e
1689
1689
+
in
1690
1690
+
let ( old_account_deactivated
1691
1691
+
, old_account_deactivation_error ) =
1692
1692
+
match deactivation_result with
1693
1693
+
| Ok () ->
1694
1694
+
(true, None)
1695
1695
+
| Error e ->
1696
1696
+
Dream.warning (fun log ->
1697
1697
+
log
1698
1698
+
"migration %s: failed to deactivate old \
1699
1699
+
account: %s"
1700
1700
+
state.did e ) ;
1701
1701
+
(false, Some e)
1702
1702
+
in
1703
1703
+
Util.render_html ~title:"Migrate Account"
1704
1704
+
(module Frontend.MigratePage)
1705
1705
+
~props:
1706
1706
+
(make_props ~step:"complete" ~did:state.did
1707
1707
+
~handle:state.handle
1708
1708
+
~blobs_imported:state.blobs_imported
1709
1709
+
~blobs_failed:state.blobs_failed
1710
1710
+
~old_account_deactivated
1711
1711
+
?old_account_deactivation_error
1712
1712
+
~message:
1713
1713
+
"Your account has been successfully \
1714
1714
+
migrated!"
1715
1715
+
() ) ) ) ) )
1727
1716
| "resend_plc_token" -> (
1728
1717
match get_migration_state ctx.req with
1729
1718
| None ->
+3
-2
pegasus/lib/api/identity/getRecommendedDidCredentials.ml
···
1
1
type response = Plc.credentials [@@deriving yojson {strict= false}]
2
2
3
3
-
let get_credentials did db =
3
3
+
let get_credentials did ?(extra_rotation_keys = []) db =
4
4
match%lwt Data_store.get_actor_by_identifier did db with
5
5
| None ->
6
6
Lwt.return_error "actor not found"
···
8
8
actor.signing_key |> Kleidos.parse_multikey_str |> Kleidos.derive_pubkey
9
9
|> Kleidos.pubkey_to_did_key
10
10
|> (fun did_key ->
11
11
-
Plc.create_did_credentials Env.rotation_key did_key actor.handle )
11
11
+
Plc.create_did_credentials Env.rotation_key did_key actor.handle
12
12
+
~rotation_did_keys:extra_rotation_keys )
12
13
|> Lwt.return_ok
13
14
14
15
let handler =