Skip to content

Commit 156b017

Browse files
committed
Merge remote-tracking branch 'origin/main' into submit_plc_operation
# Conflicts: # rsky-lexicon/src/com/atproto/identity.rs
2 parents 90b33dd + 84a39c6 commit 156b017

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

rsky-lexicon/src/com/atproto/identity.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ pub struct SignPlcOperationRequest {
2525
pub services: Option<JsonValue>,
2626
}
2727

28+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
29+
#[serde(rename_all = "camelCase")]
30+
pub struct GetRecommendedDidCredentialsResponse {
31+
pub also_known_as: Vec<String>,
32+
pub verification_methods: JsonValue,
33+
pub rotation_keys: Vec<String>,
34+
pub services: JsonValue,
35+
}
36+
2837
#[derive(Clone, Debug, Serialize, Deserialize)]
2938
#[serde(rename_all = "camelCase")]
3039
pub struct SubmitPlcOperationRequest {
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use crate::account_manager::helpers::account::AvailabilityFlags;
2+
use crate::account_manager::AccountManager;
3+
use crate::apis::ApiError;
4+
use crate::auth_verifier::AccessStandard;
5+
use crate::config::ServerConfig;
6+
use rocket::serde::json::Json;
7+
use rocket::State;
8+
use rsky_crypto::utils::encode_did_key;
9+
use rsky_lexicon::com::atproto::identity::GetRecommendedDidCredentialsResponse;
10+
use secp256k1::{Keypair, Secp256k1, SecretKey};
11+
use serde_json::json;
12+
use std::env;
13+
14+
#[tracing::instrument(skip_all)]
15+
#[rocket::get("/xrpc/com.atproto.identity.getRecommendedDidCredentials")]
16+
pub async fn get_recommended_did_credentials(
17+
auth: AccessStandard,
18+
cfg: &State<ServerConfig>,
19+
) -> Result<Json<GetRecommendedDidCredentialsResponse>, ApiError> {
20+
let requester = auth.access.credentials.unwrap().did.unwrap();
21+
let availability_flags = AvailabilityFlags {
22+
include_taken_down: Some(true),
23+
include_deactivated: Some(true),
24+
};
25+
let account = AccountManager::get_account(&requester, Some(availability_flags))
26+
.await?
27+
.expect("Account not found despite valid access");
28+
29+
let mut also_known_as = Vec::new();
30+
match account.handle {
31+
None => {}
32+
Some(res) => {
33+
also_known_as.push("at://".to_string() + res.as_str());
34+
}
35+
}
36+
37+
let signing_key = get_public_signing_key()?;
38+
let verification_methods = json!({
39+
"atproto": signing_key
40+
});
41+
42+
let rotation_key = get_public_rotation_key()?;
43+
let rotation_keys = vec![rotation_key];
44+
45+
let services = json!({
46+
"atproto_pds": {
47+
"type": "AtprotoPersonalDataServer",
48+
"endpoint": cfg.service.public_url
49+
}
50+
});
51+
let response = GetRecommendedDidCredentialsResponse {
52+
also_known_as,
53+
verification_methods,
54+
rotation_keys,
55+
services,
56+
};
57+
Ok(Json(response))
58+
}
59+
60+
fn get_public_rotation_key() -> Result<String, ApiError> {
61+
let secp = Secp256k1::new();
62+
let private_rotation_key = match env::var("PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX") {
63+
Ok(res) => res,
64+
Err(error) => {
65+
tracing::error!("Error geting rotation private key\n{error}");
66+
return Err(ApiError::RuntimeError);
67+
}
68+
};
69+
match hex::decode(private_rotation_key.as_bytes()) {
70+
Ok(bytes) => match SecretKey::from_slice(&bytes) {
71+
Ok(secret_key) => {
72+
let rotation_keypair = Keypair::from_secret_key(&secp, &secret_key);
73+
Ok(encode_did_key(&rotation_keypair.public_key()))
74+
}
75+
Err(error) => {
76+
tracing::error!("Error geting rotation secret key from bytes\n{error}");
77+
Err(ApiError::RuntimeError)
78+
}
79+
},
80+
Err(error) => {
81+
tracing::error!("Unable to hex decode rotation key\n{error}");
82+
Err(ApiError::RuntimeError)
83+
}
84+
}
85+
}
86+
87+
fn get_public_signing_key() -> Result<String, ApiError> {
88+
let secp = Secp256k1::new();
89+
let private_signing_key = match env::var("PDS_REPO_SIGNING_KEY_K256_PRIVATE_KEY_HEX") {
90+
Ok(res) => res,
91+
Err(error) => {
92+
tracing::error!("Error geting signing private key\n{error}");
93+
return Err(ApiError::RuntimeError);
94+
}
95+
};
96+
match hex::decode(private_signing_key.as_bytes()) {
97+
Ok(bytes) => match SecretKey::from_slice(&bytes) {
98+
Ok(secret_key) => {
99+
let signing_keypair = Keypair::from_secret_key(&secp, &secret_key);
100+
Ok(encode_did_key(&signing_keypair.public_key()))
101+
}
102+
Err(error) => {
103+
tracing::error!("Error geting signing secret key from bytes\n{error}");
104+
Err(ApiError::RuntimeError)
105+
}
106+
},
107+
Err(error) => {
108+
tracing::error!("Unable to hex decode signing key\n{error}");
109+
Err(ApiError::RuntimeError)
110+
}
111+
}
112+
}

rsky-pds/src/apis/com/atproto/identity/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod get_recommended_did_credentials;
12
pub mod resolve_handle;
23
pub mod sign_plc_operation;
34
pub mod submit_plc_operation;

rsky-pds/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ async fn rocket() -> _ {
244244
com::atproto::admin::update_subject_status::update_subject_status,
245245
com::atproto::identity::resolve_handle::resolve_handle,
246246
com::atproto::identity::update_handle::update_handle,
247+
com::atproto::identity::get_recommended_did_credentials::get_recommended_did_credentials,
247248
com::atproto::identity::sign_plc_operation::sign_plc_operation,
248249
com::atproto::identity::submit_plc_operation::submit_plc_operation,
249250
com::atproto::repo::apply_writes::apply_writes,

0 commit comments

Comments
 (0)