WIP for laptop
This commit is contained in:
parent
55b583b6e6
commit
3b98eb4a95
5 changed files with 93 additions and 14 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.env
|
||||
.pds-data/
|
||||
target/
|
||||
tmp/
|
||||
|
||||
37
Cargo.lock
generated
37
Cargo.lock
generated
|
|
@ -79,6 +79,18 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"cpufeatures",
|
||||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.0"
|
||||
|
|
@ -283,6 +295,15 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
|
|
@ -667,11 +688,16 @@ dependencies = [
|
|||
name = "entryway"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"async-trait",
|
||||
"atproto",
|
||||
"http 1.3.1",
|
||||
"router",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"thiserror 2.0.12",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
|
|
@ -1589,6 +1615,17 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.7.0"
|
||||
|
|
|
|||
23
entryway/migrations/01_initial_schema.sql
Normal file
23
entryway/migrations/01_initial_schema.sql
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-- PDS Entryway Account Management Schema
|
||||
-- Minimal schema for account creation and authentication
|
||||
|
||||
-- Actor table - stores public identity information
|
||||
CREATE TABLE actor (
|
||||
did VARCHAR PRIMARY KEY,
|
||||
handle VARCHAR,
|
||||
created_at VARCHAR NOT NULL
|
||||
);
|
||||
|
||||
-- Case-insensitive unique index on handle
|
||||
CREATE UNIQUE INDEX actor_handle_lower_idx ON actor (LOWER(handle));
|
||||
|
||||
-- Account table - stores private authentication data
|
||||
CREATE TABLE account (
|
||||
did VARCHAR PRIMARY KEY,
|
||||
email VARCHAR NOT NULL,
|
||||
password_scrypt VARCHAR NOT NULL,
|
||||
email_confirmed_at VARCHAR
|
||||
);
|
||||
|
||||
-- Case-insensitive unique index on email
|
||||
CREATE UNIQUE INDEX account_email_lower_idx ON account (LOWER(email));
|
||||
|
|
@ -18,13 +18,21 @@ impl Default for Router {
|
|||
Self::new()
|
||||
}
|
||||
}
|
||||
impl Router {
|
||||
impl<S> Router<S>
|
||||
where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
let router = AxumRouter::new();
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), 6702);
|
||||
Router { router, addr }
|
||||
}
|
||||
|
||||
pub fn with_state<S2>(mut self, state: S) -> Router<S2> {
|
||||
self.router = self.with_state(S);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_endpoint<E: Endpoint>(mut self, endpoint: E) -> Self {
|
||||
self.router = endpoint.add_to_router(self.router);
|
||||
self
|
||||
|
|
|
|||
|
|
@ -52,8 +52,11 @@ pub fn response(code: StatusCode, message: &str) -> Response {
|
|||
error(code, "", message)
|
||||
}
|
||||
|
||||
pub struct QueryInput {
|
||||
pub struct QueryInput<S = ()>
|
||||
where S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
pub parameters: HashMap<String, String>,
|
||||
pub state: S,
|
||||
}
|
||||
impl<S> FromRequestParts<S> for QueryInput
|
||||
where
|
||||
|
|
@ -61,23 +64,26 @@ where
|
|||
{
|
||||
type Rejection = Response;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, _state: &S)
|
||||
async fn from_request_parts(parts: &mut Parts, state: &S)
|
||||
-> Result<Self, Self::Rejection> {
|
||||
let query_params: Result<Query<HashMap<String, String>>, QueryRejection> = Query::try_from_uri(&parts.uri);
|
||||
match query_params {
|
||||
Ok(p) => Ok(QueryInput { parameters: p.0 }),
|
||||
Ok(p) => Ok(QueryInput { parameters: p.0, state }),
|
||||
Err(e) => Err(error(StatusCode::BAD_REQUEST, "Bad Parameters", &e.body_text())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProcedureInput<J> {
|
||||
pub struct ProcedureInput<J, S = ()>
|
||||
where S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
pub parameters: HashMap<String, String>,
|
||||
pub input: J,
|
||||
pub state: S,
|
||||
}
|
||||
|
||||
impl<J, S> FromRequest<S> for ProcedureInput<J>
|
||||
impl<J, S> FromRequest<S> for ProcedureInput<J, S>
|
||||
where
|
||||
J: for<'de> serde::Deserialize<'de> + Send + 'static,
|
||||
Bytes: FromRequest<S>,
|
||||
|
|
@ -95,7 +101,7 @@ where
|
|||
.map(|Json(v)| v)
|
||||
.map_err(|e| error(StatusCode::BAD_REQUEST, "Bad Parameters", &e.body_text()))?;
|
||||
|
||||
Ok(ProcedureInput { parameters, input })
|
||||
Ok(ProcedureInput { parameters, input, state })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,14 +131,14 @@ where
|
|||
}
|
||||
|
||||
impl XrpcEndpoint {
|
||||
pub fn new_query<Q>(nsid: Nsid, query: Q) -> Self
|
||||
pub fn new_query<Q, S>(nsid: Nsid, query: Q) -> Self
|
||||
where
|
||||
Q: XrpcHandler<QueryInput> + Clone
|
||||
{
|
||||
XrpcEndpoint {
|
||||
path: Path::Nsid(nsid),
|
||||
resolver: get(async move | mut parts: Parts | -> Response {
|
||||
match QueryInput::from_request_parts(&mut parts, &()).await {
|
||||
resolver: get(async move | mut parts: Parts, state: &S | -> Response {
|
||||
match QueryInput<S>::from_request_parts(&mut parts, state).await {
|
||||
Ok(qi) => query.call(qi).await,
|
||||
Err(e) => e
|
||||
}
|
||||
|
|
@ -140,15 +146,15 @@ impl XrpcEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_procedure<P, J>(nsid: Nsid, procedure: P) -> Self
|
||||
pub fn new_procedure<P, J, S>(nsid: Nsid, procedure: P) -> Self
|
||||
where
|
||||
P: XrpcHandler<ProcedureInput<J>> + Clone,
|
||||
P: XrpcHandler<ProcedureInput<J, S>> + Clone,
|
||||
J: for<'de> serde::Deserialize<'de> + Send + 'static,
|
||||
{
|
||||
XrpcEndpoint {
|
||||
path: Path::Nsid(nsid),
|
||||
resolver: post(async move | req: Request | -> Response {
|
||||
match ProcedureInput::<J>::from_request(req, &()).await {
|
||||
resolver: post(async move | req: Request, state: &S | -> Response {
|
||||
match ProcedureInput::<J, S>::from_request(req, &state).await {
|
||||
Ok(pi) => procedure.call(pi).await,
|
||||
Err(e) => e
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue