+8
-8
src/auth.rs
+8
-8
src/auth.rs
···
8
8
use axum::{extract::FromRequestParts, http::StatusCode};
9
9
use base64::Engine;
10
10
11
-
use crate::{AppState, Error, auth, error::ErrorMessage};
11
+
use crate::{AppState, Error, error::ErrorMessage};
12
12
13
13
/// This is an axum request extractor that represents an authenticated user.
14
14
///
15
15
/// If specified in an API endpoint, this will guarantee that the API can only be called
16
16
/// by an authenticated user.
17
-
pub struct AuthenticatedUser {
17
+
pub(crate) struct AuthenticatedUser {
18
18
did: String,
19
19
}
20
20
21
21
impl AuthenticatedUser {
22
-
pub fn did(&self) -> String {
22
+
pub(crate) fn did(&self) -> String {
23
23
self.did.clone()
24
24
}
25
25
}
26
26
27
27
impl FromRequestParts<AppState> for AuthenticatedUser {
28
-
type Rejection = crate::Error;
28
+
type Rejection = Error;
29
29
30
30
async fn from_request_parts(
31
31
parts: &mut axum::http::request::Parts,
32
32
state: &AppState,
33
-
) -> std::result::Result<Self, Self::Rejection> {
33
+
) -> Result<Self, Self::Rejection> {
34
34
let token = parts
35
35
.headers
36
36
.get(axum::http::header::AUTHORIZATION)
···
52
52
53
53
// N.B: We ignore all fields inside of the token up until this point because they can be
54
54
// attacker-controlled.
55
-
let (typ, claims) = auth::verify(&state.signing_key.did(), token).map_err(|e| {
55
+
let (typ, claims) = verify(&state.signing_key.did(), token).map_err(|e| {
56
56
Error::with_status(
57
57
StatusCode::UNAUTHORIZED,
58
58
e.context("failed to verify auth token"),
···
97
97
}
98
98
99
99
/// Cryptographically sign a JSON web token with the specified key.
100
-
pub fn sign(
100
+
pub(crate) fn sign(
101
101
key: &Secp256k1Keypair,
102
102
typ: &str,
103
103
claims: serde_json::Value,
···
120
120
}
121
121
122
122
/// Cryptographically verify a JSON web token's validity using the specified public key.
123
-
pub fn verify(key: &str, token: &str) -> anyhow::Result<(String, serde_json::Value)> {
123
+
pub(crate) fn verify(key: &str, token: &str) -> anyhow::Result<(String, serde_json::Value)> {
124
124
let mut parts = token.splitn(3, '.');
125
125
let hdr = parts.next().context("no header")?;
126
126
let claims = parts.next().context("no claims")?;
+8
-8
src/config.rs
+8
-8
src/config.rs
···
3
3
use serde::Deserialize;
4
4
use url::Url;
5
5
6
-
pub mod metrics {
6
+
pub(crate) mod metrics {
7
7
use super::*;
8
8
9
9
#[derive(Deserialize, Debug, Clone)]
10
-
pub struct PrometheusConfig {
10
+
pub(crate) struct PrometheusConfig {
11
11
/// The URL of the Prometheus server's exporter endpoint.
12
12
pub url: Url,
13
13
}
···
15
15
16
16
#[derive(Deserialize, Debug, Clone)]
17
17
#[serde(tag = "type")]
18
-
pub enum MetricConfig {
18
+
pub(crate) enum MetricConfig {
19
19
PrometheusPush(metrics::PrometheusConfig),
20
20
}
21
21
22
22
#[derive(Deserialize, Debug, Clone)]
23
-
pub struct FirehoseConfig {
23
+
pub(crate) struct FirehoseConfig {
24
24
/// A list of upstream relays that this PDS will try to reach out to.
25
25
pub relays: Vec<Url>,
26
26
}
27
27
28
28
#[derive(Deserialize, Debug, Clone)]
29
-
pub struct RepoConfig {
29
+
pub(crate) struct RepoConfig {
30
30
/// The path to the repository storage.
31
31
pub path: PathBuf,
32
32
}
33
33
34
34
#[derive(Deserialize, Debug, Clone)]
35
-
pub struct PlcConfig {
35
+
pub(crate) struct PlcConfig {
36
36
/// The path to the local PLC cache.
37
37
pub path: PathBuf,
38
38
}
39
39
40
40
#[derive(Deserialize, Debug, Clone)]
41
-
pub struct BlobConfig {
41
+
pub(crate) struct BlobConfig {
42
42
/// The path to store blobs into.
43
43
pub path: PathBuf,
44
44
/// The maximum size limit of blobs.
···
46
46
}
47
47
48
48
#[derive(Deserialize, Debug, Clone)]
49
-
pub struct AppConfig {
49
+
pub(crate) struct AppConfig {
50
50
/// The primary signing keys for all PLC/DID operations.
51
51
pub key: PathBuf,
52
52
/// The hostname of the PDS. Typically a domain name.
+4
-4
src/did.rs
+4
-4
src/did.rs
···
10
10
11
11
#[derive(Clone, Debug, Serialize, Deserialize)]
12
12
#[serde(rename_all = "camelCase")]
13
-
pub struct DidVerificationMethod {
13
+
pub(crate) struct DidVerificationMethod {
14
14
pub id: String,
15
15
#[serde(rename = "type")]
16
16
pub ty: String,
···
20
20
21
21
#[derive(Clone, Debug, Serialize, Deserialize)]
22
22
#[serde(rename_all = "camelCase")]
23
-
pub struct DidService {
23
+
pub(crate) struct DidService {
24
24
pub id: String,
25
25
#[serde(rename = "type")]
26
26
pub ty: String,
···
29
29
30
30
#[derive(Clone, Debug, Serialize, Deserialize)]
31
31
#[serde(rename_all = "camelCase")]
32
-
pub struct DidDocument {
32
+
pub(crate) struct DidDocument {
33
33
#[serde(rename = "@context", skip_serializing_if = "Vec::is_empty")]
34
34
pub context: Vec<Url>,
35
35
pub id: Did,
···
39
39
}
40
40
41
41
/// Resolve a DID document using the specified reqwest client.
42
-
pub async fn resolve(client: &Client, did: Did) -> Result<DidDocument> {
42
+
pub(crate) async fn resolve(client: &Client, did: Did) -> Result<DidDocument> {
43
43
let url = match did.method() {
44
44
"did:web" => {
45
45
// N.B: This is a potentially hostile operation, so we are only going to allow
+1
-1
src/endpoints/identity.rs
+1
-1
src/endpoints/identity.rs
···
181
181
}
182
182
183
183
#[rustfmt::skip]
184
-
pub fn routes() -> Router<AppState> {
184
+
pub(super) fn routes() -> Router<AppState> {
185
185
// AP /xrpc/com.atproto.identity.updateHandle
186
186
// AP /xrpc/com.atproto.identity.requestPlcOperationSignature
187
187
// AP /xrpc/com.atproto.identity.signPlcOperation
+2
-2
src/endpoints/mod.rs
+2
-2
src/endpoints/mod.rs
···
8
8
mod server;
9
9
mod sync;
10
10
11
-
pub async fn health() -> Result<Json<serde_json::Value>> {
11
+
pub(crate) async fn health() -> Result<Json<serde_json::Value>> {
12
12
Ok(Json(json!({
13
13
"version": "bluepds"
14
14
})))
15
15
}
16
16
17
-
pub fn routes() -> Router<AppState> {
17
+
pub(crate) fn routes() -> Router<AppState> {
18
18
Router::new()
19
19
.route("/_health", get(health))
20
20
.merge(identity::routes()) // com.atproto.identity
+12
-12
src/endpoints/repo.rs
+12
-12
src/endpoints/repo.rs
···
350
350
351
351
// The swap failed. Return the old commit and do not update the repository.
352
352
return Ok(Json(
353
-
repo::apply_writes::OutputData {
353
+
apply_writes::OutputData {
354
354
results: None,
355
355
commit: Some(
356
356
CommitMetaData {
···
438
438
.await;
439
439
440
440
Ok(Json(
441
-
repo::apply_writes::OutputData {
441
+
apply_writes::OutputData {
442
442
results: Some(res),
443
443
commit: Some(
444
444
CommitMetaData {
···
702
702
703
703
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
704
704
#[serde(rename_all = "camelCase")]
705
-
pub struct ListRecordsParameters {
705
+
pub(super) struct ListRecordsParameters {
706
706
///The NSID of the record type.
707
-
pub collection: atrium_api::types::string::Nsid,
707
+
pub collection: Nsid,
708
708
#[serde(skip_serializing_if = "core::option::Option::is_none")]
709
-
pub cursor: core::option::Option<String>,
709
+
pub cursor: Option<String>,
710
710
///The number of records to return.
711
711
#[serde(skip_serializing_if = "core::option::Option::is_none")]
712
-
pub limit: core::option::Option<String>,
712
+
pub limit: Option<String>,
713
713
///The handle or DID of the repo.
714
-
pub repo: atrium_api::types::string::AtIdentifier,
714
+
pub repo: AtIdentifier,
715
715
///Flag to reverse the order of the returned records.
716
716
#[serde(skip_serializing_if = "core::option::Option::is_none")]
717
-
pub reverse: core::option::Option<bool>,
717
+
pub reverse: Option<bool>,
718
718
///DEPRECATED: The highest sort-ordered rkey to stop at (exclusive)
719
719
#[serde(skip_serializing_if = "core::option::Option::is_none")]
720
-
pub rkey_end: core::option::Option<String>,
720
+
pub rkey_end: Option<String>,
721
721
///DEPRECATED: The lowest sort-ordered rkey to start from (exclusive)
722
722
#[serde(skip_serializing_if = "core::option::Option::is_none")]
723
-
pub rkey_start: core::option::Option<String>,
723
+
pub rkey_start: Option<String>,
724
724
}
725
725
726
726
async fn list_records(
···
845
845
drop(file);
846
846
let hash = sha.finalize();
847
847
848
-
let cid = atrium_repo::Cid::new_v1(
848
+
let cid = Cid::new_v1(
849
849
IPLD_RAW,
850
850
atrium_repo::Multihash::wrap(IPLD_MH_SHA2_256, hash.as_slice()).unwrap(),
851
851
);
···
885
885
}
886
886
887
887
#[rustfmt::skip]
888
-
pub fn routes() -> Router<AppState> {
888
+
pub(super) fn routes() -> Router<AppState> {
889
889
// AP /xrpc/com.atproto.repo.applyWrites
890
890
// AP /xrpc/com.atproto.repo.createRecord
891
891
// AP /xrpc/com.atproto.repo.putRecord
+5
-5
src/endpoints/server.rs
+5
-5
src/endpoints/server.rs
···
373
373
// SEC: Call argon2's `verify_password` to simulate password verification and discard the result.
374
374
// We do this to avoid exposing a timing attack where attackers can measure the response time to
375
375
// determine whether or not an account exists.
376
-
let _ = argon2::Argon2::default().verify_password(
376
+
let _ = Argon2::default().verify_password(
377
377
password.as_bytes(),
378
378
&PasswordHash::new(DUMMY_PASSWORD).unwrap(),
379
379
);
···
384
384
));
385
385
};
386
386
387
-
match argon2::Argon2::default().verify_password(
387
+
match Argon2::default().verify_password(
388
388
password.as_bytes(),
389
389
&PasswordHash::new(account.password.as_str()).context("invalid password hash in db")?,
390
390
) {
···
517
517
refresh_jwt: refresh_token,
518
518
519
519
active: Some(active), // TODO?
520
-
did: atrium_api::types::string::Did::new(did.to_string()).unwrap(),
520
+
did: Did::new(did.to_string()).unwrap(),
521
521
did_doc: None,
522
-
handle: atrium_api::types::string::Handle::new(user.handle).unwrap(),
522
+
handle: Handle::new(user.handle).unwrap(),
523
523
status,
524
524
}
525
525
.into(),
···
624
624
}
625
625
626
626
#[rustfmt::skip]
627
-
pub fn routes() -> Router<AppState> {
627
+
pub(super) fn routes() -> Router<AppState> {
628
628
// UG /xrpc/com.atproto.server.describeServer
629
629
// UP /xrpc/com.atproto.server.createAccount
630
630
// UP /xrpc/com.atproto.server.createSession
+12
-12
src/endpoints/sync.rs
+12
-12
src/endpoints/sync.rs
···
194
194
// HACK: `limit` may be passed as a string, so we must treat it as one.
195
195
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
196
196
#[serde(rename_all = "camelCase")]
197
-
pub struct ListBlobsParameters {
197
+
pub(super) struct ListBlobsParameters {
198
198
#[serde(skip_serializing_if = "core::option::Option::is_none")]
199
-
pub cursor: core::option::Option<String>,
199
+
pub cursor: Option<String>,
200
200
///The DID of the repo.
201
-
pub did: atrium_api::types::string::Did,
201
+
pub did: Did,
202
202
#[serde(skip_serializing_if = "core::option::Option::is_none")]
203
-
pub limit: core::option::Option<String>,
203
+
pub limit: Option<String>,
204
204
///Optional revision of the repo to list blobs since.
205
205
#[serde(skip_serializing_if = "core::option::Option::is_none")]
206
-
pub since: core::option::Option<String>,
206
+
pub since: Option<String>,
207
207
}
208
208
209
209
async fn list_blobs(
···
224
224
let cids = cids
225
225
.into_iter()
226
226
.map(|c| {
227
-
atrium_repo::Cid::from_str(&c)
227
+
Cid::from_str(&c)
228
228
.map(atrium_api::types::string::Cid::new)
229
229
.map_err(anyhow::Error::new)
230
230
})
···
239
239
// HACK: `limit` may be passed as a string, so we must treat it as one.
240
240
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
241
241
#[serde(rename_all = "camelCase")]
242
-
pub struct ListReposParameters {
242
+
pub(super) struct ListReposParameters {
243
243
#[serde(skip_serializing_if = "core::option::Option::is_none")]
244
-
pub cursor: core::option::Option<String>,
244
+
pub cursor: Option<String>,
245
245
#[serde(skip_serializing_if = "core::option::Option::is_none")]
246
-
pub limit: core::option::Option<String>,
246
+
pub limit: Option<String>,
247
247
}
248
248
249
249
async fn list_repos(
···
309
309
// HACK: `cursor` may be passed as a string, so we must treat it as one.
310
310
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
311
311
#[serde(rename_all = "camelCase")]
312
-
pub struct SubscribeReposParametersData {
312
+
pub(super) struct SubscribeReposParametersData {
313
313
///The last known event seq number to backfill from.
314
314
#[serde(skip_serializing_if = "core::option::Option::is_none")]
315
-
pub cursor: core::option::Option<String>,
315
+
pub cursor: Option<String>,
316
316
}
317
317
318
318
async fn subscribe_repos(
···
336
336
}
337
337
338
338
#[rustfmt::skip]
339
-
pub fn routes() -> axum::Router<AppState> {
339
+
pub(super) fn routes() -> Router<AppState> {
340
340
// UG /xrpc/com.atproto.sync.getBlob
341
341
// UG /xrpc/com.atproto.sync.getBlocks
342
342
// UG /xrpc/com.atproto.sync.getLatestCommit
+1
-1
src/error.rs
+1
-1
src/error.rs
+9
-9
src/firehose.rs
+9
-9
src/firehose.rs
···
20
20
21
21
enum FirehoseMessage {
22
22
Broadcast(sync::subscribe_repos::Message),
23
-
Connect(Box<(axum::extract::ws::WebSocket, Option<i64>)>),
23
+
Connect(Box<(WebSocket, Option<i64>)>),
24
24
}
25
25
26
26
enum FrameHeader {
···
120
120
121
121
/// A firehose producer. This is used to transmit messages to the firehose for broadcast.
122
122
#[derive(Clone, Debug)]
123
-
pub struct FirehoseProducer {
123
+
pub(crate) struct FirehoseProducer {
124
124
tx: tokio::sync::mpsc::Sender<FirehoseMessage>,
125
125
}
126
126
127
127
impl FirehoseProducer {
128
128
/// Broadcast an `#account` event.
129
-
pub async fn account(&self, account: impl Into<sync::subscribe_repos::Account>) {
129
+
pub(crate) async fn account(&self, account: impl Into<sync::subscribe_repos::Account>) {
130
130
let _ = self
131
131
.tx
132
132
.send(FirehoseMessage::Broadcast(
···
136
136
}
137
137
138
138
/// Broadcast an `#identity` event.
139
-
pub async fn identity(&self, identity: impl Into<sync::subscribe_repos::Identity>) {
139
+
pub(crate) async fn identity(&self, identity: impl Into<sync::subscribe_repos::Identity>) {
140
140
let _ = self
141
141
.tx
142
142
.send(FirehoseMessage::Broadcast(
···
146
146
}
147
147
148
148
/// Broadcast a `#commit` event.
149
-
pub async fn commit(&self, commit: impl Into<sync::subscribe_repos::Commit>) {
149
+
pub(crate) async fn commit(&self, commit: impl Into<sync::subscribe_repos::Commit>) {
150
150
let _ = self
151
151
.tx
152
152
.send(FirehoseMessage::Broadcast(
···
155
155
.await;
156
156
}
157
157
158
-
pub async fn client_connection(&self, ws: WebSocket, cursor: Option<i64>) {
158
+
pub(crate) async fn client_connection(&self, ws: WebSocket, cursor: Option<i64>) {
159
159
let _ = self
160
160
.tx
161
161
.send(FirehoseMessage::Connect(Box::new((ws, cursor))))
···
213
213
seq: u64,
214
214
history: &VecDeque<(u64, &str, sync::subscribe_repos::Message)>,
215
215
cursor: Option<i64>,
216
-
) -> anyhow::Result<WebSocket> {
216
+
) -> Result<WebSocket> {
217
217
if let Some(cursor) = cursor {
218
218
let mut frame = Vec::new();
219
219
let cursor = cursor as u64;
···
257
257
Ok(ws)
258
258
}
259
259
260
-
pub async fn reconnect_relays(client: &Client, config: &AppConfig) {
260
+
pub(crate) async fn reconnect_relays(client: &Client, config: &AppConfig) {
261
261
// Avoid connecting to upstream relays in test mode.
262
262
if config.test {
263
263
return;
···
308
308
/// This will broadcast all updates in this PDS out to anyone who is listening.
309
309
///
310
310
/// Reference: https://atproto.com/specs/sync
311
-
pub async fn spawn(
311
+
pub(crate) async fn spawn(
312
312
client: Client,
313
313
config: AppConfig,
314
314
) -> (tokio::task::JoinHandle<()>, FirehoseProducer) {
+4
-4
src/main.rs
+4
-4
src/main.rs
···
42
42
mod plc;
43
43
mod storage;
44
44
45
-
pub type Result<T> = std::result::Result<T, error::Error>;
45
+
pub type Result<T> = std::result::Result<T, Error>;
46
46
pub use error::Error;
47
47
use uuid::Uuid;
48
48
49
49
pub type Client = reqwest_middleware::ClientWithMiddleware;
50
-
pub type Db = sqlx::SqlitePool;
50
+
pub type Db = SqlitePool;
51
51
pub type Cred = Arc<dyn TokenCredential>;
52
52
53
53
pub const APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
···
191
191
}
192
192
193
193
#[rustfmt::skip]
194
-
pub fn routes() -> Router<AppState> {
194
+
pub(crate) fn routes() -> Router<AppState> {
195
195
// AP /xrpc/app.bsky.actor.putPreferences
196
196
// AG /xrpc/app.bsky.actor.getPreferences
197
197
Router::new()
···
289
289
let r = client
290
290
.request(request.method().clone(), url)
291
291
.headers(h)
292
-
.header(axum::http::header::AUTHORIZATION, format!("Bearer {token}"))
292
+
.header(http::header::AUTHORIZATION, format!("Bearer {token}"))
293
293
.body(reqwest::Body::wrap_stream(
294
294
request.into_body().into_data_stream(),
295
295
))
+10
-10
src/metrics.rs
+10
-10
src/metrics.rs
···
8
8
9
9
use crate::config;
10
10
11
-
pub const AUTH_FAILED: &str = "bluepds.auth.failed"; // Counter.
11
+
pub(crate) const AUTH_FAILED: &str = "bluepds.auth.failed"; // Counter.
12
12
13
-
pub const FIREHOSE_HISTORY: &str = "bluepds.firehose.history"; // Gauge.
14
-
pub const FIREHOSE_LISTENERS: &str = "bluepds.firehose.listeners"; // Gauge.
15
-
pub const FIREHOSE_MESSAGES: &str = "bluepds.firehose.messages"; // Counter.
16
-
pub const FIREHOSE_SEQUENCE: &str = "bluepds.firehose.sequence"; // Counter.
13
+
pub(crate) const FIREHOSE_HISTORY: &str = "bluepds.firehose.history"; // Gauge.
14
+
pub(crate) const FIREHOSE_LISTENERS: &str = "bluepds.firehose.listeners"; // Gauge.
15
+
pub(crate) const FIREHOSE_MESSAGES: &str = "bluepds.firehose.messages"; // Counter.
16
+
pub(crate) const FIREHOSE_SEQUENCE: &str = "bluepds.firehose.sequence"; // Counter.
17
17
18
-
pub const REPO_COMMITS: &str = "bluepds.repo.commits"; // Counter.
19
-
pub const REPO_OP_CREATE: &str = "bluepds.repo.op.create"; // Counter.
20
-
pub const REPO_OP_UPDATE: &str = "bluepds.repo.op.update"; // Counter.
21
-
pub const REPO_OP_DELETE: &str = "bluepds.repo.op.delete"; // Counter.
18
+
pub(crate) const REPO_COMMITS: &str = "bluepds.repo.commits"; // Counter.
19
+
pub(crate) const REPO_OP_CREATE: &str = "bluepds.repo.op.create"; // Counter.
20
+
pub(crate) const REPO_OP_UPDATE: &str = "bluepds.repo.op.update"; // Counter.
21
+
pub(crate) const REPO_OP_DELETE: &str = "bluepds.repo.op.delete"; // Counter.
22
22
23
23
/// Must be ran exactly once on startup. This will declare all of the instruments for `metrics`.
24
-
pub fn setup(config: &Option<config::MetricConfig>) -> anyhow::Result<()> {
24
+
pub(crate) fn setup(config: &Option<config::MetricConfig>) -> anyhow::Result<()> {
25
25
describe_counter!(AUTH_FAILED, "The number of failed authentication attempts.");
26
26
27
27
describe_gauge!(FIREHOSE_HISTORY, "The size of the firehose history buffer.");
+6
-6
src/plc.rs
+6
-6
src/plc.rs
···
12
12
13
13
#[derive(Debug, Deserialize, Serialize, Clone)]
14
14
#[serde(rename_all = "camelCase", tag = "type")]
15
-
pub enum PlcService {
15
+
pub(crate) enum PlcService {
16
16
#[serde(rename = "AtprotoPersonalDataServer")]
17
17
Pds { endpoint: String },
18
18
}
19
19
20
20
#[derive(Debug, Deserialize, Serialize, Clone)]
21
21
#[serde(rename_all = "camelCase")]
22
-
pub struct PlcOperation {
22
+
pub(crate) struct PlcOperation {
23
23
#[serde(rename = "type")]
24
24
pub typ: String,
25
25
pub rotation_keys: Vec<String>,
···
30
30
}
31
31
32
32
impl PlcOperation {
33
-
pub fn sign(self, sig: Vec<u8>) -> SignedPlcOperation {
33
+
pub(crate) fn sign(self, sig: Vec<u8>) -> SignedPlcOperation {
34
34
SignedPlcOperation {
35
35
typ: self.typ,
36
36
rotation_keys: self.rotation_keys,
···
45
45
46
46
#[derive(Debug, Deserialize, Serialize, Clone)]
47
47
#[serde(rename_all = "camelCase")]
48
-
pub struct SignedPlcOperation {
48
+
pub(crate) struct SignedPlcOperation {
49
49
#[serde(rename = "type")]
50
50
pub typ: String,
51
51
pub rotation_keys: Vec<String>,
···
56
56
pub sig: String,
57
57
}
58
58
59
-
pub async fn sign_op(rkey: &RotationKey, op: PlcOperation) -> anyhow::Result<SignedPlcOperation> {
59
+
pub(crate) async fn sign_op(rkey: &RotationKey, op: PlcOperation) -> anyhow::Result<SignedPlcOperation> {
60
60
let bytes = serde_ipld_dagcbor::to_vec(&op).context("failed to encode op")?;
61
61
let bytes = rkey.sign(&bytes).context("failed to sign op")?;
62
62
···
64
64
}
65
65
66
66
/// Submit a PLC operation to the public directory.
67
-
pub async fn submit(client: &Client, did: &str, op: &SignedPlcOperation) -> anyhow::Result<()> {
67
+
pub(crate) async fn submit(client: &Client, did: &str, op: &SignedPlcOperation) -> anyhow::Result<()> {
68
68
debug!("submitting {} {}", did, serde_json::to_string(&op).unwrap());
69
69
70
70
let res = client
+3
-3
src/storage.rs
+3
-3
src/storage.rs
···
10
10
11
11
use crate::{Db, config::RepoConfig};
12
12
13
-
pub async fn open_store(
13
+
pub(crate) async fn open_store(
14
14
config: &RepoConfig,
15
15
did: impl Into<String>,
16
16
) -> Result<impl AsyncBlockStoreRead + AsyncBlockStoreWrite> {
···
31
31
CarStore::open(f).await.context("failed to open car store")
32
32
}
33
33
34
-
pub async fn open_repo_db(
34
+
pub(crate) async fn open_repo_db(
35
35
config: &RepoConfig,
36
36
db: &Db,
37
37
did: impl Into<String>,
···
51
51
open_repo(config, did, Cid::from_str(&cid).unwrap()).await
52
52
}
53
53
54
-
pub async fn open_repo(
54
+
pub(crate) async fn open_repo(
55
55
config: &RepoConfig,
56
56
did: impl Into<String>,
57
57
cid: Cid,