Merge pull request #1936 from LemmyNet/required_public_key

Making public key required. Fixes #1934
This commit is contained in:
Nutomic 2021-11-22 15:37:05 +00:00 committed by GitHub
commit 76c4378011
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 44 additions and 36 deletions

View file

@ -191,6 +191,7 @@ impl Perform for SaveUserSettings {
let default_listing_type = data.default_listing_type; let default_listing_type = data.default_listing_type;
let default_sort_type = data.default_sort_type; let default_sort_type = data.default_sort_type;
let password_encrypted = local_user_view.local_user.password_encrypted; let password_encrypted = local_user_view.local_user.password_encrypted;
let public_key = local_user_view.person.public_key;
let person_form = PersonForm { let person_form = PersonForm {
name: local_user_view.person.name, name: local_user_view.person.name,
@ -207,7 +208,7 @@ impl Perform for SaveUserSettings {
local: None, local: None,
admin: None, admin: None,
private_key: None, private_key: None,
public_key: None, public_key,
last_refreshed_at: None, last_refreshed_at: None,
shared_inbox_url: None, shared_inbox_url: None,
matrix_user_id, matrix_user_id,

View file

@ -93,8 +93,8 @@ impl PerformCrud for CreateCommunity {
banner, banner,
nsfw: data.nsfw, nsfw: data.nsfw,
actor_id: Some(community_actor_id.to_owned()), actor_id: Some(community_actor_id.to_owned()),
private_key: Some(keypair.private_key), private_key: Some(Some(keypair.private_key)),
public_key: Some(keypair.public_key), public_key: keypair.public_key,
followers_url: Some(generate_followers_url(&community_actor_id)?), followers_url: Some(generate_followers_url(&community_actor_id)?),
inbox_url: Some(generate_inbox_url(&community_actor_id)?), inbox_url: Some(generate_inbox_url(&community_actor_id)?),
shared_inbox_url: Some(Some(generate_shared_inbox_url(&community_actor_id)?)), shared_inbox_url: Some(Some(generate_shared_inbox_url(&community_actor_id)?)),

View file

@ -57,6 +57,7 @@ impl PerformCrud for EditCommunity {
name: read_community.name, name: read_community.name,
title: data.title.to_owned().unwrap_or(read_community.title), title: data.title.to_owned().unwrap_or(read_community.title),
description: data.description.to_owned(), description: data.description.to_owned(),
public_key: read_community.public_key,
icon, icon,
banner, banner,
nsfw: data.nsfw, nsfw: data.nsfw,

View file

@ -109,7 +109,7 @@ impl PerformCrud for Register {
name: data.username.to_owned(), name: data.username.to_owned(),
actor_id: Some(actor_id.clone()), actor_id: Some(actor_id.clone()),
private_key: Some(Some(actor_keypair.private_key)), private_key: Some(Some(actor_keypair.private_key)),
public_key: Some(Some(actor_keypair.public_key)), public_key: actor_keypair.public_key,
inbox_url: Some(generate_inbox_url(&actor_id)?), inbox_url: Some(generate_inbox_url(&actor_id)?),
shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)), shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)),
admin: Some(no_admins), admin: Some(no_admins),
@ -189,8 +189,8 @@ impl PerformCrud for Register {
title: "The Default Community".to_string(), title: "The Default Community".to_string(),
description: Some("The Default Community".to_string()), description: Some("The Default Community".to_string()),
actor_id: Some(actor_id.to_owned()), actor_id: Some(actor_id.to_owned()),
private_key: Some(main_community_keypair.private_key), private_key: Some(Some(main_community_keypair.private_key)),
public_key: Some(main_community_keypair.public_key), public_key: main_community_keypair.public_key,
followers_url: Some(generate_followers_url(&actor_id)?), followers_url: Some(generate_followers_url(&actor_id)?),
inbox_url: Some(generate_inbox_url(&actor_id)?), inbox_url: Some(generate_inbox_url(&actor_id)?),
shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)), shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)),

View file

