mirror of
https://github.com/aljazceru/pubky-core.git
synced 2025-12-31 21:04:34 +01:00
feat(homeserver): add Users table
This commit is contained in:
70
Cargo.lock
generated
70
Cargo.lock
generated
@@ -55,6 +55,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
@@ -219,6 +228,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
@@ -264,6 +279,12 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.11"
|
||||
@@ -406,6 +427,12 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.9"
|
||||
@@ -567,6 +594,29 @@ version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"hash32",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"spin",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heed"
|
||||
version = "0.20.3"
|
||||
@@ -1043,6 +1093,18 @@ dependencies = [
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8"
|
||||
dependencies = [
|
||||
"cobs",
|
||||
"embedded-io",
|
||||
"heapless",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -1095,7 +1157,9 @@ dependencies = [
|
||||
"dirs-next",
|
||||
"heed",
|
||||
"pkarr",
|
||||
"postcard",
|
||||
"pubky-common",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
@@ -1472,6 +1536,12 @@ dependencies = [
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
|
||||
@@ -10,7 +10,9 @@ bytes = "1.6.1"
|
||||
dirs-next = "2.0.0"
|
||||
heed = "0.20.3"
|
||||
pkarr = { version = "2.1.0", features = ["async"] }
|
||||
postcard = { version = "1.0.8", features = ["alloc"] }
|
||||
pubky-common = { version = "0.1.0", path = "../pubky-common" }
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
tokio = { version = "1.37.0", features = ["full"] }
|
||||
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
|
||||
tracing = "0.1.40"
|
||||
|
||||
@@ -1,19 +1,38 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use heed::{Env, EnvOpenOptions};
|
||||
use heed::{types::Str, Database, Env, EnvOpenOptions, RwTxn};
|
||||
|
||||
mod migrations;
|
||||
pub mod tables;
|
||||
|
||||
use migrations::TABLES_COUNT;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DB {
|
||||
env: Env,
|
||||
pub(crate) env: Env,
|
||||
}
|
||||
|
||||
impl DB {
|
||||
pub fn open(storage: &Path) -> anyhow::Result<Self> {
|
||||
fs::create_dir_all(storage).unwrap();
|
||||
|
||||
let env = unsafe { EnvOpenOptions::new().open(storage) }?;
|
||||
let env = unsafe { EnvOpenOptions::new().max_dbs(TABLES_COUNT).open(storage) }?;
|
||||
|
||||
Ok(DB { env })
|
||||
let db = DB { env };
|
||||
|
||||
db.run_migrations();
|
||||
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
fn run_migrations(&self) -> anyhow::Result<()> {
|
||||
let mut wtxn = self.env.write_txn()?;
|
||||
|
||||
migrations::create_users_table(&self.env, &mut wtxn);
|
||||
|
||||
wtxn.commit()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
11
pubky-homeserver/src/database/migrations.rs
Normal file
11
pubky-homeserver/src/database/migrations.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use heed::{types::Str, Database, Env, RwTxn};
|
||||
|
||||
use super::tables;
|
||||
|
||||
pub const TABLES_COUNT: u32 = 1;
|
||||
|
||||
pub fn create_users_table(env: &Env, wtxn: &mut RwTxn) -> anyhow::Result<()> {
|
||||
let _: tables::users::UsersTable = env.create_database(wtxn, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
1
pubky-homeserver/src/database/tables.rs
Normal file
1
pubky-homeserver/src/database/tables.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod users;
|
||||
59
pubky-homeserver/src/database/tables/users.rs
Normal file
59
pubky-homeserver/src/database/tables/users.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use std::{borrow::Cow, time::SystemTime};
|
||||
|
||||
use postcard::{from_bytes, to_allocvec};
|
||||
use pubky_common::timestamp::Timestamp;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use heed::{types::Str, BoxedError, BytesDecode, BytesEncode, Database};
|
||||
use pkarr::PublicKey;
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// PublicKey => User.
|
||||
pub type UsersTable = Database<PublicKeyCodec, User>;
|
||||
|
||||
pub const USERS_TABLE: &str = "users";
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub struct User {
|
||||
pub created_at: u64,
|
||||
}
|
||||
|
||||
impl<'a> BytesEncode<'a> for User {
|
||||
type EItem = Self;
|
||||
|
||||
fn bytes_encode(user: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
|
||||
let vec = to_allocvec(user).unwrap();
|
||||
|
||||
Ok(Cow::Owned(vec))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BytesDecode<'a> for User {
|
||||
type DItem = Self;
|
||||
|
||||
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
|
||||
let user: User = from_bytes(bytes).unwrap();
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PublicKeyCodec {}
|
||||
|
||||
impl<'a> BytesEncode<'a> for PublicKeyCodec {
|
||||
type EItem = PublicKey;
|
||||
|
||||
fn bytes_encode(pubky: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
|
||||
Ok(Cow::Borrowed(pubky.as_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> BytesDecode<'a> for PublicKeyCodec {
|
||||
type DItem = PublicKey;
|
||||
|
||||
fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
|
||||
Ok(PublicKey::try_from(bytes)?)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
};
|
||||
use pubky_common::auth::AuthnSignatureError;
|
||||
use tracing::debug;
|
||||
|
||||
pub type Result<T, E = Error> = core::result::Result<T, E>;
|
||||
|
||||
@@ -52,39 +53,47 @@ impl IntoResponse for Error {
|
||||
}
|
||||
|
||||
impl From<QueryRejection> for Error {
|
||||
fn from(value: QueryRejection) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(value))
|
||||
fn from(error: QueryRejection) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExtensionRejection> for Error {
|
||||
fn from(value: ExtensionRejection) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(value))
|
||||
fn from(error: ExtensionRejection) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PathRejection> for Error {
|
||||
fn from(value: PathRejection) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(value))
|
||||
fn from(error: PathRejection) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Self::new(StatusCode::INTERNAL_SERVER_ERROR, Some(value))
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
Self::new(StatusCode::INTERNAL_SERVER_ERROR, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
// === Pubky specific errors ===
|
||||
|
||||
impl From<AuthnSignatureError> for Error {
|
||||
fn from(value: AuthnSignatureError) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(value))
|
||||
fn from(error: AuthnSignatureError) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pkarr::Error> for Error {
|
||||
fn from(value: pkarr::Error) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(value))
|
||||
fn from(error: pkarr::Error) -> Self {
|
||||
Self::new(StatusCode::BAD_REQUEST, Some(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<heed::Error> for Error {
|
||||
fn from(error: heed::Error) -> Self {
|
||||
debug!(?error);
|
||||
|
||||
Self::with_status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
use axum::{extract::State, response::IntoResponse};
|
||||
use bytes::Bytes;
|
||||
|
||||
use crate::{error::Result, extractors::Pubky, server::AppState};
|
||||
use pubky_common::timestamp::Timestamp;
|
||||
|
||||
use crate::{
|
||||
database::tables::users::{User, UsersTable, USERS_TABLE},
|
||||
error::Result,
|
||||
extractors::Pubky,
|
||||
server::AppState,
|
||||
};
|
||||
|
||||
pub async fn signup(
|
||||
State(state): State<AppState>,
|
||||
@@ -10,7 +17,16 @@ pub async fn signup(
|
||||
) -> Result<impl IntoResponse> {
|
||||
state.verifier.verify(&body, pubky.public_key())?;
|
||||
|
||||
// TODO: store account in database.
|
||||
let mut wtxn = state.db.env.write_txn()?;
|
||||
let users: UsersTable = state.db.env.create_database(&mut wtxn, Some(USERS_TABLE))?;
|
||||
|
||||
users.put(
|
||||
&mut wtxn,
|
||||
pubky.public_key(),
|
||||
&User {
|
||||
created_at: Timestamp::now().into_inner(),
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user