Skip to content

Commit a871067

Browse files
committed
Preserve existing non-PDS rotation keys in migration
1 parent 5d2164a commit a871067

File tree

2 files changed

+128
-138
lines changed

2 files changed

+128
-138
lines changed

pegasus/lib/api/account_/migrate.ml

Lines changed: 125 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,156 +1574,145 @@ let post_handler =
15741574
~handle:state.handle ~old_pds:state.old_pds
15751575
"Please enter the PLC token from your email"
15761576
else
1577-
(* Get our recommended credentials *)
1577+
(* new rotation keys = current rotation keys - old PDS key(s) + new PDS key *)
1578+
let%lwt old_pds_keys =
1579+
match%lwt
1580+
get_remote_recommended_credentials
1581+
~pds_endpoint:state.old_pds ~access_jwt:state.access_jwt
1582+
with
1583+
| Ok creds ->
1584+
Lwt.return creds.rotation_keys
1585+
| Error e ->
1586+
Dream.warning (fun log ->
1587+
log
1588+
"migration %s: failed to get old PDS \
1589+
credentials: %s"
1590+
state.did e ) ;
1591+
Lwt.return []
1592+
in
1593+
let%lwt current_keys =
1594+
match%lwt get_plc_rotation_keys ~did:state.did with
1595+
| Ok keys ->
1596+
Lwt.return keys
1597+
| Error _ ->
1598+
Lwt.return []
1599+
in
1600+
(* remove old PDS key(s) from current keys *)
1601+
let keys_to_preserve =
1602+
List.filter
1603+
(fun k -> not (List.mem k old_pds_keys))
1604+
current_keys
1605+
in
1606+
(* construct recommended credentials *)
15781607
match%lwt
15791608
get_recommended_did_credentials state.did ctx.db
1609+
~extra_rotation_keys:keys_to_preserve
15801610
with
15811611
| Error e ->
15821612
render_error ~step:"enter_plc_token" ~did:state.did
15831613
~handle:state.handle ~old_pds:state.old_pds
15841614
("Failed to get credentials: " ^ e)
1585-
| Ok base_credentials -> (
1586-
(* new rotation keys = current rotation keys - old PDS key(s) + new PDS key *)
1587-
let%lwt merged_credentials =
1588-
let%lwt old_pds_keys =
1589-
match%lwt
1590-
get_remote_recommended_credentials
1591-
~pds_endpoint:state.old_pds
1592-
~access_jwt:state.access_jwt
1593-
with
1594-
| Ok creds ->
1595-
Lwt.return creds.rotation_keys
1596-
| Error e ->
1597-
Dream.warning (fun log ->
1598-
log
1599-
"migration %s: failed to get old PDS \
1600-
credentials: %s"
1601-
state.did e ) ;
1602-
Lwt.return []
1603-
in
1604-
let%lwt current_keys =
1605-
match%lwt get_plc_rotation_keys ~did:state.did with
1606-
| Ok keys ->
1607-
Lwt.return keys
1608-
| Error _ ->
1609-
Lwt.return []
1610-
in
1611-
(* remove old PDS key(s) from current keys *)
1612-
let preserved_keys =
1613-
List.filter
1614-
(fun k -> not (List.mem k old_pds_keys))
1615-
current_keys
1616-
in
1617-
(* then add in new key *)
1618-
let merged_keys =
1619-
preserved_keys @ base_credentials.rotation_keys
1620-
|> List.sort_uniq String.compare
1621-
in
1622-
Lwt.return
1623-
{base_credentials with rotation_keys= merged_keys}
1624-
in
1625-
(* get old pds to sign plc operation *)
1615+
| Ok credentials -> (
1616+
(* get old pds to sign plc operation *)
1617+
match%lwt
1618+
sign_plc_operation ~pds_endpoint:state.old_pds
1619+
~access_jwt:state.access_jwt ~token:plc_token
1620+
~credentials
1621+
with
1622+
| Error e ->
1623+
render_error ~step:"enter_plc_token" ~did:state.did
1624+
~handle:state.handle ~old_pds:state.old_pds
1625+
("Failed to sign PLC operation: " ^ e)
1626+
| Ok signed_operation -> (
1627+
(* submit plc operation *)
16261628
match%lwt
1627-
sign_plc_operation ~pds_endpoint:state.old_pds
1628-
~access_jwt:state.access_jwt ~token:plc_token
1629-
~credentials:merged_credentials
1629+
submit_plc_operation ~did:state.did ~handle:state.handle
1630+
~operation:signed_operation ctx.db
16301631
with
16311632
| Error e ->
16321633
render_error ~step:"enter_plc_token" ~did:state.did
16331634
~handle:state.handle ~old_pds:state.old_pds
1634-
("Failed to sign PLC operation: " ^ e)
1635-
| Ok signed_operation -> (
1636-
(* submit plc operation *)
1637-
match%lwt
1638-
submit_plc_operation ~did:state.did
1639-
~handle:state.handle ~operation:signed_operation
1640-
ctx.db
1641-
with
1642-
| Error e ->
1643-
render_error ~step:"enter_plc_token" ~did:state.did
1644-
~handle:state.handle ~old_pds:state.old_pds
1645-
("Failed to submit PLC operation: " ^ e)
1646-
| Ok () ->
1647-
(* log account status before activation *)
1648-
let%lwt () =
1649-
match%lwt
1650-
check_local_account_status ~did:state.did
1651-
with
1652-
| Ok status ->
1653-
Dream.info (fun log ->
1654-
log
1655-
"migration %s: activating account, \
1656-
imported_blobs=%d/%d"
1657-
state.did status.imported_blobs
1658-
status.expected_blobs ) ;
1659-
Lwt.return_unit
1660-
| Error e ->
1661-
Dream.warning (fun log ->
1662-
log
1663-
"migration %s: failed to check status \
1664-
before activation: %s"
1665-
state.did e ) ;
1666-
Lwt.return_unit
1667-
in
1668-
(* activate the account *)
1669-
let%lwt () = activate_account state.did ctx.db in
1670-
let%lwt () = Session.log_in_did ctx.req state.did in
1671-
let%lwt () = clear_migration_state ctx.req in
1672-
(* try deactivating old account with current token, refresh if expired *)
1673-
let%lwt deactivation_result =
1635+
("Failed to submit PLC operation: " ^ e)
1636+
| Ok () ->
1637+
(* log account status before activation *)
1638+
let%lwt () =
1639+
match%lwt
1640+
check_local_account_status ~did:state.did
1641+
with
1642+
| Ok status ->
1643+
Dream.info (fun log ->
1644+
log
1645+
"migration %s: activating account, \
1646+
imported_blobs=%d/%d"
1647+
state.did status.imported_blobs
1648+
status.expected_blobs ) ;
1649+
Lwt.return_unit
1650+
| Error e ->
1651+
Dream.warning (fun log ->
1652+
log
1653+
"migration %s: failed to check status \
1654+
before activation: %s"
1655+
state.did e ) ;
1656+
Lwt.return_unit
1657+
in
1658+
(* activate the account *)
1659+
let%lwt () = activate_account state.did ctx.db in
1660+
let%lwt () = Session.log_in_did ctx.req state.did in
1661+
let%lwt () = clear_migration_state ctx.req in
1662+
(* try deactivating old account with current token, refresh if expired *)
1663+
let%lwt deactivation_result =
1664+
match%lwt
1665+
deactivate_old_account ~pds_endpoint:state.old_pds
1666+
~access_jwt:state.access_jwt
1667+
with
1668+
| Ok () ->
1669+
Lwt.return_ok ()
1670+
| Error e
1671+
when Util.str_contains ~affix:"401" e
1672+
|| Util.str_contains ~affix:"Unauthorized" e
1673+
-> (
16741674
match%lwt
1675-
deactivate_old_account
1676-
~pds_endpoint:state.old_pds
1677-
~access_jwt:state.access_jwt
1675+
refresh_session ~pds_endpoint:state.old_pds
1676+
~refresh_jwt:state.refresh_jwt
16781677
with
1679-
| Ok () ->
1680-
Lwt.return_ok ()
1681-
| Error e
1682-
when Util.str_contains ~affix:"401" e
1683-
|| Util.str_contains ~affix:"Unauthorized"
1684-
e -> (
1685-
match%lwt
1686-
refresh_session ~pds_endpoint:state.old_pds
1687-
~refresh_jwt:state.refresh_jwt
1688-
with
1689-
| Ok tokens ->
1690-
deactivate_old_account
1691-
~pds_endpoint:state.old_pds
1692-
~access_jwt:tokens.access_jwt
1693-
| Error refresh_err ->
1694-
Lwt.return_error
1695-
(Printf.sprintf
1696-
"Token expired and refresh failed: %s"
1697-
refresh_err ) )
1698-
| Error e ->
1699-
Lwt.return_error e
1700-
in
1701-
let ( old_account_deactivated
1702-
, old_account_deactivation_error ) =
1703-
match deactivation_result with
1704-
| Ok () ->
1705-
(true, None)
1706-
| Error e ->
1707-
Dream.warning (fun log ->
1708-
log
1709-
"migration %s: failed to deactivate \
1710-
old account: %s"
1711-
state.did e ) ;
1712-
(false, Some e)
1713-
in
1714-
Util.render_html ~title:"Migrate Account"
1715-
(module Frontend.MigratePage)
1716-
~props:
1717-
(make_props ~step:"complete" ~did:state.did
1718-
~handle:state.handle
1719-
~blobs_imported:state.blobs_imported
1720-
~blobs_failed:state.blobs_failed
1721-
~old_account_deactivated
1722-
?old_account_deactivation_error
1723-
~message:
1724-
"Your account has been successfully \
1725-
migrated!"
1726-
() ) ) ) ) )
1678+
| Ok tokens ->
1679+
deactivate_old_account
1680+
~pds_endpoint:state.old_pds
1681+
~access_jwt:tokens.access_jwt
1682+
| Error refresh_err ->
1683+
Lwt.return_error
1684+
(Printf.sprintf
1685+
"Token expired and refresh failed: %s"
1686+
refresh_err ) )
1687+
| Error e ->
1688+
Lwt.return_error e
1689+
in
1690+
let ( old_account_deactivated
1691+
, old_account_deactivation_error ) =
1692+
match deactivation_result with
1693+
| Ok () ->
1694+
(true, None)
1695+
| Error e ->
1696+
Dream.warning (fun log ->
1697+
log
1698+
"migration %s: failed to deactivate old \
1699+
account: %s"
1700+
state.did e ) ;
1701+
(false, Some e)
1702+
in
1703+
Util.render_html ~title:"Migrate Account"
1704+
(module Frontend.MigratePage)
1705+
~props:
1706+
(make_props ~step:"complete" ~did:state.did
1707+
~handle:state.handle
1708+
~blobs_imported:state.blobs_imported
1709+
~blobs_failed:state.blobs_failed
1710+
~old_account_deactivated
1711+
?old_account_deactivation_error
1712+
~message:
1713+
"Your account has been successfully \
1714+
migrated!"
1715+
() ) ) ) ) )
17271716
| "resend_plc_token" -> (
17281717
match get_migration_state ctx.req with
17291718
| None ->

pegasus/lib/api/identity/getRecommendedDidCredentials.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
type response = Plc.credentials [@@deriving yojson {strict= false}]
22

3-
let get_credentials did db =
3+
let get_credentials did ?(extra_rotation_keys = []) db =
44
match%lwt Data_store.get_actor_by_identifier did db with
55
| None ->
66
Lwt.return_error "actor not found"
77
| Some actor ->
88
actor.signing_key |> Kleidos.parse_multikey_str |> Kleidos.derive_pubkey
99
|> Kleidos.pubkey_to_did_key
1010
|> (fun did_key ->
11-
Plc.create_did_credentials Env.rotation_key did_key actor.handle )
11+
Plc.create_did_credentials Env.rotation_key did_key actor.handle
12+
~rotation_did_keys:extra_rotation_keys )
1213
|> Lwt.return_ok
1314

1415
let handler =

0 commit comments

Comments
 (0)