@ -103,7 +103,7 @@ impl ActorType for UserOrCommunity {
} }
} }
fn public_key(&self) -> Option<String> { fn public_key(&self) -> String {
match self { match self {
UserOrCommunity::User(p) => p.public_key(), UserOrCommunity::User(p) => p.public_key(),
UserOrCommunity::Community(p) => p.public_key(), UserOrCommunity::Community(p) => p.public_key(),

View file

@ -95,7 +95,7 @@ where
let actor = ObjectId::<UserOrCommunity>::new(activity_data.actor) let actor = ObjectId::<UserOrCommunity>::new(activity_data.actor)
.dereference(context, request_counter) .dereference(context, request_counter)
.await?; .await?;
verify_signature(&request, &actor.public_key().context(location_info!())?)?; verify_signature(&request, &actor.public_key())?;
// Do nothing if we received the same activity before // Do nothing if we received the same activity before
if is_activity_already_known(context.pool(), &activity_data.id).await? { if is_activity_already_known(context.pool(), &activity_data.id).await? {

View file

@ -163,7 +163,7 @@ impl ActorType for ApubCommunity {
fn actor_id(&self) -> Url { fn actor_id(&self) -> Url {
self.actor_id.to_owned().into() self.actor_id.to_owned().into()
} }
fn public_key(&self) -> Option<String> { fn public_key(&self) -> String {
self.public_key.to_owned() self.public_key.to_owned()
} }
fn private_key(&self) -> Option<String> { fn private_key(&self) -> Option<String> {
@ -244,7 +244,6 @@ pub(crate) mod tests {
let community = parse_lemmy_community(&context).await; let community = parse_lemmy_community(&context).await;
assert_eq!(community.title, "Ten Forward"); assert_eq!(community.title, "Ten Forward");
assert!(community.public_key.is_some());
assert!(!community.local); assert!(!community.local);
assert_eq!(community.description.as_ref().unwrap().len(), 132); assert_eq!(community.description.as_ref().unwrap().len(), 132);

View file

@ -158,7 +158,7 @@ impl ApubObject for ApubPerson {
admin: Some(false), admin: Some(false),
bot_account: Some(person.kind == UserTypes::Service), bot_account: Some(person.kind == UserTypes::Service),
private_key: None, private_key: None,
public_key: Some(Some(person.public_key.public_key_pem)), public_key: person.public_key.public_key_pem,
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
inbox_url: Some(person.inbox.into()), inbox_url: Some(person.inbox.into()),
shared_inbox_url: Some(person.endpoints.shared_inbox.map(|s| s.into())), shared_inbox_url: Some(person.endpoints.shared_inbox.map(|s| s.into())),
@ -177,7 +177,7 @@ impl ActorType for ApubPerson {
self.actor_id.to_owned().into() self.actor_id.to_owned().into()
} }
fn public_key(&self) -> Option<String> { fn public_key(&self) -> String {
self.public_key.to_owned() self.public_key.to_owned()
} }
@ -222,7 +222,6 @@ pub(crate) mod tests {
let person = parse_lemmy_person(&context).await; let person = parse_lemmy_person(&context).await;
assert_eq!(person.display_name, Some("Jean-Luc Picard".to_string())); assert_eq!(person.display_name, Some("Jean-Luc Picard".to_string()));
assert!(person.public_key.is_some());
assert!(!person.local); assert!(!person.local);
assert_eq!(person.bio.as_ref().unwrap().len(), 39); assert_eq!(person.bio.as_ref().unwrap().len(), 39);
@ -245,7 +244,6 @@ pub(crate) mod tests {
assert_eq!(person.actor_id, url.into()); assert_eq!(person.actor_id, url.into());
assert_eq!(person.name, "lanodan"); assert_eq!(person.name, "lanodan");
assert!(person.public_key.is_some());
assert!(!person.local); assert!(!person.local);
assert_eq!(request_counter, 0); assert_eq!(request_counter, 0);
assert_eq!(person.bio.as_ref().unwrap().len(), 873); assert_eq!(person.bio.as_ref().unwrap().len(), 873);

View file

@ -81,7 +81,7 @@ impl Group {
actor_id: Some(self.id.into()), actor_id: Some(self.id.into()),
local: Some(false), local: Some(false),
private_key: None, private_key: None,
public_key: Some(self.public_key.public_key_pem), public_key: self.public_key.public_key_pem,
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
icon: Some(self.icon.map(|i| i.url.into())), icon: Some(self.icon.map(|i| i.url.into())),
banner: Some(self.image.map(|i| i.url.into())), banner: Some(self.image.map(|i| i.url.into())),

View file

@ -1,8 +1,7 @@
use crate::{data::Data, signatures::PublicKey}; use crate::{data::Data, signatures::PublicKey};
use activitystreams::chrono::NaiveDateTime; use activitystreams::chrono::NaiveDateTime;
use anyhow::Context;
pub use lemmy_apub_lib_derive::*; pub use lemmy_apub_lib_derive::*;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::LemmyError;
use url::Url; use url::Url;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
@ -71,8 +70,7 @@ pub trait ApubObject {
pub trait ActorType { pub trait ActorType {
fn actor_id(&self) -> Url; fn actor_id(&self) -> Url;
// TODO: this should not be an option (needs db migration in lemmy) fn public_key(&self) -> String;
fn public_key(&self) -> Option<String>;
fn private_key(&self) -> Option<String>; fn private_key(&self) -> Option<String>;
fn inbox_url(&self) -> Url; fn inbox_url(&self) -> Url;
@ -87,7 +85,7 @@ pub trait ActorType {
Ok(PublicKey { Ok(PublicKey {
id: format!("{}#main-key", self.actor_id()), id: format!("{}#main-key", self.actor_id()),
owner: Box::new(self.actor_id()), owner: Box::new(self.actor_id()),
public_key_pem: self.public_key().context(location_info!())?, public_key_pem: self.public_key(),
}) })
} }
} }

View file

@ -319,6 +319,7 @@ mod tests {
let new_community = CommunityForm { let new_community = CommunityForm {
name: "TIL".into(), name: "TIL".into(),
title: "nada".to_owned(), title: "nada".to_owned(),
public_key: "nada".to_owned(),
..CommunityForm::default() ..CommunityForm::default()
}; };
@ -337,7 +338,7 @@ mod tests {
actor_id: inserted_community.actor_id.to_owned(), actor_id: inserted_community.actor_id.to_owned(),
local: true, local: true,
private_key: None, private_key: None,
public_key: None, public_key: "nada".to_owned(),
last_refreshed_at: inserted_community.published, last_refreshed_at: inserted_community.published,
icon: None, icon: None,
banner: None, banner: None,

View file

@ -270,6 +270,7 @@ mod tests {
let new_person = PersonForm { let new_person = PersonForm {
name: "holly".into(), name: "holly".into(),
public_key: "nada".to_owned(),
..PersonForm::default() ..PersonForm::default()
}; };
@ -291,7 +292,7 @@ mod tests {
bot_account: false, bot_account: false,
admin: false, admin: false,
private_key: None, private_key: None,
public_key: None, public_key: "nada".to_owned(),
last_refreshed_at: inserted_person.published, last_refreshed_at: inserted_person.published,
inbox_url: inserted_person.inbox_url.to_owned(), inbox_url: inserted_person.inbox_url.to_owned(),
shared_inbox_url: None, shared_inbox_url: None,

View file

@ -86,7 +86,7 @@ table! {
actor_id -> Varchar, actor_id -> Varchar,
local -> Bool, local -> Bool,
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Text,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
icon -> Nullable<Varchar>, icon -> Nullable<Varchar>,
banner -> Nullable<Varchar>, banner -> Nullable<Varchar>,
@ -293,7 +293,7 @@ table! {
bio -> Nullable<Text>, bio -> Nullable<Text>,
local -> Bool, local -> Bool,
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Text,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
banner -> Nullable<Varchar>, banner -> Nullable<Varchar>,
deleted -> Bool, deleted -> Bool,
@ -514,7 +514,7 @@ table! {
bio -> Nullable<Text>, bio -> Nullable<Text>,
local -> Bool, local -> Bool,
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Text,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
banner -> Nullable<Varchar>, banner -> Nullable<Varchar>,
deleted -> Bool, deleted -> Bool,
@ -539,7 +539,7 @@ table! {
bio -> Nullable<Text>, bio -> Nullable<Text>,
local -> Bool, local -> Bool,
private_key -> Nullable<Text>, private_key -> Nullable<Text>,
public_key -> Nullable<Text>, public_key -> Text,
last_refreshed_at -> Timestamp, last_refreshed_at -> Timestamp,
banner -> Nullable<Varchar>, banner -> Nullable<Varchar>,
deleted -> Bool, deleted -> Bool,

View file

@ -19,7 +19,7 @@ pub struct Community {
pub actor_id: DbUrl, pub actor_id: DbUrl,
pub local: bool, pub local: bool,
pub private_key: Option<String>, pub private_key: Option<String>,
pub public_key: Option<String>, pub public_key: String,
pub last_refreshed_at: chrono::NaiveDateTime, pub last_refreshed_at: chrono::NaiveDateTime,
pub icon: Option<DbUrl>, pub icon: Option<DbUrl>,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
@ -60,8 +60,8 @@ pub struct CommunityForm {
pub nsfw: Option<bool>, pub nsfw: Option<bool>,
pub actor_id: Option<DbUrl>, pub actor_id: Option<DbUrl>,
pub local: Option<bool>, pub local: Option<bool>,
pub private_key: Option<String>, pub private_key: Option<Option<String>>,
pub public_key: Option<String>, pub public_key: String,
pub last_refreshed_at: Option<chrono::NaiveDateTime>, pub last_refreshed_at: Option<chrono::NaiveDateTime>,
pub icon: Option<Option<DbUrl>>, pub icon: Option<Option<DbUrl>>,
pub banner: Option<Option<DbUrl>>, pub banner: Option<Option<DbUrl>>,

View file

@ -18,7 +18,7 @@ pub struct Person {
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
pub private_key: Option<String>, pub private_key: Option<String>,
pub public_key: Option<String>, pub public_key: String,
pub last_refreshed_at: chrono::NaiveDateTime, pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
@ -66,7 +66,7 @@ pub struct PersonAlias1 {
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
pub private_key: Option<String>, pub private_key: Option<String>,
pub public_key: Option<String>, pub public_key: String,
pub last_refreshed_at: chrono::NaiveDateTime, pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
@ -113,7 +113,7 @@ pub struct PersonAlias2 {
pub bio: Option<String>, pub bio: Option<String>,
pub local: bool, pub local: bool,
pub private_key: Option<String>, pub private_key: Option<String>,
pub public_key: Option<String>, pub public_key: String,
pub last_refreshed_at: chrono::NaiveDateTime, pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<DbUrl>, pub banner: Option<DbUrl>,
pub deleted: bool, pub deleted: bool,
@ -159,7 +159,7 @@ pub struct PersonForm {
pub bio: Option<Option<String>>, pub bio: Option<Option<String>>,
pub local: Option<bool>, pub local: Option<bool>,
pub private_key: Option<Option<String>>, pub private_key: Option<Option<String>>,
pub public_key: Option<Option<String>>, pub public_key: String,
pub last_refreshed_at: Option<chrono::NaiveDateTime>, pub last_refreshed_at: Option<chrono::NaiveDateTime>,
pub banner: Option<Option<DbUrl>>, pub banner: Option<Option<DbUrl>>,
pub deleted: Option<bool>, pub deleted: Option<bool>,

View file

@ -0,0 +1,2 @@
alter table community alter column public_key drop not null;
alter table person alter column public_key drop not null;

View file

@ -0,0 +1,7 @@
-- Delete the empty public keys
delete from community where public_key is null;
delete from person where public_key is null;
-- Make it required
alter table community alter column public_key set not null;
alter table person alter column public_key set not null;

View file

@ -64,7 +64,7 @@ fn user_updates_2020_04_02(
protocol_and_hostname, protocol_and_hostname,
)?), )?),
private_key: Some(Some(keypair.private_key)), private_key: Some(Some(keypair.private_key)),
public_key: Some(Some(keypair.public_key)), public_key: keypair.public_key,
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
..PersonForm::default() ..PersonForm::default()
}; };
@ -109,8 +109,8 @@ fn community_updates_2020_04_02(
updated: None, updated: None,
actor_id: Some(community_actor_id.to_owned()), actor_id: Some(community_actor_id.to_owned()),
local: Some(ccommunity.local), local: Some(ccommunity.local),
private_key: Some(keypair.private_key), private_key: Some(Some(keypair.private_key)),
public_key: Some(keypair.public_key), public_key: keypair.public_key,
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
published: None, published: None,
icon: Some(ccommunity.icon.to_owned()), icon: Some(ccommunity.icon.to_owned()),