add public/private keys for users

main
anna 1 year ago
parent 888caba1d1
commit 4be3bdda0c
Signed by: fef
GPG Key ID: EC22E476DC2D3D84

1
Cargo.lock generated

@ -1569,6 +1569,7 @@ dependencies = [
"locspan",
"log",
"mime",
"openssl",
"pretty_env_logger",
"rdf-types",
"reqwest",

@ -19,6 +19,7 @@ jsonwebtoken = { version = "8", default-features = false }
locspan = "0.7"
log = "0.4"
mime = "0.3"
openssl = "0.10"
pretty_env_logger = "0.4"
rdf-types = "0.12"
reqwest = { version = "0.11", features = [ "rustls" ] }

@ -4,6 +4,7 @@ CREATE TABLE accounts (
name VARCHAR NOT NULL,
domain VARCHAR NOT NULL,
display_name VARCHAR DEFAULT NULL,
public_key bytea DEFAULT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now(),
updated_at TIMESTAMP NOT NULL DEFAULT now()
);

@ -5,7 +5,8 @@ CREATE TABLE users (
password VARCHAR NOT NULL,
reason VARCHAR DEFAULT NULL,
activated BOOLEAN NOT NULL DEFAULT FALSE,
locale VARCHAR NOT NULL
locale VARCHAR NOT NULL,
private_key bytea NOT NULL
);
CREATE UNIQUE INDEX index_users_on_email ON users (email);

@ -23,6 +23,7 @@ pub enum Error {
MalformedHeader(header::ToStrError),
NotFound,
Reqwest(reqwest::Error),
OpenSSL(openssl::error::ErrorStack),
}
impl ResponseError for Error {
@ -59,6 +60,7 @@ impl fmt::Display for Error {
Error::MalformedApub(msg) => write!(f, "Malformed ActivityPub: {msg}"),
Error::MalformedHeader(to_str_error) => to_str_error.fmt(f),
Error::Reqwest(reqwest_error) => reqwest_error.fmt(f),
Error::OpenSSL(_) => write!(f, "OpenSSL failed for some reason"),
}
}
}
@ -102,6 +104,12 @@ impl From<reqwest::Error> for Error {
}
}
impl From<openssl::error::ErrorStack> for Error {
fn from(e: openssl::error::ErrorStack) -> Error {
Error::OpenSSL(e)
}
}
impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where

@ -22,14 +22,15 @@ impl PgAccountDataSource {
pub async fn create(&self, new: NewAccount) -> Result<Account> {
let account: Account = sqlx::query_as(
"INSERT INTO accounts (iri, name, domain, display_name)
VALUES ($1, $2, $3, $4)
"INSERT INTO accounts (iri, name, domain, display_name, public_key)
VALUES ($1, $2, $3, $4, $5)
RETURNING *",
)
.bind(new.iri)
.bind(new.name)
.bind(new.domain)
.bind(new.display_name)
.bind(new.public_key)
.fetch_one(&self.pool)
.await?;
Ok(account)

@ -39,8 +39,8 @@ impl PgUserDataSource {
pub async fn create(&self, new: NewUser) -> Result<User> {
let user: User = sqlx::query_as(
"INSERT INTO users (account_id, email, password, reason, locale) \
VALUES ($1, $2, $3, $4, $5) \
"INSERT INTO users (account_id, email, password, reason, locale, private_key) \
VALUES ($1, $2, $3, $4, $5, $6) \
RETURNING *",
)
.bind(new.account_id)
@ -48,6 +48,7 @@ impl PgUserDataSource {
.bind(new.password)
.bind(new.reason)
.bind(new.locale)
.bind(new.private_key)
.fetch_one(&self.pool)
.await?;
Ok(user)

@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use crate::core::*;
use crate::util::keys::PublicKeyDer;
use crate::util::validate::{ResultBuilder, Validate};
pub type AccountId = Id<Account>;
@ -14,6 +15,7 @@ pub struct Account {
pub name: String,
pub domain: String,
pub display_name: Option<String>,
pub public_key: Option<PublicKeyDer>,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
}
@ -23,6 +25,7 @@ pub struct NewAccount {
pub name: String,
pub domain: String,
pub display_name: Option<String>,
pub public_key: Option<PublicKeyDer>,
}
impl From<Account> for AccountId {

@ -3,6 +3,7 @@ use sqlx::FromRow;
use crate::core::*;
use crate::model::AccountId;
use crate::util::keys::PrivateKeyDer;
use crate::util::validate::{ResultBuilder, Validate};
pub type UserId = Id<User>;
@ -16,6 +17,7 @@ pub struct User {
pub reason: Option<String>,
pub locale: String,
pub activated: bool,
pub private_key: PrivateKeyDer,
}
pub struct NewUser {
@ -24,6 +26,7 @@ pub struct NewUser {
pub password: String,
pub reason: Option<String>,
pub locale: String,
pub private_key: PrivateKeyDer,
}
impl From<User> for UserId {

@ -6,7 +6,7 @@ use crate::ent;
use crate::middle::AuthData;
use crate::model::{AccountId, NewAccount, NewUser};
use crate::state::AppState;
use crate::util::password;
use crate::util::keys::generate_keypair;
use crate::util::validate::{ResultBuilder, Validate};
#[derive(Deserialize)]
@ -23,6 +23,8 @@ struct SignupData {
async fn signup(data: web::Form<SignupData>, state: AppState) -> Result<HttpResponse> {
let data: Sane<SignupData> = Insane::from(data.into_inner()).try_into()?;
let data = data.inner();
let (pubkey, privkey) = generate_keypair()?;
let account = state
.repo
.accounts
@ -31,6 +33,7 @@ async fn signup(data: web::Form<SignupData>, state: AppState) -> Result<HttpResp
name: data.username,
domain: "localhost".into(),
display_name: None,
public_key: Some(pubkey),
}))
.await?;
state
@ -42,6 +45,7 @@ async fn signup(data: web::Form<SignupData>, state: AppState) -> Result<HttpResp
password: password::hash(&data.password),
locale: data.locale,
reason: data.reason,
private_key: privkey,
}))
.await?;
Ok(HttpResponse::Ok().finish())

@ -0,0 +1,20 @@
use openssl::pkey::{Private, Public};
use openssl::rsa::Rsa;
use serde::{Deserialize, Serialize};
use crate::core::*;
#[derive(sqlx::Type, Clone, Serialize, Deserialize)]
#[sqlx(transparent)]
pub struct PublicKeyDer(Vec<u8>);
#[derive(sqlx::Type, Clone, Serialize, Deserialize)]
#[sqlx(transparent)]
pub struct PrivateKeyDer(Vec<u8>);
pub fn generate_keypair() -> Result<(PublicKeyDer, PrivateKeyDer)> {
let private = Rsa::generate(4096)?;
let public_key = PublicKeyDer(private.public_key_to_der()?);
let private_key = PrivateKeyDer(private.private_key_to_der()?);
Ok((public_key, private_key))
}

@ -1,5 +1,6 @@
pub mod bear;
pub mod http;
pub mod keys;
pub mod password;
pub mod token;
pub mod validate;

Loading…
Cancel
Save