mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-22 20:31:19 +00:00
Mark database fields as sensitive so they dont show up in logs (#4720)
* Mark database fields as sensitive so they dont show up in logs * add file * fix test * Update crates/apub/src/objects/person.rs Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> * Update crates/apub/src/objects/community.rs Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> * Update crates/apub/src/objects/instance.rs Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> --------- Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
parent
1a4aa3eaba
commit
99aac07714
20 changed files with 114 additions and 165 deletions
|
@ -1,11 +1,7 @@
|
||||||
use crate::{build_totp_2fa, generate_totp_2fa_secret};
|
use crate::{build_totp_2fa, generate_totp_2fa_secret};
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
use actix_web::web::Json;
|
use actix_web::web::Json;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{context::LemmyContext, person::GenerateTotpSecretResponse};
|
||||||
context::LemmyContext,
|
|
||||||
person::GenerateTotpSecretResponse,
|
|
||||||
sensitive::Sensitive,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::local_user::{LocalUser, LocalUserUpdateForm};
|
use lemmy_db_schema::source::local_user::{LocalUser, LocalUserUpdateForm};
|
||||||
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||||
|
@ -41,6 +37,6 @@ pub async fn generate_totp_secret(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(Json(GenerateTotpSecretResponse {
|
Ok(Json(GenerateTotpSecretResponse {
|
||||||
totp_secret_url: Sensitive::new(secret_url),
|
totp_secret_url: secret_url.into(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ use lemmy_utils::{
|
||||||
error::{LemmyErrorType, LemmyResult},
|
error::{LemmyErrorType, LemmyResult},
|
||||||
utils::validation::{is_valid_bio_field, is_valid_display_name, is_valid_matrix_id},
|
utils::validation::{is_valid_bio_field, is_valid_display_name, is_valid_matrix_id},
|
||||||
};
|
};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[tracing::instrument(skip(context))]
|
#[tracing::instrument(skip(context))]
|
||||||
pub async fn save_user_settings(
|
pub async fn save_user_settings(
|
||||||
|
@ -57,7 +58,7 @@ pub async fn save_user_settings(
|
||||||
if let Some(Some(email)) = &email {
|
if let Some(Some(email)) = &email {
|
||||||
let previous_email = local_user_view.local_user.email.clone().unwrap_or_default();
|
let previous_email = local_user_view.local_user.email.clone().unwrap_or_default();
|
||||||
// if email was changed, check that it is not taken and send verification mail
|
// if email was changed, check that it is not taken and send verification mail
|
||||||
if &previous_email != email {
|
if previous_email.deref() != email {
|
||||||
if LocalUser::is_email_taken(&mut context.pool(), email).await? {
|
if LocalUser::is_email_taken(&mut context.pool(), email).await? {
|
||||||
return Err(LemmyErrorType::EmailAlreadyExists)?;
|
return Err(LemmyErrorType::EmailAlreadyExists)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::{context::LemmyContext, sensitive::Sensitive};
|
use crate::context::LemmyContext;
|
||||||
use actix_web::{http::header::USER_AGENT, HttpRequest};
|
use actix_web::{http::header::USER_AGENT, HttpRequest};
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
|
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::LocalUserId,
|
newtypes::LocalUserId,
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::login_token::{LoginToken, LoginTokenCreateForm},
|
source::login_token::{LoginToken, LoginTokenCreateForm},
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||||
|
@ -40,7 +41,7 @@ impl Claims {
|
||||||
user_id: LocalUserId,
|
user_id: LocalUserId,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> LemmyResult<Sensitive<String>> {
|
) -> LemmyResult<SensitiveString> {
|
||||||
let hostname = context.settings().hostname.clone();
|
let hostname = context.settings().hostname.clone();
|
||||||
let my_claims = Claims {
|
let my_claims = Claims {
|
||||||
sub: user_id.0.to_string(),
|
sub: user_id.0.to_string(),
|
||||||
|
@ -50,7 +51,7 @@ impl Claims {
|
||||||
|
|
||||||
let secret = &context.secret().jwt_secret;
|
let secret = &context.secret().jwt_secret;
|
||||||
let key = EncodingKey::from_secret(secret.as_ref());
|
let key = EncodingKey::from_secret(secret.as_ref());
|
||||||
let token = encode(&Header::default(), &my_claims, &key)?;
|
let token: SensitiveString = encode(&Header::default(), &my_claims, &key)?.into();
|
||||||
let ip = req
|
let ip = req
|
||||||
.connection_info()
|
.connection_info()
|
||||||
.realip_remote_addr()
|
.realip_remote_addr()
|
||||||
|
@ -67,7 +68,7 @@ impl Claims {
|
||||||
user_agent,
|
user_agent,
|
||||||
};
|
};
|
||||||
LoginToken::create(&mut context.pool(), form).await?;
|
LoginToken::create(&mut context.pool(), form).await?;
|
||||||
Ok(Sensitive::new(token))
|
Ok(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl LemmyContext {
|
||||||
let client = ClientBuilder::new(client).build();
|
let client = ClientBuilder::new(client).build();
|
||||||
let secret = Secret {
|
let secret = Secret {
|
||||||
id: 0,
|
id: 0,
|
||||||
jwt_secret: String::new(),
|
jwt_secret: String::new().into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let rate_limit_cell = RateLimitCell::with_test_config();
|
let rate_limit_cell = RateLimitCell::with_test_config();
|
||||||
|
|
|
@ -14,7 +14,6 @@ pub mod private_message;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod send_activity;
|
pub mod send_activity;
|
||||||
pub mod sensitive;
|
|
||||||
pub mod site;
|
pub mod site;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::sensitive::Sensitive;
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::site::Site,
|
source::site::Site,
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
|
@ -25,8 +25,8 @@ use ts_rs::TS;
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Logging into lemmy.
|
/// Logging into lemmy.
|
||||||
pub struct Login {
|
pub struct Login {
|
||||||
pub username_or_email: Sensitive<String>,
|
pub username_or_email: SensitiveString,
|
||||||
pub password: Sensitive<String>,
|
pub password: SensitiveString,
|
||||||
/// May be required, if totp is enabled for their account.
|
/// May be required, if totp is enabled for their account.
|
||||||
pub totp_2fa_token: Option<String>,
|
pub totp_2fa_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,11 @@ pub struct Login {
|
||||||
/// Register / Sign up to lemmy.
|
/// Register / Sign up to lemmy.
|
||||||
pub struct Register {
|
pub struct Register {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub password: Sensitive<String>,
|
pub password: SensitiveString,
|
||||||
pub password_verify: Sensitive<String>,
|
pub password_verify: SensitiveString,
|
||||||
pub show_nsfw: Option<bool>,
|
pub show_nsfw: Option<bool>,
|
||||||
/// email is mandatory if email verification is enabled on the server
|
/// email is mandatory if email verification is enabled on the server
|
||||||
pub email: Option<Sensitive<String>>,
|
pub email: Option<SensitiveString>,
|
||||||
/// The UUID of the captcha item.
|
/// The UUID of the captcha item.
|
||||||
pub captcha_uuid: Option<String>,
|
pub captcha_uuid: Option<String>,
|
||||||
/// Your captcha answer.
|
/// Your captcha answer.
|
||||||
|
@ -99,7 +99,7 @@ pub struct SaveUserSettings {
|
||||||
/// Your display name, which can contain strange characters, and does not need to be unique.
|
/// Your display name, which can contain strange characters, and does not need to be unique.
|
||||||
pub display_name: Option<String>,
|
pub display_name: Option<String>,
|
||||||
/// Your email.
|
/// Your email.
|
||||||
pub email: Option<Sensitive<String>>,
|
pub email: Option<SensitiveString>,
|
||||||
/// Your bio / info, in markdown.
|
/// Your bio / info, in markdown.
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
/// Your matrix user id. Ex: @my_user:matrix.org
|
/// Your matrix user id. Ex: @my_user:matrix.org
|
||||||
|
@ -140,9 +140,9 @@ pub struct SaveUserSettings {
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Changes your account password.
|
/// Changes your account password.
|
||||||
pub struct ChangePassword {
|
pub struct ChangePassword {
|
||||||
pub new_password: Sensitive<String>,
|
pub new_password: SensitiveString,
|
||||||
pub new_password_verify: Sensitive<String>,
|
pub new_password_verify: SensitiveString,
|
||||||
pub old_password: Sensitive<String>,
|
pub old_password: SensitiveString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -152,7 +152,7 @@ pub struct ChangePassword {
|
||||||
/// A response for your login.
|
/// A response for your login.
|
||||||
pub struct LoginResponse {
|
pub struct LoginResponse {
|
||||||
/// This is None in response to `Register` if email verification is enabled, or the server requires registration applications.
|
/// This is None in response to `Register` if email verification is enabled, or the server requires registration applications.
|
||||||
pub jwt: Option<Sensitive<String>>,
|
pub jwt: Option<SensitiveString>,
|
||||||
/// If registration applications are required, this will return true for a signup response.
|
/// If registration applications are required, this will return true for a signup response.
|
||||||
pub registration_created: bool,
|
pub registration_created: bool,
|
||||||
/// If email verifications are required, this will return true for a signup response.
|
/// If email verifications are required, this will return true for a signup response.
|
||||||
|
@ -340,7 +340,7 @@ pub struct CommentReplyResponse {
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Delete your account.
|
/// Delete your account.
|
||||||
pub struct DeleteAccount {
|
pub struct DeleteAccount {
|
||||||
pub password: Sensitive<String>,
|
pub password: SensitiveString,
|
||||||
pub delete_content: bool,
|
pub delete_content: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ pub struct DeleteAccount {
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Reset your password via email.
|
/// Reset your password via email.
|
||||||
pub struct PasswordReset {
|
pub struct PasswordReset {
|
||||||
pub email: Sensitive<String>,
|
pub email: SensitiveString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
||||||
|
@ -357,9 +357,9 @@ pub struct PasswordReset {
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Change your password after receiving a reset request.
|
/// Change your password after receiving a reset request.
|
||||||
pub struct PasswordChangeAfterReset {
|
pub struct PasswordChangeAfterReset {
|
||||||
pub token: Sensitive<String>,
|
pub token: SensitiveString,
|
||||||
pub password: Sensitive<String>,
|
pub password: SensitiveString,
|
||||||
pub password_verify: Sensitive<String>,
|
pub password_verify: SensitiveString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -405,7 +405,7 @@ pub struct VerifyEmail {
|
||||||
#[cfg_attr(feature = "full", derive(TS))]
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
pub struct GenerateTotpSecretResponse {
|
pub struct GenerateTotpSecretResponse {
|
||||||
pub totp_secret_url: Sensitive<String>,
|
pub totp_secret_url: SensitiveString,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{
|
|
||||||
borrow::Borrow,
|
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
};
|
|
||||||
#[cfg(feature = "full")]
|
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize, Default)]
|
|
||||||
#[serde(transparent)]
|
|
||||||
pub struct Sensitive<T>(T);
|
|
||||||
|
|
||||||
impl<T> Sensitive<T> {
|
|
||||||
pub fn new(item: T) -> Self {
|
|
||||||
Sensitive(item)
|
|
||||||
}
|
|
||||||
pub fn into_inner(self) -> T {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> std::fmt::Debug for Sensitive<T> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("Sensitive").finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsRef<T> for Sensitive<T> {
|
|
||||||
fn as_ref(&self) -> &T {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<str> for Sensitive<String> {
|
|
||||||
fn as_ref(&self) -> &str {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<[u8]> for Sensitive<String> {
|
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
self.0.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<[u8]> for Sensitive<Vec<u8>> {
|
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
self.0.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsMut<T> for Sensitive<T> {
|
|
||||||
fn as_mut(&mut self) -> &mut T {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsMut<str> for Sensitive<String> {
|
|
||||||
fn as_mut(&mut self) -> &mut str {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Sensitive<String> {
|
|
||||||
type Target = str;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for Sensitive<String> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<T> for Sensitive<T> {
|
|
||||||
fn from(t: T) -> Self {
|
|
||||||
Sensitive(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Sensitive<String> {
|
|
||||||
fn from(s: &str) -> Self {
|
|
||||||
Sensitive(s.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Borrow<T> for Sensitive<T> {
|
|
||||||
fn borrow(&self) -> &T {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Borrow<str> for Sensitive<String> {
|
|
||||||
fn borrow(&self) -> &str {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "full")]
|
|
||||||
impl TS for Sensitive<String> {
|
|
||||||
fn name() -> String {
|
|
||||||
"string".to_string()
|
|
||||||
}
|
|
||||||
fn name_with_type_args(_args: Vec<String>) -> String {
|
|
||||||
"string".to_string()
|
|
||||||
}
|
|
||||||
fn dependencies() -> Vec<ts_rs::Dependency> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
fn transparent() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -28,6 +28,7 @@ use lemmy_api_common::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::{
|
source::{
|
||||||
activity::ActorType,
|
activity::ActorType,
|
||||||
actor_language::CommunityLanguage,
|
actor_language::CommunityLanguage,
|
||||||
|
@ -213,7 +214,7 @@ impl Actor for ApubCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn private_key_pem(&self) -> Option<String> {
|
fn private_key_pem(&self) -> Option<String> {
|
||||||
self.private_key.clone()
|
self.private_key.clone().map(SensitiveString::into_inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inbox(&self) -> Url {
|
fn inbox(&self) -> Url {
|
||||||
|
|
|
@ -29,6 +29,7 @@ use lemmy_api_common::{
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::InstanceId,
|
newtypes::InstanceId,
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::{
|
source::{
|
||||||
activity::ActorType,
|
activity::ActorType,
|
||||||
actor_language::SiteLanguage,
|
actor_language::SiteLanguage,
|
||||||
|
@ -187,7 +188,7 @@ impl Actor for ApubSite {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn private_key_pem(&self) -> Option<String> {
|
fn private_key_pem(&self) -> Option<String> {
|
||||||
self.private_key.clone()
|
self.private_key.clone().map(SensitiveString::into_inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inbox(&self) -> Url {
|
fn inbox(&self) -> Url {
|
||||||
|
|
|
@ -30,6 +30,7 @@ use lemmy_api_common::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::{
|
source::{
|
||||||
activity::ActorType,
|
activity::ActorType,
|
||||||
local_site::LocalSite,
|
local_site::LocalSite,
|
||||||
|
@ -200,7 +201,7 @@ impl Actor for ApubPerson {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn private_key_pem(&self) -> Option<String> {
|
fn private_key_pem(&self) -> Option<String> {
|
||||||
self.private_key.clone()
|
self.private_key.clone().map(SensitiveString::into_inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inbox(&self) -> Url {
|
fn inbox(&self) -> Url {
|
||||||
|
|
|
@ -50,7 +50,7 @@ impl PasswordResetRequest {
|
||||||
) -> Result<PasswordResetRequest, Error> {
|
) -> Result<PasswordResetRequest, Error> {
|
||||||
let form = PasswordResetRequestForm {
|
let form = PasswordResetRequestForm {
|
||||||
local_user_id: from_local_user_id,
|
local_user_id: from_local_user_id,
|
||||||
token: token_,
|
token: token_.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::create(pool, &form).await
|
Self::create(pool, &form).await
|
||||||
|
@ -134,7 +134,7 @@ mod tests {
|
||||||
let expected_password_reset_request = PasswordResetRequest {
|
let expected_password_reset_request = PasswordResetRequest {
|
||||||
id: inserted_password_reset_request.id,
|
id: inserted_password_reset_request.id,
|
||||||
local_user_id: inserted_local_user.id,
|
local_user_id: inserted_local_user.id,
|
||||||
token: token.to_string(),
|
token: token.to_string().into(),
|
||||||
published: inserted_password_reset_request.published,
|
published: inserted_password_reset_request.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub mod aggregates;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod impls;
|
pub mod impls;
|
||||||
pub mod newtypes;
|
pub mod newtypes;
|
||||||
|
pub mod sensitive;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[allow(clippy::wildcard_imports)]
|
#[allow(clippy::wildcard_imports)]
|
||||||
|
|
57
crates/db_schema/src/sensitive.rs
Normal file
57
crates/db_schema/src/sensitive.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{fmt::Debug, ops::Deref};
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
use ts_rs::TS;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize, Default)]
|
||||||
|
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||||
|
#[serde(transparent)]
|
||||||
|
pub struct SensitiveString(String);
|
||||||
|
|
||||||
|
impl SensitiveString {
|
||||||
|
pub fn into_inner(self) -> String {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for SensitiveString {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("Sensitive").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8]> for SensitiveString {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for SensitiveString {
|
||||||
|
type Target = str;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for SensitiveString {
|
||||||
|
fn from(t: String) -> Self {
|
||||||
|
SensitiveString(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
impl TS for SensitiveString {
|
||||||
|
fn name() -> String {
|
||||||
|
"string".to_string()
|
||||||
|
}
|
||||||
|
fn name_with_type_args(_args: Vec<String>) -> String {
|
||||||
|
"string".to_string()
|
||||||
|
}
|
||||||
|
fn dependencies() -> Vec<ts_rs::Dependency> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
fn transparent() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
use crate::schema::{community, community_follower, community_moderator, community_person_ban};
|
use crate::schema::{community, community_follower, community_moderator, community_person_ban};
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{CommunityId, DbUrl, InstanceId, PersonId},
|
newtypes::{CommunityId, DbUrl, InstanceId, PersonId},
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::placeholder_apub_url,
|
source::placeholder_apub_url,
|
||||||
CommunityVisibility,
|
CommunityVisibility,
|
||||||
};
|
};
|
||||||
|
@ -39,7 +40,7 @@ pub struct Community {
|
||||||
/// Whether the community is local.
|
/// Whether the community is local.
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<SensitiveString>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
use crate::schema::local_user;
|
use crate::schema::local_user;
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{LocalUserId, PersonId},
|
newtypes::{LocalUserId, PersonId},
|
||||||
|
sensitive::SensitiveString,
|
||||||
ListingType,
|
ListingType,
|
||||||
PostListingMode,
|
PostListingMode,
|
||||||
SortType,
|
SortType,
|
||||||
|
@ -24,8 +25,8 @@ pub struct LocalUser {
|
||||||
/// The person_id for the local user.
|
/// The person_id for the local user.
|
||||||
pub person_id: PersonId,
|
pub person_id: PersonId,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub password_encrypted: String,
|
pub password_encrypted: SensitiveString,
|
||||||
pub email: Option<String>,
|
pub email: Option<SensitiveString>,
|
||||||
/// Whether to show NSFW content.
|
/// Whether to show NSFW content.
|
||||||
pub show_nsfw: bool,
|
pub show_nsfw: bool,
|
||||||
pub theme: String,
|
pub theme: String,
|
||||||
|
@ -47,7 +48,7 @@ pub struct LocalUser {
|
||||||
/// Whether their registration application has been accepted.
|
/// Whether their registration application has been accepted.
|
||||||
pub accepted_application: bool,
|
pub accepted_application: bool,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub totp_2fa_secret: Option<String>,
|
pub totp_2fa_secret: Option<SensitiveString>,
|
||||||
/// Open links in a new tab.
|
/// Open links in a new tab.
|
||||||
pub open_links_in_new_tab: bool,
|
pub open_links_in_new_tab: bool,
|
||||||
pub blur_nsfw: bool,
|
pub blur_nsfw: bool,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::newtypes::LocalUserId;
|
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::login_token;
|
use crate::schema::login_token;
|
||||||
|
use crate::{newtypes::LocalUserId, sensitive::SensitiveString};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
@ -18,7 +18,7 @@ use ts_rs::TS;
|
||||||
pub struct LoginToken {
|
pub struct LoginToken {
|
||||||
/// Jwt token for this login
|
/// Jwt token for this login
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub token: String,
|
pub token: SensitiveString,
|
||||||
pub user_id: LocalUserId,
|
pub user_id: LocalUserId,
|
||||||
/// Time of login
|
/// Time of login
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
|
@ -31,7 +31,7 @@ pub struct LoginToken {
|
||||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = login_token))]
|
#[cfg_attr(feature = "full", diesel(table_name = login_token))]
|
||||||
pub struct LoginTokenCreateForm {
|
pub struct LoginTokenCreateForm {
|
||||||
pub token: String,
|
pub token: SensitiveString,
|
||||||
pub user_id: LocalUserId,
|
pub user_id: LocalUserId,
|
||||||
pub ip: Option<String>,
|
pub ip: Option<String>,
|
||||||
pub user_agent: Option<String>,
|
pub user_agent: Option<String>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::newtypes::LocalUserId;
|
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::password_reset_request;
|
use crate::schema::password_reset_request;
|
||||||
|
use crate::{newtypes::LocalUserId, sensitive::SensitiveString};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
|
@ -9,7 +9,7 @@ use chrono::{DateTime, Utc};
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
pub struct PasswordResetRequest {
|
pub struct PasswordResetRequest {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub token: String,
|
pub token: SensitiveString,
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
pub local_user_id: LocalUserId,
|
pub local_user_id: LocalUserId,
|
||||||
}
|
}
|
||||||
|
@ -18,5 +18,5 @@ pub struct PasswordResetRequest {
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = password_reset_request))]
|
#[cfg_attr(feature = "full", diesel(table_name = password_reset_request))]
|
||||||
pub struct PasswordResetRequestForm {
|
pub struct PasswordResetRequestForm {
|
||||||
pub local_user_id: LocalUserId,
|
pub local_user_id: LocalUserId,
|
||||||
pub token: String,
|
pub token: SensitiveString,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
use crate::schema::{person, person_follower};
|
use crate::schema::{person, person_follower};
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{DbUrl, InstanceId, PersonId},
|
newtypes::{DbUrl, InstanceId, PersonId},
|
||||||
|
sensitive::SensitiveString,
|
||||||
source::placeholder_apub_url,
|
source::placeholder_apub_url,
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
@ -36,7 +37,7 @@ pub struct Person {
|
||||||
/// Whether the person is local to our site.
|
/// Whether the person is local to our site.
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<SensitiveString>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::secret;
|
use crate::schema::secret;
|
||||||
|
use crate::sensitive::SensitiveString;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable))]
|
#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable))]
|
||||||
|
@ -7,5 +8,5 @@ use crate::schema::secret;
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
pub struct Secret {
|
pub struct Secret {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub jwt_secret: String,
|
pub jwt_secret: SensitiveString,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::newtypes::{DbUrl, InstanceId, SiteId};
|
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::site;
|
use crate::schema::site;
|
||||||
|
use crate::{
|
||||||
|
newtypes::{DbUrl, InstanceId, SiteId},
|
||||||
|
sensitive::SensitiveString,
|
||||||
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
@ -35,7 +38,7 @@ pub struct Site {
|
||||||
/// The site inbox
|
/// The site inbox
|
||||||
pub inbox_url: DbUrl,
|
pub inbox_url: DbUrl,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<SensitiveString>,
|
||||||
// TODO: mark as `serde(skip)` in next major release as its not needed for api
|
// TODO: mark as `serde(skip)` in next major release as its not needed for api
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
|
|
Loading…
Reference in a new issue