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",
|
"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]]
|
[[package]]
|
||||||
name = "async-lock"
|
name = "async-lock"
|
||||||
version = "3.4.0"
|
version = "3.4.0"
|
||||||
|
|
@ -283,6 +295,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake2"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
|
@ -667,11 +688,16 @@ dependencies = [
|
||||||
name = "entryway"
|
name = "entryway"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argon2",
|
||||||
|
"async-trait",
|
||||||
"atproto",
|
"atproto",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"router",
|
"router",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sqlx",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
|
@ -1589,6 +1615,17 @@ dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"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]]
|
[[package]]
|
||||||
name = "pem-rfc7468"
|
name = "pem-rfc7468"
|
||||||
version = "0.7.0"
|
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()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Router {
|
impl<S> Router<S>
|
||||||
|
where
|
||||||
|
S: Clone + Send + Sync + 'static,
|
||||||
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let router = AxumRouter::new();
|
let router = AxumRouter::new();
|
||||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), 6702);
|
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), 6702);
|
||||||
Router { router, addr }
|
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 {
|
pub fn add_endpoint<E: Endpoint>(mut self, endpoint: E) -> Self {
|
||||||
self.router = endpoint.add_to_router(self.router);
|
self.router = endpoint.add_to_router(self.router);
|
||||||
self
|
self
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,11 @@ pub fn response(code: StatusCode, message: &str) -> Response {
|
||||||
error(code, "", message)
|
error(code, "", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QueryInput {
|
pub struct QueryInput<S = ()>
|
||||||
|
where S: Clone + Send + Sync + 'static,
|
||||||
|
{
|
||||||
pub parameters: HashMap<String, String>,
|
pub parameters: HashMap<String, String>,
|
||||||
|
pub state: S,
|
||||||
}
|
}
|
||||||
impl<S> FromRequestParts<S> for QueryInput
|
impl<S> FromRequestParts<S> for QueryInput
|
||||||
where
|
where
|
||||||
|
|
@ -61,23 +64,26 @@ where
|
||||||
{
|
{
|
||||||
type Rejection = Response;
|
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> {
|
-> Result<Self, Self::Rejection> {
|
||||||
let query_params: Result<Query<HashMap<String, String>>, QueryRejection> = Query::try_from_uri(&parts.uri);
|
let query_params: Result<Query<HashMap<String, String>>, QueryRejection> = Query::try_from_uri(&parts.uri);
|
||||||
match query_params {
|
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())),
|
Err(e) => Err(error(StatusCode::BAD_REQUEST, "Bad Parameters", &e.body_text())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ProcedureInput<J> {
|
pub struct ProcedureInput<J, S = ()>
|
||||||
|
where S: Clone + Send + Sync + 'static,
|
||||||
|
{
|
||||||
pub parameters: HashMap<String, String>,
|
pub parameters: HashMap<String, String>,
|
||||||
pub input: J,
|
pub input: J,
|
||||||
|
pub state: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<J, S> FromRequest<S> for ProcedureInput<J>
|
impl<J, S> FromRequest<S> for ProcedureInput<J, S>
|
||||||
where
|
where
|
||||||
J: for<'de> serde::Deserialize<'de> + Send + 'static,
|
J: for<'de> serde::Deserialize<'de> + Send + 'static,
|
||||||
Bytes: FromRequest<S>,
|
Bytes: FromRequest<S>,
|
||||||
|
|
@ -95,7 +101,7 @@ where
|
||||||
.map(|Json(v)| v)
|
.map(|Json(v)| v)
|
||||||
.map_err(|e| error(StatusCode::BAD_REQUEST, "Bad Parameters", &e.body_text()))?;
|
.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 {
|
impl XrpcEndpoint {
|
||||||
pub fn new_query<Q>(nsid: Nsid, query: Q) -> Self
|
pub fn new_query<Q, S>(nsid: Nsid, query: Q) -> Self
|
||||||
where
|
where
|
||||||
Q: XrpcHandler<QueryInput> + Clone
|
Q: XrpcHandler<QueryInput> + Clone
|
||||||
{
|
{
|
||||||
XrpcEndpoint {
|
XrpcEndpoint {
|
||||||
path: Path::Nsid(nsid),
|
path: Path::Nsid(nsid),
|
||||||
resolver: get(async move | mut parts: Parts | -> Response {
|
resolver: get(async move | mut parts: Parts, state: &S | -> Response {
|
||||||
match QueryInput::from_request_parts(&mut parts, &()).await {
|
match QueryInput<S>::from_request_parts(&mut parts, state).await {
|
||||||
Ok(qi) => query.call(qi).await,
|
Ok(qi) => query.call(qi).await,
|
||||||
Err(e) => e
|
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
|
where
|
||||||
P: XrpcHandler<ProcedureInput<J>> + Clone,
|
P: XrpcHandler<ProcedureInput<J, S>> + Clone,
|
||||||
J: for<'de> serde::Deserialize<'de> + Send + 'static,
|
J: for<'de> serde::Deserialize<'de> + Send + 'static,
|
||||||
{
|
{
|
||||||
XrpcEndpoint {
|
XrpcEndpoint {
|
||||||
path: Path::Nsid(nsid),
|
path: Path::Nsid(nsid),
|
||||||
resolver: post(async move | req: Request | -> Response {
|
resolver: post(async move | req: Request, state: &S | -> Response {
|
||||||
match ProcedureInput::<J>::from_request(req, &()).await {
|
match ProcedureInput::<J, S>::from_request(req, &state).await {
|
||||||
Ok(pi) => procedure.call(pi).await,
|
Ok(pi) => procedure.call(pi).await,
|
||||||
Err(e) => e
|
Err(e) => e
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue