mirror of
https://github.com/Blah-IM/blahrs.git
synced 2025-05-01 00:31:09 +00:00
doc: add and sync code docs from OAPI
This commit is contained in:
parent
71c5f038fa
commit
ee85112fb6
4 changed files with 31 additions and 2 deletions
|
@ -10,12 +10,16 @@ use ed25519_dalek::{
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// User pubkey pair to uniquely identity a user.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct UserKey {
|
pub struct UserKey {
|
||||||
|
/// The identity key (`id_key`).
|
||||||
pub id_key: PubKey,
|
pub id_key: PubKey,
|
||||||
|
/// The action key (`act_key`).
|
||||||
pub act_key: PubKey,
|
pub act_key: PubKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raw Ed25519 public key, serialized in hex-encoded string.
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct PubKey(#[serde(with = "hex::serde")] pub [u8; PUBLIC_KEY_LENGTH]);
|
pub struct PubKey(#[serde(with = "hex::serde")] pub [u8; PUBLIC_KEY_LENGTH]);
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub struct UserIdentityDesc {
|
||||||
pub profile: Signed<UserProfile>,
|
pub profile: Signed<UserProfile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error on verifying [`UserIdentityDesc`].
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
pub struct VerifyError(#[from] VerifyErrorImpl);
|
pub struct VerifyError(#[from] VerifyErrorImpl);
|
||||||
|
@ -44,6 +45,7 @@ enum VerifyErrorImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserIdentityDesc {
|
impl UserIdentityDesc {
|
||||||
|
/// The relative path from domain to the well-known identity description file.
|
||||||
pub const WELL_KNOWN_PATH: &str = "/.well-known/blah/identity.json";
|
pub const WELL_KNOWN_PATH: &str = "/.well-known/blah/identity.json";
|
||||||
|
|
||||||
/// Validate signatures of the identity description at given time.
|
/// Validate signatures of the identity description at given time.
|
||||||
|
@ -89,21 +91,33 @@ impl UserIdentityDesc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Description of an action key.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(tag = "typ", rename = "user_act_key")]
|
#[serde(tag = "typ", rename = "user_act_key")]
|
||||||
pub struct UserActKeyDesc {
|
pub struct UserActKeyDesc {
|
||||||
|
/// Per-device action key for signing msgs.
|
||||||
pub act_key: PubKey,
|
pub act_key: PubKey,
|
||||||
|
/// The UNIX timestamp of expire time.
|
||||||
pub expire_time: u64,
|
pub expire_time: u64,
|
||||||
|
/// User-provided arbitrary comment string.
|
||||||
pub comment: String,
|
pub comment: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// User profile describing their non-cryptographic metadata.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(tag = "typ", rename = "user_profile")]
|
#[serde(tag = "typ", rename = "user_profile")]
|
||||||
pub struct UserProfile {
|
pub struct UserProfile {
|
||||||
|
/// Preferred chat servers ordered by decreasing preference, for starting private chats.
|
||||||
pub preferred_chat_server_urls: Vec<Url>,
|
pub preferred_chat_server_urls: Vec<Url>,
|
||||||
|
/// Allowed identity URLs (`id_url`) where this profile should be retrieved on.
|
||||||
pub id_urls: Vec<IdUrl>,
|
pub id_urls: Vec<IdUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Identity URL.
|
||||||
|
///
|
||||||
|
/// In short, it must be a valid URL in format `https?://some.domain.name(:\d+)?/`.
|
||||||
|
/// Servers may pose additional requirement including: requiring HTTPS, rejecting ports,
|
||||||
|
/// rejecting `localhost` or local hostnames, and etc.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||||
#[serde(try_from = "Url")]
|
#[serde(try_from = "Url")]
|
||||||
pub struct IdUrl(Url);
|
pub struct IdUrl(Url);
|
||||||
|
@ -128,6 +142,7 @@ impl IdUrl {
|
||||||
/// which is 64. Adding the schema and port, it should still be below 80.
|
/// which is 64. Adding the schema and port, it should still be below 80.
|
||||||
///
|
///
|
||||||
/// Ref: <https://www.rfc-editor.org/rfc/rfc3280>
|
/// Ref: <https://www.rfc-editor.org/rfc/rfc3280>
|
||||||
|
// TODO: IPFS URLs can be extensively long, should we keep this limit?
|
||||||
pub const MAX_LEN: usize = 80;
|
pub const MAX_LEN: usize = 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +154,7 @@ impl ops::Deref for IdUrl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error on validating [`IdUrl`].
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Error)]
|
#[derive(Debug, Clone, PartialEq, Eq, Error)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum IdUrlError {
|
pub enum IdUrlError {
|
||||||
|
|
|
@ -55,9 +55,15 @@ impl<T> WithMsgId<T> {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(tag = "typ", rename = "user_register")]
|
#[serde(tag = "typ", rename = "user_register")]
|
||||||
pub struct UserRegisterPayload {
|
pub struct UserRegisterPayload {
|
||||||
|
/// The normalized server URL to register on.
|
||||||
|
/// It must matches chat server's base_url.
|
||||||
pub server_url: Url,
|
pub server_url: Url,
|
||||||
|
/// The normalized identity URL.
|
||||||
|
/// It should be in form `https://<domain>/`.
|
||||||
pub id_url: IdUrl,
|
pub id_url: IdUrl,
|
||||||
|
/// Hex encoded user primary key (`id_key`).
|
||||||
pub id_key: PubKey,
|
pub id_key: PubKey,
|
||||||
|
/// Server specific register challenge.
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub challenge: Option<UserRegisterChallengeResponse>,
|
pub challenge: Option<UserRegisterChallengeResponse>,
|
||||||
}
|
}
|
||||||
|
@ -68,7 +74,10 @@ pub struct UserRegisterPayload {
|
||||||
pub enum UserRegisterChallengeResponse {
|
pub enum UserRegisterChallengeResponse {
|
||||||
/// Proof of work challenge containing the same nonce from server challenge request.
|
/// Proof of work challenge containing the same nonce from server challenge request.
|
||||||
/// The whole msg signee hash should have enough prefix zero bits.
|
/// The whole msg signee hash should have enough prefix zero bits.
|
||||||
Pow { nonce: u32 },
|
Pow {
|
||||||
|
/// The challenge nonce retrieved from a recent GET response of `/_blah/user/me`.
|
||||||
|
nonce: u32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: `deny_unknown_fields` breaks this.
|
// FIXME: `deny_unknown_fields` breaks this.
|
||||||
|
|
|
@ -128,7 +128,7 @@ pub struct RoomMetadata {
|
||||||
/// Response to list room msgs.
|
/// Response to list room msgs.
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct RoomMsgs {
|
pub struct RoomMsgs {
|
||||||
/// Result list of msgs.
|
/// Result list of msgs ordered in reverse of server-received time.
|
||||||
pub msgs: Vec<SignedChatMsgWithId>,
|
pub msgs: Vec<SignedChatMsgWithId>,
|
||||||
/// The skip-token to fetch the next page.
|
/// The skip-token to fetch the next page.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
|
Loading…
Add table
Reference in a new issue