WIP: Setup xrpc module and createAccount template
This commit is contained in:
parent
1f490cd296
commit
7eb0be102e
3 changed files with 193 additions and 33 deletions
|
|
@ -1,21 +1,11 @@
|
|||
use router::{
|
||||
Router,
|
||||
xrpc::{
|
||||
XrpcEndpoint,
|
||||
ProcedureInput,
|
||||
Response,
|
||||
error,
|
||||
},
|
||||
xrpc::XrpcEndpoint,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use atproto::types::Nsid;
|
||||
use http::status::StatusCode;
|
||||
use tracing::{
|
||||
event,
|
||||
instrument,
|
||||
Level,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
mod xrpc;
|
||||
use xrpc::create_account;
|
||||
|
||||
struct Config {
|
||||
entryway_url: String,
|
||||
|
|
@ -36,22 +26,3 @@ async fn main() {
|
|||
router.serve().await;
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct CreateAccountInput {
|
||||
email: Option<String>,
|
||||
handle: String,
|
||||
did: Option<String>,
|
||||
invite_code: Option<String>,
|
||||
verification_code: Option<String>,
|
||||
verification_phone: Option<String>,
|
||||
password: Option<String>,
|
||||
recovery_key: Option<String>,
|
||||
plc_op: Option<String>,
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn create_account(data: ProcedureInput<CreateAccountInput>) -> Response {
|
||||
event!(Level::INFO, "In create_account");
|
||||
|
||||
error(StatusCode::OK, "error", "message")
|
||||
}
|
||||
|
|
|
|||
186
entryway/src/xrpc/create_account.rs
Normal file
186
entryway/src/xrpc/create_account.rs
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
use router::xrpc::{ProcedureInput, Response, error};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use http::status::StatusCode;
|
||||
use tracing::{event, instrument, Level};
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct CreateAccountInput {
|
||||
pub email: Option<String>,
|
||||
pub handle: String,
|
||||
pub did: Option<String>,
|
||||
pub invite_code: Option<String>,
|
||||
pub verification_code: Option<String>,
|
||||
pub verification_phone: Option<String>,
|
||||
pub password: Option<String>,
|
||||
pub recovery_key: Option<String>,
|
||||
pub plc_op: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct CreateAccountResponse {
|
||||
pub handle: String,
|
||||
pub did: String,
|
||||
// pub did_doc: Option<DidDocument>, // TODO: Define DidDocument type
|
||||
pub access_jwt: String,
|
||||
pub refresh_jwt: String,
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub async fn create_account(data: ProcedureInput<CreateAccountInput>) -> Response {
|
||||
event!(Level::INFO, "Creating account for handle: {}", data.input.handle);
|
||||
|
||||
// TODO: Implement the following steps based on the TypeScript reference:
|
||||
|
||||
// 1. Input validation
|
||||
let validated_input = match validate_inputs(&data.input).await {
|
||||
Ok(input) => input,
|
||||
Err(err) => return err,
|
||||
};
|
||||
|
||||
// 2. Check handle and email availability
|
||||
if let Err(err) = check_availability(&validated_input).await {
|
||||
return err;
|
||||
}
|
||||
|
||||
// 3. Generate DID and signing key
|
||||
let (did, signing_key, plc_op) = match generate_identity(&validated_input).await {
|
||||
Ok(identity) => identity,
|
||||
Err(err) => return err,
|
||||
};
|
||||
|
||||
// 4. Create actor store entry
|
||||
if let Err(err) = create_actor_store(&did, &signing_key).await {
|
||||
return err;
|
||||
}
|
||||
|
||||
// 5. Create repository
|
||||
let repo_commit = match create_repository(&did).await {
|
||||
Ok(commit) => commit,
|
||||
Err(err) => return err,
|
||||
};
|
||||
|
||||
// 6. Submit PLC operation (if needed)
|
||||
if let Some(op) = plc_op {
|
||||
if let Err(err) = submit_plc_operation(&did, &op).await {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Create account and session
|
||||
let credentials = match create_account_and_session(&validated_input, &did, &repo_commit).await {
|
||||
Ok(creds) => creds,
|
||||
Err(err) => return err,
|
||||
};
|
||||
|
||||
// 8. Sequence events (identity, account, commit, sync)
|
||||
if let Err(err) = sequence_events(&did, &validated_input.handle, &repo_commit).await {
|
||||
return err;
|
||||
}
|
||||
|
||||
// 9. Update repo root
|
||||
if let Err(err) = update_repo_root(&did, &repo_commit).await {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Return success response
|
||||
let response = CreateAccountResponse {
|
||||
handle: validated_input.handle,
|
||||
did: did.clone(),
|
||||
access_jwt: credentials.access_jwt,
|
||||
refresh_jwt: credentials.refresh_jwt,
|
||||
};
|
||||
|
||||
event!(Level::INFO, "Account created successfully for DID: {}", did);
|
||||
|
||||
// TODO: Replace with proper JSON response encoding
|
||||
error(StatusCode::OK, "success", "Account created successfully")
|
||||
}
|
||||
|
||||
// TODO: Implement these helper functions
|
||||
|
||||
async fn validate_inputs(input: &CreateAccountInput) -> Result<ValidatedInput, Response> {
|
||||
// Based on validateInputsForLocalPds in the TypeScript version
|
||||
// - Validate email format and not disposable
|
||||
// - Validate password length
|
||||
// - Check invite code if required
|
||||
// - Normalize and validate handle
|
||||
todo!("Implement input validation")
|
||||
}
|
||||
|
||||
async fn check_availability(input: &ValidatedInput) -> Result<(), Response> {
|
||||
// Check that handle and email are not already taken
|
||||
todo!("Implement availability checking")
|
||||
}
|
||||
|
||||
async fn generate_identity(input: &ValidatedInput) -> Result<(String, SigningKey, Option<PlcOp>), Response> {
|
||||
// Generate signing key
|
||||
// Create DID and PLC operation if not provided
|
||||
todo!("Implement identity generation")
|
||||
}
|
||||
|
||||
async fn create_actor_store(did: &str, signing_key: &SigningKey) -> Result<(), Response> {
|
||||
// Create actor store entry for the new account
|
||||
todo!("Implement actor store creation")
|
||||
}
|
||||
|
||||
async fn create_repository(did: &str) -> Result<RepoCommit, Response> {
|
||||
// Create empty repository for the account
|
||||
todo!("Implement repository creation")
|
||||
}
|
||||
|
||||
async fn submit_plc_operation(did: &str, plc_op: &PlcOp) -> Result<(), Response> {
|
||||
// Submit PLC operation to register/update DID
|
||||
todo!("Implement PLC operation submission")
|
||||
}
|
||||
|
||||
async fn create_account_and_session(
|
||||
input: &ValidatedInput,
|
||||
did: &str,
|
||||
repo_commit: &RepoCommit,
|
||||
) -> Result<Credentials, Response> {
|
||||
// Create account record and initial session
|
||||
// Generate JWT tokens
|
||||
todo!("Implement account and session creation")
|
||||
}
|
||||
|
||||
async fn sequence_events(did: &str, handle: &str, repo_commit: &RepoCommit) -> Result<(), Response> {
|
||||
// Sequence identity, account, commit, and sync events
|
||||
todo!("Implement event sequencing")
|
||||
}
|
||||
|
||||
async fn update_repo_root(did: &str, repo_commit: &RepoCommit) -> Result<(), Response> {
|
||||
// Update repository root reference
|
||||
todo!("Implement repo root update")
|
||||
}
|
||||
|
||||
// TODO: Define these types based on our implementation needs
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ValidatedInput {
|
||||
handle: String,
|
||||
email: String,
|
||||
password: Option<String>,
|
||||
invite_code: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SigningKey {
|
||||
// TODO: Define signing key structure
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PlcOp {
|
||||
// TODO: Define PLC operation structure
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RepoCommit {
|
||||
cid: String,
|
||||
rev: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Credentials {
|
||||
access_jwt: String,
|
||||
refresh_jwt: String,
|
||||
}
|
||||
3
entryway/src/xrpc/mod.rs
Normal file
3
entryway/src/xrpc/mod.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub mod create_account;
|
||||
|
||||
pub use create_account::create_account;
|
||||
Loading…
Add table
Add a link
Reference in a new issue