Compare commits
1 commit
main
...
sync_actor
Author | SHA1 | Date | |
---|---|---|---|
ef25414aff |
19 changed files with 602 additions and 348 deletions
|
@ -65,17 +65,21 @@ pub struct GetCommentsResponse {
|
|||
}
|
||||
|
||||
impl Perform<CommentResponse> for Oper<CreateComment> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommentResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommentResponse, Error> {
|
||||
let data: &CreateComment = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
||||
let user_id = claims.id;
|
||||
|
||||
let hostname = &format!("https://{}", Settings::get().hostname);
|
||||
let hostname = &format!("https://{}", settings.hostname);
|
||||
|
||||
// Check for a community ban
|
||||
let post = Post::read(&conn, data.post_id)?;
|
||||
|
@ -137,14 +141,14 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
|
|||
if let Some(mention_email) = mention_user.email {
|
||||
let subject = &format!(
|
||||
"{} - Mentioned by {}",
|
||||
Settings::get().hostname,
|
||||
settings.hostname,
|
||||
claims.username
|
||||
);
|
||||
let html = &format!(
|
||||
"<h1>User Mention</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||
claims.username, comment_form.content, hostname
|
||||
);
|
||||
match send_email(subject, &mention_email, &mention_user.name, html) {
|
||||
match send_email(subject, &mention_email, &mention_user.name, html, settings) {
|
||||
Ok(_o) => _o,
|
||||
Err(e) => error!("{}", e),
|
||||
};
|
||||
|
@ -166,14 +170,14 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
|
|||
if let Some(comment_reply_email) = parent_user.email {
|
||||
let subject = &format!(
|
||||
"{} - Reply from {}",
|
||||
Settings::get().hostname,
|
||||
settings.hostname,
|
||||
claims.username
|
||||
);
|
||||
let html = &format!(
|
||||
"<h1>Comment Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||
claims.username, comment_form.content, hostname
|
||||
);
|
||||
match send_email(subject, &comment_reply_email, &parent_user.name, html) {
|
||||
match send_email(subject, &comment_reply_email, &parent_user.name, html, settings) {
|
||||
Ok(_o) => _o,
|
||||
Err(e) => error!("{}", e),
|
||||
};
|
||||
|
@ -191,14 +195,14 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
|
|||
if let Some(post_reply_email) = parent_user.email {
|
||||
let subject = &format!(
|
||||
"{} - Reply from {}",
|
||||
Settings::get().hostname,
|
||||
settings.hostname,
|
||||
claims.username
|
||||
);
|
||||
let html = &format!(
|
||||
"<h1>Post Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||
claims.username, comment_form.content, hostname
|
||||
);
|
||||
match send_email(subject, &post_reply_email, &parent_user.name, html) {
|
||||
match send_email(subject, &post_reply_email, &parent_user.name, html, settings) {
|
||||
Ok(_o) => _o,
|
||||
Err(e) => error!("{}", e),
|
||||
};
|
||||
|
@ -231,10 +235,14 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
|
|||
}
|
||||
|
||||
impl Perform<CommentResponse> for Oper<EditComment> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommentResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommentResponse, Error> {
|
||||
let data: &EditComment = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -361,10 +369,14 @@ impl Perform<CommentResponse> for Oper<EditComment> {
|
|||
}
|
||||
|
||||
impl Perform<CommentResponse> for Oper<SaveComment> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommentResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommentResponse, Error> {
|
||||
let data: &SaveComment = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -398,10 +410,14 @@ impl Perform<CommentResponse> for Oper<SaveComment> {
|
|||
}
|
||||
|
||||
impl Perform<CommentResponse> for Oper<CreateCommentLike> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommentResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommentResponse, Error> {
|
||||
let data: &CreateCommentLike = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -475,11 +491,15 @@ impl Perform<CommentResponse> for Oper<CreateCommentLike> {
|
|||
}
|
||||
|
||||
impl Perform<GetCommentsResponse> for Oper<GetComments> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetCommentsResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetCommentsResponse, Error> {
|
||||
let data: &GetComments = &self.data;
|
||||
|
||||
let user_claims: Option<Claims> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => Some(claims.claims),
|
||||
Err(_e) => None,
|
||||
},
|
||||
|
|
|
@ -114,11 +114,15 @@ pub struct TransferCommunity {
|
|||
}
|
||||
|
||||
impl Perform<GetCommunityResponse> for Oper<GetCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetCommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetCommunityResponse, Error> {
|
||||
let data: &GetCommunity = &self.data;
|
||||
|
||||
let user_id: Option<i32> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => {
|
||||
let user_id = claims.claims.id;
|
||||
Some(user_id)
|
||||
|
@ -168,10 +172,14 @@ impl Perform<GetCommunityResponse> for Oper<GetCommunity> {
|
|||
}
|
||||
|
||||
impl Perform<CommunityResponse> for Oper<CreateCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommunityResponse, Error> {
|
||||
let data: &CreateCommunity = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -246,7 +254,11 @@ impl Perform<CommunityResponse> for Oper<CreateCommunity> {
|
|||
}
|
||||
|
||||
impl Perform<CommunityResponse> for Oper<EditCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommunityResponse, Error> {
|
||||
let data: &EditCommunity = &self.data;
|
||||
|
||||
if let Err(slurs) = slur_check(&data.name) {
|
||||
|
@ -263,7 +275,7 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
|
|||
}
|
||||
}
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -330,11 +342,15 @@ impl Perform<CommunityResponse> for Oper<EditCommunity> {
|
|||
}
|
||||
|
||||
impl Perform<ListCommunitiesResponse> for Oper<ListCommunities> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<ListCommunitiesResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<ListCommunitiesResponse, Error> {
|
||||
let data: &ListCommunities = &self.data;
|
||||
|
||||
let user_claims: Option<Claims> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => Some(claims.claims),
|
||||
Err(_e) => None,
|
||||
},
|
||||
|
@ -367,10 +383,14 @@ impl Perform<ListCommunitiesResponse> for Oper<ListCommunities> {
|
|||
}
|
||||
|
||||
impl Perform<CommunityResponse> for Oper<FollowCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<CommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<CommunityResponse, Error> {
|
||||
let data: &FollowCommunity = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -403,10 +423,14 @@ impl Perform<CommunityResponse> for Oper<FollowCommunity> {
|
|||
}
|
||||
|
||||
impl Perform<GetFollowedCommunitiesResponse> for Oper<GetFollowedCommunities> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetFollowedCommunitiesResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetFollowedCommunitiesResponse, Error> {
|
||||
let data: &GetFollowedCommunities = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -425,10 +449,14 @@ impl Perform<GetFollowedCommunitiesResponse> for Oper<GetFollowedCommunities> {
|
|||
}
|
||||
|
||||
impl Perform<BanFromCommunityResponse> for Oper<BanFromCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<BanFromCommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<BanFromCommunityResponse, Error> {
|
||||
let data: &BanFromCommunity = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -478,10 +506,14 @@ impl Perform<BanFromCommunityResponse> for Oper<BanFromCommunity> {
|
|||
}
|
||||
|
||||
impl Perform<AddModToCommunityResponse> for Oper<AddModToCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<AddModToCommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<AddModToCommunityResponse, Error> {
|
||||
let data: &AddModToCommunity = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -521,10 +553,14 @@ impl Perform<AddModToCommunityResponse> for Oper<AddModToCommunity> {
|
|||
}
|
||||
|
||||
impl Perform<GetCommunityResponse> for Oper<TransferCommunity> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetCommunityResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetCommunityResponse, Error> {
|
||||
let data: &TransferCommunity = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::db::user_mention::*;
|
|||
use crate::db::user_mention_view::*;
|
||||
use crate::db::user_view::*;
|
||||
use crate::db::*;
|
||||
use crate::Settings;
|
||||
use crate::{
|
||||
extract_usernames, fetch_iframely_and_pictshare_data, naive_from_unix, naive_now, remove_slurs,
|
||||
slur_check, slurs_vec_to_str,
|
||||
|
@ -56,7 +57,7 @@ impl<T> Oper<T> {
|
|||
}
|
||||
|
||||
pub trait Perform<T> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<T, Error>
|
||||
fn perform(&self, conn: &PgConnection, settings: &Settings) -> Result<T, Error>
|
||||
where
|
||||
T: Sized;
|
||||
}
|
||||
|
|
|
@ -80,10 +80,14 @@ pub struct SavePost {
|
|||
}
|
||||
|
||||
impl Perform<PostResponse> for Oper<CreatePost> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PostResponse, Error> {
|
||||
let data: &CreatePost = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -169,11 +173,15 @@ impl Perform<PostResponse> for Oper<CreatePost> {
|
|||
}
|
||||
|
||||
impl Perform<GetPostResponse> for Oper<GetPost> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetPostResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetPostResponse, Error> {
|
||||
let data: &GetPost = &self.data;
|
||||
|
||||
let user_id: Option<i32> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => {
|
||||
let user_id = claims.claims.id;
|
||||
Some(user_id)
|
||||
|
@ -217,11 +225,15 @@ impl Perform<GetPostResponse> for Oper<GetPost> {
|
|||
}
|
||||
|
||||
impl Perform<GetPostsResponse> for Oper<GetPosts> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetPostsResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetPostsResponse, Error> {
|
||||
let data: &GetPosts = &self.data;
|
||||
|
||||
let user_claims: Option<Claims> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => Some(claims.claims),
|
||||
Err(_e) => None,
|
||||
},
|
||||
|
@ -260,10 +272,14 @@ impl Perform<GetPostsResponse> for Oper<GetPosts> {
|
|||
}
|
||||
|
||||
impl Perform<PostResponse> for Oper<CreatePostLike> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PostResponse, Error> {
|
||||
let data: &CreatePostLike = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -318,7 +334,11 @@ impl Perform<PostResponse> for Oper<CreatePostLike> {
|
|||
}
|
||||
|
||||
impl Perform<PostResponse> for Oper<EditPost> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PostResponse, Error> {
|
||||
let data: &EditPost = &self.data;
|
||||
|
||||
if let Err(slurs) = slur_check(&data.name) {
|
||||
|
@ -331,7 +351,7 @@ impl Perform<PostResponse> for Oper<EditPost> {
|
|||
}
|
||||
}
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -432,10 +452,14 @@ impl Perform<PostResponse> for Oper<EditPost> {
|
|||
}
|
||||
|
||||
impl Perform<PostResponse> for Oper<SavePost> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PostResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PostResponse, Error> {
|
||||
let data: &SavePost = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
|
|
@ -114,7 +114,11 @@ pub struct SaveSiteConfig {
|
|||
}
|
||||
|
||||
impl Perform<ListCategoriesResponse> for Oper<ListCategories> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<ListCategoriesResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<ListCategoriesResponse, Error> {
|
||||
let _data: &ListCategories = &self.data;
|
||||
|
||||
let categories: Vec<Category> = Category::list_all(&conn)?;
|
||||
|
@ -125,7 +129,11 @@ impl Perform<ListCategoriesResponse> for Oper<ListCategories> {
|
|||
}
|
||||
|
||||
impl Perform<GetModlogResponse> for Oper<GetModlog> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetModlogResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetModlogResponse, Error> {
|
||||
let data: &GetModlog = &self.data;
|
||||
|
||||
let removed_posts = ModRemovePostView::list(
|
||||
|
@ -198,10 +206,14 @@ impl Perform<GetModlogResponse> for Oper<GetModlog> {
|
|||
}
|
||||
|
||||
impl Perform<SiteResponse> for Oper<CreateSite> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<SiteResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<SiteResponse, Error> {
|
||||
let data: &CreateSite = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -245,10 +257,14 @@ impl Perform<SiteResponse> for Oper<CreateSite> {
|
|||
}
|
||||
|
||||
impl Perform<SiteResponse> for Oper<EditSite> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<SiteResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<SiteResponse, Error> {
|
||||
let data: &EditSite = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -294,13 +310,17 @@ impl Perform<SiteResponse> for Oper<EditSite> {
|
|||
}
|
||||
|
||||
impl Perform<GetSiteResponse> for Oper<GetSite> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetSiteResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetSiteResponse, Error> {
|
||||
let _data: &GetSite = &self.data;
|
||||
|
||||
let site = Site::read(&conn, 1);
|
||||
let site_view = if site.is_ok() {
|
||||
Some(SiteView::read(&conn)?)
|
||||
} else if let Some(setup) = Settings::get().setup.as_ref() {
|
||||
} else if let Some(setup) = &settings.setup {
|
||||
let register = Register {
|
||||
username: setup.admin_username.to_owned(),
|
||||
email: setup.admin_email.to_owned(),
|
||||
|
@ -309,7 +329,7 @@ impl Perform<GetSiteResponse> for Oper<GetSite> {
|
|||
admin: true,
|
||||
show_nsfw: true,
|
||||
};
|
||||
let login_response = Oper::new(register).perform(&conn)?;
|
||||
let login_response = Oper::new(register).perform(&conn, &settings)?;
|
||||
info!("Admin {} created", setup.admin_username);
|
||||
|
||||
let create_site = CreateSite {
|
||||
|
@ -320,7 +340,7 @@ impl Perform<GetSiteResponse> for Oper<GetSite> {
|
|||
enable_nsfw: false,
|
||||
auth: login_response.jwt,
|
||||
};
|
||||
Oper::new(create_site).perform(&conn)?;
|
||||
Oper::new(create_site).perform(&conn, &settings)?;
|
||||
info!("Site {} created", setup.site_name);
|
||||
Some(SiteView::read(&conn)?)
|
||||
} else {
|
||||
|
@ -347,11 +367,15 @@ impl Perform<GetSiteResponse> for Oper<GetSite> {
|
|||
}
|
||||
|
||||
impl Perform<SearchResponse> for Oper<Search> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<SearchResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<SearchResponse, Error> {
|
||||
let data: &Search = &self.data;
|
||||
|
||||
let user_id: Option<i32> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => {
|
||||
let user_id = claims.claims.id;
|
||||
Some(user_id)
|
||||
|
@ -465,10 +489,14 @@ impl Perform<SearchResponse> for Oper<Search> {
|
|||
}
|
||||
|
||||
impl Perform<GetSiteResponse> for Oper<TransferSite> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetSiteResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetSiteResponse, Error> {
|
||||
let data: &TransferSite = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -528,10 +556,14 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
|
|||
}
|
||||
|
||||
impl Perform<GetSiteConfigResponse> for Oper<GetSiteConfig> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetSiteConfigResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetSiteConfigResponse, Error> {
|
||||
let data: &GetSiteConfig = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -553,10 +585,14 @@ impl Perform<GetSiteConfigResponse> for Oper<GetSiteConfig> {
|
|||
}
|
||||
|
||||
impl Perform<GetSiteConfigResponse> for Oper<SaveSiteConfig> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetSiteConfigResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetSiteConfigResponse, Error> {
|
||||
let data: &SaveSiteConfig = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
|
|
@ -205,7 +205,11 @@ pub struct UserJoinResponse {
|
|||
}
|
||||
|
||||
impl Perform<LoginResponse> for Oper<Login> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<LoginResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<LoginResponse, Error> {
|
||||
let data: &Login = &self.data;
|
||||
|
||||
// Fetch that username / email
|
||||
|
@ -221,12 +225,16 @@ impl Perform<LoginResponse> for Oper<Login> {
|
|||
}
|
||||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse { jwt: user.jwt() })
|
||||
Ok(LoginResponse { jwt: user.jwt(&settings.jwt_secret) })
|
||||
}
|
||||
}
|
||||
|
||||
impl Perform<LoginResponse> for Oper<Register> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<LoginResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<LoginResponse, Error> {
|
||||
let data: &Register = &self.data;
|
||||
|
||||
// Make sure site has open registration
|
||||
|
@ -253,7 +261,7 @@ impl Perform<LoginResponse> for Oper<Register> {
|
|||
// Register the new user
|
||||
let user_form = UserForm {
|
||||
name: data.username.to_owned(),
|
||||
fedi_name: Settings::get().hostname,
|
||||
fedi_name: settings.hostname.to_owned(),
|
||||
email: data.email.to_owned(),
|
||||
matrix_user_id: None,
|
||||
avatar: None,
|
||||
|
@ -334,16 +342,20 @@ impl Perform<LoginResponse> for Oper<Register> {
|
|||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: inserted_user.jwt(),
|
||||
jwt: inserted_user.jwt(&settings.jwt_secret),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Perform<LoginResponse> for Oper<SaveUserSettings> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<LoginResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<LoginResponse, Error> {
|
||||
let data: &SaveUserSettings = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -422,17 +434,21 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
|
|||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: updated_user.jwt(),
|
||||
jwt: updated_user.jwt(&settings.jwt_secret),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetUserDetailsResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetUserDetailsResponse, Error> {
|
||||
let data: &GetUserDetails = &self.data;
|
||||
|
||||
let user_claims: Option<Claims> = match &data.auth {
|
||||
Some(auth) => match Claims::decode(&auth) {
|
||||
Some(auth) => match Claims::decode(&auth, &settings.jwt_secret) {
|
||||
Ok(claims) => Some(claims.claims),
|
||||
Err(_e) => None,
|
||||
},
|
||||
|
@ -525,10 +541,14 @@ impl Perform<GetUserDetailsResponse> for Oper<GetUserDetails> {
|
|||
}
|
||||
|
||||
impl Perform<AddAdminResponse> for Oper<AddAdmin> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<AddAdminResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<AddAdminResponse, Error> {
|
||||
let data: &AddAdmin = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -588,10 +608,14 @@ impl Perform<AddAdminResponse> for Oper<AddAdmin> {
|
|||
}
|
||||
|
||||
impl Perform<BanUserResponse> for Oper<BanUser> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<BanUserResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<BanUserResponse, Error> {
|
||||
let data: &BanUser = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -657,10 +681,14 @@ impl Perform<BanUserResponse> for Oper<BanUser> {
|
|||
}
|
||||
|
||||
impl Perform<GetRepliesResponse> for Oper<GetReplies> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetRepliesResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetRepliesResponse, Error> {
|
||||
let data: &GetReplies = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -681,10 +709,14 @@ impl Perform<GetRepliesResponse> for Oper<GetReplies> {
|
|||
}
|
||||
|
||||
impl Perform<GetUserMentionsResponse> for Oper<GetUserMentions> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetUserMentionsResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetUserMentionsResponse, Error> {
|
||||
let data: &GetUserMentions = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -705,10 +737,14 @@ impl Perform<GetUserMentionsResponse> for Oper<GetUserMentions> {
|
|||
}
|
||||
|
||||
impl Perform<UserMentionResponse> for Oper<EditUserMention> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<UserMentionResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<UserMentionResponse, Error> {
|
||||
let data: &EditUserMention = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -738,10 +774,14 @@ impl Perform<UserMentionResponse> for Oper<EditUserMention> {
|
|||
}
|
||||
|
||||
impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<GetRepliesResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<GetRepliesResponse, Error> {
|
||||
let data: &MarkAllAsRead = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -822,10 +862,14 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
|
|||
}
|
||||
|
||||
impl Perform<LoginResponse> for Oper<DeleteAccount> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<LoginResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<LoginResponse, Error> {
|
||||
let data: &DeleteAccount = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -903,7 +947,11 @@ impl Perform<LoginResponse> for Oper<DeleteAccount> {
|
|||
}
|
||||
|
||||
impl Perform<PasswordResetResponse> for Oper<PasswordReset> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PasswordResetResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PasswordResetResponse, Error> {
|
||||
let data: &PasswordReset = &self.data;
|
||||
|
||||
// Fetch that email
|
||||
|
@ -922,9 +970,9 @@ impl Perform<PasswordResetResponse> for Oper<PasswordReset> {
|
|||
// TODO no i18n support here.
|
||||
let user_email = &user.email.expect("email");
|
||||
let subject = &format!("Password reset for {}", user.name);
|
||||
let hostname = &format!("https://{}", Settings::get().hostname); //TODO add https for now.
|
||||
let hostname = &format!("https://{}", &settings.hostname); //TODO add https for now.
|
||||
let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", user.name, hostname, &token);
|
||||
match send_email(subject, user_email, &user.name, html) {
|
||||
match send_email(subject, user_email, &user.name, html, &settings) {
|
||||
Ok(_o) => _o,
|
||||
Err(_e) => return Err(APIError::err(&_e).into()),
|
||||
};
|
||||
|
@ -934,7 +982,11 @@ impl Perform<PasswordResetResponse> for Oper<PasswordReset> {
|
|||
}
|
||||
|
||||
impl Perform<LoginResponse> for Oper<PasswordChange> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<LoginResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<LoginResponse, Error> {
|
||||
let data: &PasswordChange = &self.data;
|
||||
|
||||
// Fetch the user_id from the token
|
||||
|
@ -953,23 +1005,27 @@ impl Perform<LoginResponse> for Oper<PasswordChange> {
|
|||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: updated_user.jwt(),
|
||||
jwt: updated_user.jwt(&settings.jwt_secret),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Perform<PrivateMessageResponse> for Oper<CreatePrivateMessage> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PrivateMessageResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PrivateMessageResponse, Error> {
|
||||
let data: &CreatePrivateMessage = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
||||
let user_id = claims.id;
|
||||
|
||||
let hostname = &format!("https://{}", Settings::get().hostname);
|
||||
let hostname = &format!("https://{}", &settings.hostname);
|
||||
|
||||
// Check for a site ban
|
||||
if UserView::read(&conn, user_id)?.banned {
|
||||
|
@ -1000,14 +1056,14 @@ impl Perform<PrivateMessageResponse> for Oper<CreatePrivateMessage> {
|
|||
if let Some(email) = recipient_user.email {
|
||||
let subject = &format!(
|
||||
"{} - Private Message from {}",
|
||||
Settings::get().hostname,
|
||||
&settings.hostname,
|
||||
claims.username
|
||||
);
|
||||
let html = &format!(
|
||||
"<h1>Private Message</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||
claims.username, &content_slurs_removed, hostname
|
||||
);
|
||||
match send_email(subject, &email, &recipient_user.name, html) {
|
||||
match send_email(subject, &email, &recipient_user.name, html, &settings) {
|
||||
Ok(_o) => _o,
|
||||
Err(e) => error!("{}", e),
|
||||
};
|
||||
|
@ -1021,10 +1077,14 @@ impl Perform<PrivateMessageResponse> for Oper<CreatePrivateMessage> {
|
|||
}
|
||||
|
||||
impl Perform<PrivateMessageResponse> for Oper<EditPrivateMessage> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PrivateMessageResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PrivateMessageResponse, Error> {
|
||||
let data: &EditPrivateMessage = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -1076,10 +1136,14 @@ impl Perform<PrivateMessageResponse> for Oper<EditPrivateMessage> {
|
|||
}
|
||||
|
||||
impl Perform<PrivateMessagesResponse> for Oper<GetPrivateMessages> {
|
||||
fn perform(&self, conn: &PgConnection) -> Result<PrivateMessagesResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<PrivateMessagesResponse, Error> {
|
||||
let data: &GetPrivateMessages = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
@ -1097,10 +1161,14 @@ impl Perform<PrivateMessagesResponse> for Oper<GetPrivateMessages> {
|
|||
}
|
||||
|
||||
impl Perform<UserJoinResponse> for Oper<UserJoin> {
|
||||
fn perform(&self, _conn: &PgConnection) -> Result<UserJoinResponse, Error> {
|
||||
fn perform(
|
||||
&self,
|
||||
conn: &PgConnection,
|
||||
settings: &Settings,
|
||||
) -> Result<UserJoinResponse, Error> {
|
||||
let data: &UserJoin = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
let claims = match Claims::decode(&data.auth, &settings.jwt_secret) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
|
|
@ -91,7 +91,7 @@ mod tests {
|
|||
|
||||
let page = post.as_page();
|
||||
assert_eq!(
|
||||
format!("https://{}/federation/post/62", Settings::get().hostname),
|
||||
format!("https://{}/federation/post/62", "fake_host"),
|
||||
page.object_props.id_string().unwrap()
|
||||
);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ mod tests {
|
|||
pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> String {
|
||||
format!(
|
||||
"https://{}/federation/{}/{}",
|
||||
Settings::get().hostname,
|
||||
"fake_host",
|
||||
point,
|
||||
value
|
||||
)
|
||||
|
|
|
@ -69,8 +69,8 @@ impl Community {
|
|||
.first::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn get_url(&self) -> String {
|
||||
format!("https://{}/c/{}", Settings::get().hostname, self.name)
|
||||
pub fn get_url(&self, hostname: &str) -> String {
|
||||
format!("https://{}/c/{}", hostname, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<T> MaybeOptional<T> for Option<T> {
|
|||
}
|
||||
|
||||
pub fn establish_unpooled_connection() -> PgConnection {
|
||||
let db_url = Settings::get().get_database_url();
|
||||
let db_url = Settings::init().unwrap().get_database_url();
|
||||
PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url))
|
||||
}
|
||||
|
||||
|
|
|
@ -110,14 +110,14 @@ pub struct Claims {
|
|||
}
|
||||
|
||||
impl Claims {
|
||||
pub fn decode(jwt: &str) -> Result<TokenData<Claims>, jsonwebtoken::errors::Error> {
|
||||
pub fn decode(jwt: &str, jwt_secret: &str) -> Result<TokenData<Claims>, jsonwebtoken::errors::Error> {
|
||||
let v = Validation {
|
||||
validate_exp: false,
|
||||
..Validation::default()
|
||||
};
|
||||
decode::<Claims>(
|
||||
&jwt,
|
||||
&DecodingKey::from_secret(Settings::get().jwt_secret.as_ref()),
|
||||
&DecodingKey::from_secret(jwt_secret.as_bytes()),
|
||||
&v,
|
||||
)
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ impl Claims {
|
|||
|
||||
type Jwt = String;
|
||||
impl User_ {
|
||||
pub fn jwt(&self) -> Jwt {
|
||||
pub fn jwt(&self, jwt_secret: &str) -> Jwt {
|
||||
let my_claims = Claims {
|
||||
id: self.id,
|
||||
username: self.name.to_owned(),
|
||||
|
@ -141,7 +141,7 @@ impl User_ {
|
|||
encode(
|
||||
&Header::default(),
|
||||
&my_claims,
|
||||
&EncodingKey::from_secret(Settings::get().jwt_secret.as_ref()),
|
||||
&EncodingKey::from_secret(jwt_secret.as_bytes()),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
@ -165,12 +165,12 @@ impl User_ {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_profile_url(&self) -> String {
|
||||
format!("https://{}/u/{}", Settings::get().hostname, self.name)
|
||||
pub fn get_profile_url(&self, hostname: &str) -> String {
|
||||
format!("https://{}/u/{}", hostname, self.name)
|
||||
}
|
||||
|
||||
pub fn find_by_jwt(conn: &PgConnection, jwt: &str) -> Result<Self, Error> {
|
||||
let claims: Claims = Claims::decode(&jwt).expect("Invalid token").claims;
|
||||
pub fn find_by_jwt(conn: &PgConnection, jwt: &str, jwt_secret: &str) -> Result<Self, Error> {
|
||||
let claims: Claims = Claims::decode(jwt, jwt_secret).expect("Invalid token").claims;
|
||||
Self::read(&conn, claims.id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,8 +111,9 @@ pub fn send_email(
|
|||
to_email: &str,
|
||||
to_username: &str,
|
||||
html: &str,
|
||||
settings: &Settings,
|
||||
) -> Result<(), String> {
|
||||
let email_config = Settings::get().email.ok_or("no_email_setup")?;
|
||||
let email_config = settings.email.to_owned().ok_or("no_email_setup")?;
|
||||
|
||||
let email = Email::builder()
|
||||
.to((to_email, to_username))
|
||||
|
@ -127,7 +128,7 @@ pub fn send_email(
|
|||
} else {
|
||||
SmtpClient::new(&email_config.smtp_server, ClientSecurity::None).unwrap()
|
||||
}
|
||||
.hello_name(ClientId::Domain(Settings::get().hostname))
|
||||
.hello_name(ClientId::Domain(settings.hostname.to_owned()))
|
||||
.smtp_utf8(true)
|
||||
.authentication_mechanism(Mechanism::Plain)
|
||||
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited);
|
||||
|
|
|
@ -2,10 +2,8 @@ extern crate lemmy_server;
|
|||
#[macro_use]
|
||||
extern crate diesel_migrations;
|
||||
|
||||
use actix::prelude::*;
|
||||
use actix_web::*;
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel::PgConnection;
|
||||
use actix::prelude::*;
|
||||
use lemmy_server::routes::{api, federation, feeds, index, nodeinfo, webfinger, websocket};
|
||||
use lemmy_server::settings::Settings;
|
||||
use lemmy_server::websocket::server::*;
|
||||
|
@ -16,21 +14,24 @@ embed_migrations!();
|
|||
#[actix_rt::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
env_logger::init();
|
||||
let settings = Settings::get();
|
||||
|
||||
// Set up the r2d2 connection pool
|
||||
let manager = ConnectionManager::<PgConnection>::new(&settings.get_database_url());
|
||||
let pool = Pool::builder()
|
||||
.max_size(settings.database.pool_size)
|
||||
.build(manager)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", settings.get_database_url()));
|
||||
// Set up the Chatserver's shared state
|
||||
let cs_state_web = web::Data::new(ChatSharedState::init());
|
||||
let cs_state_web_two = cs_state_web.clone();
|
||||
let server = SyncArbiter::start(2, move || ChatServer::init(cs_state_web.clone()));
|
||||
|
||||
let settings = cs_state_web_two.settings.lock().unwrap().to_owned();
|
||||
|
||||
// Run the migrations from code
|
||||
let conn = pool.get().unwrap();
|
||||
// let conn = pool.get().unwrap();
|
||||
let conn = cs_state_web_two.pool.lock().unwrap().get().unwrap();
|
||||
embedded_migrations::run(&conn).unwrap();
|
||||
|
||||
|
||||
// Set up websocket server
|
||||
let server = ChatServer::startup(pool.clone()).start();
|
||||
// let server = ChatServer::init(cs_state).start();
|
||||
|
||||
// let cs_state_web_two = cs_state_web.clone();
|
||||
|
||||
println!(
|
||||
"Starting http server at {}:{}",
|
||||
|
@ -39,10 +40,11 @@ async fn main() -> io::Result<()> {
|
|||
|
||||
// Create Http server with websocket support
|
||||
HttpServer::new(move || {
|
||||
let settings = Settings::get();
|
||||
let settings = cs_state_web_two.settings.lock().unwrap().to_owned();
|
||||
App::new()
|
||||
.wrap(middleware::Logger::default())
|
||||
.data(pool.clone())
|
||||
// .app_data(cs_state_web_two.clone())
|
||||
.app_data(cs_state_web_two.clone())
|
||||
.data(server.clone())
|
||||
// The routes
|
||||
.configure(api::config)
|
||||
|
@ -59,7 +61,7 @@ async fn main() -> io::Result<()> {
|
|||
))
|
||||
.service(actix_files::Files::new(
|
||||
"/docs",
|
||||
settings.front_end_dir + "/documentation",
|
||||
settings.front_end_dir.to_owned() + "/documentation",
|
||||
))
|
||||
})
|
||||
.bind((settings.bind, settings.port))?
|
||||
|
|
|
@ -4,14 +4,13 @@ use crate::api::post::*;
|
|||
use crate::api::site::*;
|
||||
use crate::api::user::*;
|
||||
use crate::api::{Oper, Perform};
|
||||
use crate::websocket::server::ChatSharedState;
|
||||
use actix_web::{web, HttpResponse};
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel::PgConnection;
|
||||
use failure::Error;
|
||||
use serde::Serialize;
|
||||
|
||||
type DbParam = web::Data<Pool<ConnectionManager<PgConnection>>>;
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
cfg
|
||||
|
@ -66,40 +65,46 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
.route("/api/v1/user/save_user_settings", web::put().to(route_post::<SaveUserSettings, LoginResponse>));
|
||||
}
|
||||
|
||||
fn perform<Request, Response>(data: Request, db: DbParam) -> Result<HttpResponse, Error>
|
||||
fn perform<Request, Response>(
|
||||
data: Request,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
Response: Serialize,
|
||||
Oper<Request>: Perform<Response>,
|
||||
{
|
||||
let conn = match db.get() {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(format_err!("{}", e)),
|
||||
};
|
||||
// let conn = match db.get() {
|
||||
// Ok(c) => c,
|
||||
// Err(e) => return Err(format_err!("{}", e)),
|
||||
// };
|
||||
let conn = state.pool.lock().unwrap().get()?;
|
||||
let settings = state.settings.lock().unwrap();
|
||||
|
||||
let oper: Oper<Request> = Oper::new(data);
|
||||
let response = oper.perform(&conn);
|
||||
let response = oper.perform(&conn, &settings);
|
||||
Ok(HttpResponse::Ok().json(response?))
|
||||
}
|
||||
|
||||
async fn route_get<Data, Response>(
|
||||
data: web::Query<Data>,
|
||||
db: DbParam,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
Data: Serialize,
|
||||
Response: Serialize,
|
||||
Oper<Data>: Perform<Response>,
|
||||
{
|
||||
perform::<Data, Response>(data.0, db)
|
||||
perform::<Data, Response>(data.0, state)
|
||||
}
|
||||
|
||||
async fn route_post<Data, Response>(
|
||||
data: web::Json<Data>,
|
||||
db: DbParam,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
Data: Serialize,
|
||||
Response: Serialize,
|
||||
Oper<Data>: Perform<Response>,
|
||||
{
|
||||
perform::<Data, Response>(data.0, db)
|
||||
perform::<Data, Response>(data.0, state)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ use crate::db::site_view::SiteView;
|
|||
use crate::db::user::{Claims, User_};
|
||||
use crate::db::user_mention_view::{UserMentionQueryBuilder, UserMentionView};
|
||||
use crate::db::{ListingType, SortType};
|
||||
use crate::{markdown_to_html, Settings};
|
||||
use crate::websocket::server::ChatSharedState;
|
||||
use crate::markdown_to_html;
|
||||
use actix_web::{web, HttpResponse, Result};
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel::PgConnection;
|
||||
use failure::Error;
|
||||
use rss::{CategoryBuilder, ChannelBuilder, GuidBuilder, Item, ItemBuilder};
|
||||
|
@ -37,11 +37,12 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
|
||||
async fn get_all_feed(
|
||||
info: web::Query<Params>,
|
||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let res = web::block(move || {
|
||||
let conn = db.get()?;
|
||||
get_feed_all_data(&conn, &get_sort_type(info)?)
|
||||
let conn = state.pool.lock().unwrap().get()?;
|
||||
let hostname = &state.settings.lock().unwrap().hostname;
|
||||
get_feed_all_data(&conn, &hostname, &get_sort_type(info)?)
|
||||
})
|
||||
.await
|
||||
.map(|rss| {
|
||||
|
@ -53,7 +54,7 @@ async fn get_all_feed(
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result<String, failure::Error> {
|
||||
fn get_feed_all_data(conn: &PgConnection, hostname: &str, sort_type: &SortType) -> Result<String, failure::Error> {
|
||||
let site_view = SiteView::read(&conn)?;
|
||||
|
||||
let posts = PostQueryBuilder::create(&conn)
|
||||
|
@ -61,12 +62,12 @@ fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result<String
|
|||
.sort(sort_type)
|
||||
.list()?;
|
||||
|
||||
let items = create_post_items(posts);
|
||||
let items = create_post_items(posts, hostname);
|
||||
|
||||
let mut channel_builder = ChannelBuilder::default();
|
||||
channel_builder
|
||||
.title(&format!("{} - All", site_view.name))
|
||||
.link(format!("https://{}", Settings::get().hostname))
|
||||
.link(format!("https://{}", hostname))
|
||||
.items(items);
|
||||
|
||||
if let Some(site_desc) = site_view.description {
|
||||
|
@ -79,10 +80,12 @@ fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result<String
|
|||
async fn get_feed(
|
||||
path: web::Path<(String, String)>,
|
||||
info: web::Query<Params>,
|
||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let res = web::block(move || {
|
||||
let conn = db.get()?;
|
||||
let conn = state.pool.lock().unwrap().get()?;
|
||||
let hostname = &state.settings.lock().unwrap().hostname;
|
||||
let jwt_secret = &state.settings.lock().unwrap().jwt_secret;
|
||||
|
||||
let sort_type = get_sort_type(info)?;
|
||||
|
||||
|
@ -97,10 +100,10 @@ async fn get_feed(
|
|||
let param = path.1.to_owned();
|
||||
|
||||
match request_type {
|
||||
RequestType::User => get_feed_user(&conn, &sort_type, param),
|
||||
RequestType::Community => get_feed_community(&conn, &sort_type, param),
|
||||
RequestType::Front => get_feed_front(&conn, &sort_type, param),
|
||||
RequestType::Inbox => get_feed_inbox(&conn, param),
|
||||
RequestType::User => get_feed_user(&conn, &hostname, &sort_type, param),
|
||||
RequestType::Community => get_feed_community(&conn, &hostname, &sort_type, param),
|
||||
RequestType::Front => get_feed_front(&conn, &hostname, &jwt_secret, &sort_type, param),
|
||||
RequestType::Inbox => get_feed_inbox(&conn, &hostname, &jwt_secret, param),
|
||||
}
|
||||
})
|
||||
.await
|
||||
|
@ -124,12 +127,13 @@ fn get_sort_type(info: web::Query<Params>) -> Result<SortType, ParseError> {
|
|||
|
||||
fn get_feed_user(
|
||||
conn: &PgConnection,
|
||||
hostname: &str,
|
||||
sort_type: &SortType,
|
||||
user_name: String,
|
||||
) -> Result<ChannelBuilder, Error> {
|
||||
let site_view = SiteView::read(&conn)?;
|
||||
let user = User_::find_by_username(&conn, &user_name)?;
|
||||
let user_url = user.get_profile_url();
|
||||
let user_url = user.get_profile_url(hostname);
|
||||
|
||||
let posts = PostQueryBuilder::create(&conn)
|
||||
.listing_type(ListingType::All)
|
||||
|
@ -137,7 +141,7 @@ fn get_feed_user(
|
|||
.for_creator_id(user.id)
|
||||
.list()?;
|
||||
|
||||
let items = create_post_items(posts);
|
||||
let items = create_post_items(posts, hostname);
|
||||
|
||||
let mut channel_builder = ChannelBuilder::default();
|
||||
channel_builder
|
||||
|
@ -150,12 +154,13 @@ fn get_feed_user(
|
|||
|
||||
fn get_feed_community(
|
||||
conn: &PgConnection,
|
||||
hostname: &str,
|
||||
sort_type: &SortType,
|
||||
community_name: String,
|
||||
) -> Result<ChannelBuilder, Error> {
|
||||
let site_view = SiteView::read(&conn)?;
|
||||
let community = Community::read_from_name(&conn, community_name)?;
|
||||
let community_url = community.get_url();
|
||||
let community_url = community.get_url(hostname);
|
||||
|
||||
let posts = PostQueryBuilder::create(&conn)
|
||||
.listing_type(ListingType::All)
|
||||
|
@ -163,7 +168,7 @@ fn get_feed_community(
|
|||
.for_community_id(community.id)
|
||||
.list()?;
|
||||
|
||||
let items = create_post_items(posts);
|
||||
let items = create_post_items(posts, hostname);
|
||||
|
||||
let mut channel_builder = ChannelBuilder::default();
|
||||
channel_builder
|
||||
|
@ -180,11 +185,13 @@ fn get_feed_community(
|
|||
|
||||
fn get_feed_front(
|
||||
conn: &PgConnection,
|
||||
hostname: &str,
|
||||
jwt_secret: &str,
|
||||
sort_type: &SortType,
|
||||
jwt: String,
|
||||
) -> Result<ChannelBuilder, Error> {
|
||||
let site_view = SiteView::read(&conn)?;
|
||||
let user_id = Claims::decode(&jwt)?.claims.id;
|
||||
let user_id = Claims::decode(&jwt, jwt_secret)?.claims.id;
|
||||
|
||||
let posts = PostQueryBuilder::create(&conn)
|
||||
.listing_type(ListingType::Subscribed)
|
||||
|
@ -192,12 +199,12 @@ fn get_feed_front(
|
|||
.my_user_id(user_id)
|
||||
.list()?;
|
||||
|
||||
let items = create_post_items(posts);
|
||||
let items = create_post_items(posts, hostname);
|
||||
|
||||
let mut channel_builder = ChannelBuilder::default();
|
||||
channel_builder
|
||||
.title(&format!("{} - Subscribed", site_view.name))
|
||||
.link(format!("https://{}", Settings::get().hostname))
|
||||
.link(format!("https://{}", hostname))
|
||||
.items(items);
|
||||
|
||||
if let Some(site_desc) = site_view.description {
|
||||
|
@ -207,9 +214,13 @@ fn get_feed_front(
|
|||
Ok(channel_builder)
|
||||
}
|
||||
|
||||
fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result<ChannelBuilder, Error> {
|
||||
fn get_feed_inbox(
|
||||
conn: &PgConnection,
|
||||
hostname: &str,
|
||||
jwt_secret: &str,
|
||||
jwt: String) -> Result<ChannelBuilder, Error> {
|
||||
let site_view = SiteView::read(&conn)?;
|
||||
let user_id = Claims::decode(&jwt)?.claims.id;
|
||||
let user_id = Claims::decode(&jwt, jwt_secret)?.claims.id;
|
||||
|
||||
let sort = SortType::New;
|
||||
|
||||
|
@ -221,12 +232,12 @@ fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result<ChannelBuilder, Er
|
|||
.sort(&sort)
|
||||
.list()?;
|
||||
|
||||
let items = create_reply_and_mention_items(replies, mentions);
|
||||
let items = create_reply_and_mention_items(replies, mentions, hostname);
|
||||
|
||||
let mut channel_builder = ChannelBuilder::default();
|
||||
channel_builder
|
||||
.title(&format!("{} - Inbox", site_view.name))
|
||||
.link(format!("https://{}/inbox", Settings::get().hostname))
|
||||
.link(format!("https://{}/inbox", hostname))
|
||||
.items(items);
|
||||
|
||||
if let Some(site_desc) = site_view.description {
|
||||
|
@ -239,17 +250,18 @@ fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result<ChannelBuilder, Er
|
|||
fn create_reply_and_mention_items(
|
||||
replies: Vec<ReplyView>,
|
||||
mentions: Vec<UserMentionView>,
|
||||
hostname: &str,
|
||||
) -> Vec<Item> {
|
||||
let mut reply_items: Vec<Item> = replies
|
||||
.iter()
|
||||
.map(|r| {
|
||||
let reply_url = format!(
|
||||
"https://{}/post/{}/comment/{}",
|
||||
Settings::get().hostname,
|
||||
hostname,
|
||||
r.post_id,
|
||||
r.id
|
||||
);
|
||||
build_item(&r.creator_name, &r.published, &reply_url, &r.content)
|
||||
build_item(&r.creator_name, &r.published, &reply_url, &r.content, hostname)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -258,11 +270,11 @@ fn create_reply_and_mention_items(
|
|||
.map(|m| {
|
||||
let mention_url = format!(
|
||||
"https://{}/post/{}/comment/{}",
|
||||
Settings::get().hostname,
|
||||
hostname,
|
||||
m.post_id,
|
||||
m.id
|
||||
);
|
||||
build_item(&m.creator_name, &m.published, &mention_url, &m.content)
|
||||
build_item(&m.creator_name, &m.published, &mention_url, &m.content, hostname)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -270,10 +282,10 @@ fn create_reply_and_mention_items(
|
|||
reply_items
|
||||
}
|
||||
|
||||
fn build_item(creator_name: &str, published: &NaiveDateTime, url: &str, content: &str) -> Item {
|
||||
fn build_item(creator_name: &str, published: &NaiveDateTime, url: &str, content: &str, hostname: &str) -> Item {
|
||||
let mut i = ItemBuilder::default();
|
||||
i.title(format!("Reply from {}", creator_name));
|
||||
let author_url = format!("https://{}/u/{}", Settings::get().hostname, creator_name);
|
||||
let author_url = format!("https://{}/u/{}", hostname, creator_name);
|
||||
i.author(format!(
|
||||
"/u/{} <a href=\"{}\">(link)</a>",
|
||||
creator_name, author_url
|
||||
|
@ -290,7 +302,7 @@ fn build_item(creator_name: &str, published: &NaiveDateTime, url: &str, content:
|
|||
i.build().unwrap()
|
||||
}
|
||||
|
||||
fn create_post_items(posts: Vec<PostView>) -> Vec<Item> {
|
||||
fn create_post_items(posts: Vec<PostView>, hostname: &str) -> Vec<Item> {
|
||||
let mut items: Vec<Item> = Vec::new();
|
||||
|
||||
for p in posts {
|
||||
|
@ -298,7 +310,7 @@ fn create_post_items(posts: Vec<PostView>) -> Vec<Item> {
|
|||
|
||||
i.title(p.name);
|
||||
|
||||
let author_url = format!("https://{}/u/{}", Settings::get().hostname, p.creator_name);
|
||||
let author_url = format!("https://{}/u/{}", hostname, p.creator_name);
|
||||
i.author(format!(
|
||||
"/u/{} <a href=\"{}\">(link)</a>",
|
||||
p.creator_name, author_url
|
||||
|
@ -307,7 +319,7 @@ fn create_post_items(posts: Vec<PostView>) -> Vec<Item> {
|
|||
let dt = DateTime::<Utc>::from_utc(p.published, Utc);
|
||||
i.pub_date(dt.to_rfc2822());
|
||||
|
||||
let post_url = format!("https://{}/post/{}", Settings::get().hostname, p.id);
|
||||
let post_url = format!("https://{}/post/{}", hostname, p.id);
|
||||
i.comments(post_url.to_owned());
|
||||
let guid = GuidBuilder::default()
|
||||
.permalink(true)
|
||||
|
@ -317,7 +329,7 @@ fn create_post_items(posts: Vec<PostView>) -> Vec<Item> {
|
|||
|
||||
let community_url = format!(
|
||||
"https://{}/c/{}",
|
||||
Settings::get().hostname,
|
||||
hostname,
|
||||
p.community_name
|
||||
);
|
||||
|
||||
|
@ -326,7 +338,7 @@ fn create_post_items(posts: Vec<PostView>) -> Vec<Item> {
|
|||
"/c/{} <a href=\"{}\">(link)</a>",
|
||||
p.community_name, community_url
|
||||
))
|
||||
.domain(Settings::get().hostname.to_owned())
|
||||
.domain(hostname.to_string())
|
||||
.build();
|
||||
i.categories(vec![category.unwrap()]);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::settings::Settings;
|
||||
use crate::websocket::server::ChatSharedState;
|
||||
use actix_files::NamedFile;
|
||||
use actix_web::web;
|
||||
|
||||
|
@ -43,8 +43,10 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
.route("/password_change/{token}", web::get().to(index));
|
||||
}
|
||||
|
||||
async fn index() -> Result<NamedFile, actix_web::error::Error> {
|
||||
async fn index(
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<NamedFile, actix_web::error::Error> {
|
||||
Ok(NamedFile::open(
|
||||
Settings::get().front_end_dir + "/index.html",
|
||||
state.settings.lock().unwrap().front_end_dir.to_owned() + "/index.html",
|
||||
)?)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use crate::db::site_view::SiteView;
|
||||
use crate::version;
|
||||
use crate::Settings;
|
||||
use crate::websocket::server::ChatSharedState;
|
||||
use actix_web::body::Body;
|
||||
use actix_web::web;
|
||||
use actix_web::HttpResponse;
|
||||
use diesel::r2d2::{ConnectionManager, Pool};
|
||||
use diesel::PgConnection;
|
||||
use serde::Serialize;
|
||||
|
||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
|
@ -14,26 +12,29 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
.route("/.well-known/nodeinfo", web::get().to(node_info_well_known));
|
||||
}
|
||||
|
||||
async fn node_info_well_known() -> HttpResponse<Body> {
|
||||
async fn node_info_well_known(
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> HttpResponse<Body> {
|
||||
let node_info = NodeInfoWellKnown {
|
||||
links: NodeInfoWellKnownLinks {
|
||||
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(),
|
||||
href: format!("https://{}/nodeinfo/2.0.json", Settings::get().hostname),
|
||||
href: format!("https://{}/nodeinfo/2.0.json", state.settings.lock().unwrap().hostname),
|
||||
},
|
||||
};
|
||||
HttpResponse::Ok().json(node_info)
|
||||
}
|
||||
|
||||
async fn node_info(
|
||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let res = web::block(move || {
|
||||
let conn = db.get()?;
|
||||
|
||||
let conn = state.pool.lock().unwrap().get()?;
|
||||
let site_view = match SiteView::read(&conn) {
|
||||
Ok(site_view) => site_view,
|
||||
Err(_) => return Err(format_err!("not_found")),
|
||||
};
|
||||
let protocols = if Settings::get().federation_enabled {
|
||||
let protocols = if state.settings.lock().unwrap().federation_enabled {
|
||||
vec!["activitypub".to_string()]
|
||||
} else {
|
||||
vec![]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::db::community::Community;
|
||||
use crate::websocket::server::ChatSharedState;
|
||||
use crate::Settings;
|
||||
use actix_web::web;
|
||||
use actix_web::web::Query;
|
||||
|
@ -14,21 +15,17 @@ pub struct Params {
|
|||
resource: String,
|
||||
}
|
||||
|
||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
if Settings::get().federation_enabled {
|
||||
pub fn config(
|
||||
cfg: &mut web::ServiceConfig,
|
||||
) {
|
||||
|
||||
// TODO couldn't get this to pass the app state
|
||||
// if state.settings.lock().unwrap().federation_enabled {
|
||||
cfg.route(
|
||||
".well-known/webfinger",
|
||||
web::get().to(get_webfinger_response),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref WEBFINGER_COMMUNITY_REGEX: Regex = Regex::new(&format!(
|
||||
"^group:([a-z0-9_]{{3, 20}})@{}$",
|
||||
Settings::get().hostname
|
||||
))
|
||||
.unwrap();
|
||||
// }
|
||||
}
|
||||
|
||||
/// Responds to webfinger requests of the following format. There isn't any real documentation for
|
||||
|
@ -39,10 +36,16 @@ lazy_static! {
|
|||
/// https://radical.town/.well-known/webfinger?resource=acct:felix@radical.town
|
||||
async fn get_webfinger_response(
|
||||
info: Query<Params>,
|
||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||
state: web::Data<ChatSharedState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let res = web::block(move || {
|
||||
let conn = db.get()?;
|
||||
let conn = state.pool.lock().unwrap().get()?;
|
||||
let hostname = &state.settings.lock().unwrap().hostname;
|
||||
let WEBFINGER_COMMUNITY_REGEX: Regex = Regex::new(&format!(
|
||||
"^group:([a-z0-9_]{{3, 20}})@{}$",
|
||||
hostname
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let regex_parsed = WEBFINGER_COMMUNITY_REGEX
|
||||
.captures(&info.resource)
|
||||
|
@ -63,7 +66,7 @@ async fn get_webfinger_response(
|
|||
Err(_) => return Err(format_err!("not_found")),
|
||||
};
|
||||
|
||||
let community_url = community.get_url();
|
||||
let community_url = community.get_url(&hostname);
|
||||
|
||||
Ok(json!({
|
||||
"subject": info.resource,
|
||||
|
|
|
@ -4,7 +4,8 @@ use serde::Deserialize;
|
|||
use std::env;
|
||||
use std::fs;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
static CONFIG_FILE_DEFAULTS: &str = "config/defaults.hjson";
|
||||
static CONFIG_FILE: &str = "config/config.hjson";
|
||||
|
@ -60,19 +61,12 @@ pub struct Database {
|
|||
pub pool_size: u32,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref SETTINGS: RwLock<Settings> = RwLock::new(match Settings::init() {
|
||||
Ok(c) => c,
|
||||
Err(e) => panic!("{}", e),
|
||||
});
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
/// Reads config from the files and environment.
|
||||
/// First, defaults are loaded from CONFIG_FILE_DEFAULTS, then these values can be overwritten
|
||||
/// from CONFIG_FILE (optional). Finally, values from the environment (with prefix LEMMY) are
|
||||
/// added to the config.
|
||||
fn init() -> Result<Self, ConfigError> {
|
||||
pub fn init() -> Result<Self, ConfigError> {
|
||||
let mut s = Config::new();
|
||||
|
||||
s.merge(File::with_name(CONFIG_FILE_DEFAULTS))?;
|
||||
|
@ -90,9 +84,9 @@ impl Settings {
|
|||
}
|
||||
|
||||
/// Returns the config as a struct.
|
||||
pub fn get() -> Self {
|
||||
SETTINGS.read().unwrap().to_owned()
|
||||
}
|
||||
// pub fn get() -> Self {
|
||||
// SETTINGS.read().unwrap().to_owned()
|
||||
// }
|
||||
|
||||
/// Returns the postgres connection url. If LEMMY_DATABASE_URL is set, that is used,
|
||||
/// otherwise the connection url is generated from the config.
|
||||
|
@ -120,15 +114,18 @@ impl Settings {
|
|||
|
||||
pub fn save_config_file(data: &str) -> Result<String, Error> {
|
||||
fs::write(CONFIG_FILE, data)?;
|
||||
|
||||
// Reload the new settings
|
||||
// From https://stackoverflow.com/questions/29654927/how-do-i-assign-a-string-to-a-mutable-static-variable/47181804#47181804
|
||||
let mut new_settings = SETTINGS.write().unwrap();
|
||||
*new_settings = match Settings::init() {
|
||||
Ok(c) => c,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
|
||||
Self::read_config_file()
|
||||
}
|
||||
|
||||
// pub fn live_reload_config(new_settings: Self) -> Result<(), Error> {
|
||||
// // TODO test that this works now
|
||||
// // Reload the new settings
|
||||
// // From https://stackoverflow.com/questions/29654927/how-do-i-assign-a-string-to-a-mutable-static-variable/47181804#47181804
|
||||
// new_settings = match Settings::init() {
|
||||
// Ok(c) => c,
|
||||
// Err(e) => panic!("{}", e),
|
||||
// };
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -7,13 +7,16 @@ use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
|||
use diesel::PgConnection;
|
||||
use failure::Error;
|
||||
use log::{error, info, warn};
|
||||
use rand::{rngs::ThreadRng, Rng};
|
||||
use rand::{Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::str::FromStr;
|
||||
use std::time::SystemTime;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::Arc;
|
||||
use strum::IntoEnumIterator;
|
||||
use actix_web::web;
|
||||
|
||||
use crate::api::comment::*;
|
||||
use crate::api::community::*;
|
||||
|
@ -80,105 +83,138 @@ pub enum RateLimitType {
|
|||
Post,
|
||||
}
|
||||
|
||||
/// `ChatServer` manages chat rooms and responsible for coordinating chat
|
||||
/// session.
|
||||
pub struct ChatServer {
|
||||
pub struct ChatSharedState {
|
||||
/// The Settings
|
||||
pub settings: Mutex<Settings>,
|
||||
|
||||
/// Connection pool
|
||||
pub pool: Mutex<Pool<ConnectionManager<PgConnection>>>,
|
||||
|
||||
/// A map from generated random ID to session addr
|
||||
sessions: HashMap<ConnectionId, SessionInfo>,
|
||||
sessions: Mutex<HashMap<ConnectionId, SessionInfo>>,
|
||||
|
||||
/// A map from post_id to set of connectionIDs
|
||||
post_rooms: HashMap<PostId, HashSet<ConnectionId>>,
|
||||
post_rooms: Mutex<HashMap<PostId, HashSet<ConnectionId>>>,
|
||||
|
||||
/// A map from community to set of connectionIDs
|
||||
community_rooms: HashMap<CommunityId, HashSet<ConnectionId>>,
|
||||
community_rooms: Mutex<HashMap<CommunityId, HashSet<ConnectionId>>>,
|
||||
|
||||
/// A map from user id to its connection ID for joined users. Remember a user can have multiple
|
||||
/// sessions (IE clients)
|
||||
user_rooms: HashMap<UserId, HashSet<ConnectionId>>,
|
||||
user_rooms: Mutex<HashMap<UserId, HashSet<ConnectionId>>>,
|
||||
|
||||
/// Rate limiting based on rate type and IP addr
|
||||
rate_limit_buckets: HashMap<RateLimitType, HashMap<IPAddr, RateLimitBucket>>,
|
||||
rate_limit_buckets: Mutex<HashMap<RateLimitType, HashMap<IPAddr, RateLimitBucket>>>,
|
||||
}
|
||||
|
||||
rng: ThreadRng,
|
||||
db: Pool<ConnectionManager<PgConnection>>,
|
||||
impl ChatSharedState {
|
||||
pub fn init() -> Self {
|
||||
|
||||
// Setup Settings
|
||||
let settings = match Settings::init() {
|
||||
Ok(c) => c,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
|
||||
// Set up the r2d2 connection pool
|
||||
let manager = ConnectionManager::<PgConnection>::new(&settings.get_database_url());
|
||||
let pool = Pool::builder()
|
||||
.max_size(settings.database.pool_size)
|
||||
.build(manager)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", settings.get_database_url()));
|
||||
|
||||
ChatSharedState {
|
||||
settings: Mutex::new(settings),
|
||||
pool: Mutex::new(pool),
|
||||
sessions: Mutex::new(HashMap::new()),
|
||||
rate_limit_buckets: Mutex::new(HashMap::new()),
|
||||
post_rooms: Mutex::new(HashMap::new()),
|
||||
community_rooms: Mutex::new(HashMap::new()),
|
||||
user_rooms: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// `ChatServer` manages chat rooms and responsible for coordinating chat
|
||||
/// session.
|
||||
pub struct ChatServer {
|
||||
state: web::Data<ChatSharedState>,
|
||||
}
|
||||
|
||||
impl ChatServer {
|
||||
pub fn startup(db: Pool<ConnectionManager<PgConnection>>) -> ChatServer {
|
||||
pub fn init(state: web::Data<ChatSharedState>) -> Self {
|
||||
ChatServer {
|
||||
sessions: HashMap::new(),
|
||||
rate_limit_buckets: HashMap::new(),
|
||||
post_rooms: HashMap::new(),
|
||||
community_rooms: HashMap::new(),
|
||||
user_rooms: HashMap::new(),
|
||||
rng: rand::thread_rng(),
|
||||
db,
|
||||
state,
|
||||
}
|
||||
}
|
||||
|
||||
fn join_community_room(&mut self, community_id: CommunityId, id: ConnectionId) {
|
||||
fn join_community_room(&self, community_id: CommunityId, id: ConnectionId) {
|
||||
// remove session from all rooms
|
||||
for sessions in self.community_rooms.values_mut() {
|
||||
for sessions in self.state.community_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&id);
|
||||
}
|
||||
|
||||
// Also leave all post rooms
|
||||
// This avoids double messages
|
||||
for sessions in self.post_rooms.values_mut() {
|
||||
for sessions in self.state.post_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&id);
|
||||
}
|
||||
|
||||
// If the room doesn't exist yet
|
||||
if self.community_rooms.get_mut(&community_id).is_none() {
|
||||
self.community_rooms.insert(community_id, HashSet::new());
|
||||
if self.state.community_rooms.lock().unwrap().get_mut(&community_id).is_none() {
|
||||
self.state.community_rooms.lock().unwrap().insert(community_id, HashSet::new());
|
||||
}
|
||||
|
||||
self
|
||||
.state
|
||||
.community_rooms
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_mut(&community_id)
|
||||
.unwrap()
|
||||
.insert(id);
|
||||
}
|
||||
|
||||
fn join_post_room(&mut self, post_id: PostId, id: ConnectionId) {
|
||||
fn join_post_room(&self, post_id: PostId, id: ConnectionId) {
|
||||
// remove session from all rooms
|
||||
for sessions in self.post_rooms.values_mut() {
|
||||
for sessions in self.state.post_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&id);
|
||||
}
|
||||
|
||||
// Also leave all communities
|
||||
// This avoids double messages
|
||||
for sessions in self.community_rooms.values_mut() {
|
||||
for sessions in self.state.community_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&id);
|
||||
}
|
||||
|
||||
// If the room doesn't exist yet
|
||||
if self.post_rooms.get_mut(&post_id).is_none() {
|
||||
self.post_rooms.insert(post_id, HashSet::new());
|
||||
if self.state.post_rooms.lock().unwrap().get_mut(&post_id).is_none() {
|
||||
self.state.post_rooms.lock().unwrap().insert(post_id, HashSet::new());
|
||||
}
|
||||
|
||||
self.post_rooms.get_mut(&post_id).unwrap().insert(id);
|
||||
self.state.post_rooms.lock().unwrap().get_mut(&post_id).unwrap().insert(id);
|
||||
}
|
||||
|
||||
fn join_user_room(&mut self, user_id: UserId, id: ConnectionId) {
|
||||
fn join_user_room(&self, user_id: UserId, id: ConnectionId) {
|
||||
// remove session from all rooms
|
||||
for sessions in self.user_rooms.values_mut() {
|
||||
for sessions in self.state.user_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&id);
|
||||
}
|
||||
|
||||
// If the room doesn't exist yet
|
||||
if self.user_rooms.get_mut(&user_id).is_none() {
|
||||
self.user_rooms.insert(user_id, HashSet::new());
|
||||
if self.state.user_rooms.lock().unwrap().get_mut(&user_id).is_none() {
|
||||
self.state.user_rooms.lock().unwrap().insert(user_id, HashSet::new());
|
||||
}
|
||||
|
||||
self.user_rooms.get_mut(&user_id).unwrap().insert(id);
|
||||
self.state.user_rooms.lock().unwrap().get_mut(&user_id).unwrap().insert(id);
|
||||
}
|
||||
|
||||
fn send_post_room_message(&self, post_id: PostId, message: &str, skip_id: ConnectionId) {
|
||||
if let Some(sessions) = self.post_rooms.get(&post_id) {
|
||||
if let Some(sessions) = self.state.post_rooms.lock().unwrap().get(&post_id) {
|
||||
for id in sessions {
|
||||
if *id != skip_id {
|
||||
if let Some(info) = self.sessions.get(id) {
|
||||
if let Some(info) = self.state.sessions.lock().unwrap().get(id) {
|
||||
let _ = info.addr.do_send(WSMessage(message.to_owned()));
|
||||
}
|
||||
}
|
||||
|
@ -192,10 +228,10 @@ impl ChatServer {
|
|||
message: &str,
|
||||
skip_id: ConnectionId,
|
||||
) {
|
||||
if let Some(sessions) = self.community_rooms.get(&community_id) {
|
||||
if let Some(sessions) = self.state.community_rooms.lock().unwrap().get(&community_id) {
|
||||
for id in sessions {
|
||||
if *id != skip_id {
|
||||
if let Some(info) = self.sessions.get(id) {
|
||||
if let Some(info) = self.state.sessions.lock().unwrap().get(id) {
|
||||
let _ = info.addr.do_send(WSMessage(message.to_owned()));
|
||||
}
|
||||
}
|
||||
|
@ -204,10 +240,10 @@ impl ChatServer {
|
|||
}
|
||||
|
||||
fn send_user_room_message(&self, user_id: UserId, message: &str, skip_id: ConnectionId) {
|
||||
if let Some(sessions) = self.user_rooms.get(&user_id) {
|
||||
if let Some(sessions) = self.state.user_rooms.lock().unwrap().get(&user_id) {
|
||||
for id in sessions {
|
||||
if *id != skip_id {
|
||||
if let Some(info) = self.sessions.get(id) {
|
||||
if let Some(info) = self.state.sessions.lock().unwrap().get(id) {
|
||||
let _ = info.addr.do_send(WSMessage(message.to_owned()));
|
||||
}
|
||||
}
|
||||
|
@ -216,9 +252,9 @@ impl ChatServer {
|
|||
}
|
||||
|
||||
fn send_all_message(&self, message: &str, skip_id: ConnectionId) {
|
||||
for id in self.sessions.keys() {
|
||||
for id in self.state.sessions.lock().unwrap().keys() {
|
||||
if *id != skip_id {
|
||||
if let Some(info) = self.sessions.get(id) {
|
||||
if let Some(info) = self.state.sessions.lock().unwrap().get(id) {
|
||||
let _ = info.addr.do_send(WSMessage(message.to_owned()));
|
||||
}
|
||||
}
|
||||
|
@ -287,47 +323,47 @@ impl ChatServer {
|
|||
to_json_string(&user_operation, post)
|
||||
}
|
||||
|
||||
fn check_rate_limit_register(&mut self, id: usize, check_only: bool) -> Result<(), Error> {
|
||||
fn check_rate_limit_register(&self, id: usize, check_only: bool) -> Result<(), Error> {
|
||||
self.check_rate_limit_full(
|
||||
RateLimitType::Register,
|
||||
id,
|
||||
Settings::get().rate_limit.register,
|
||||
Settings::get().rate_limit.register_per_second,
|
||||
self.state.settings.lock().unwrap().rate_limit.register,
|
||||
self.state.settings.lock().unwrap().rate_limit.register_per_second,
|
||||
check_only,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_rate_limit_post(&mut self, id: usize, check_only: bool) -> Result<(), Error> {
|
||||
fn check_rate_limit_post(&self, id: usize, check_only: bool) -> Result<(), Error> {
|
||||
self.check_rate_limit_full(
|
||||
RateLimitType::Post,
|
||||
id,
|
||||
Settings::get().rate_limit.post,
|
||||
Settings::get().rate_limit.post_per_second,
|
||||
self.state.settings.lock().unwrap().rate_limit.post,
|
||||
self.state.settings.lock().unwrap().rate_limit.post_per_second,
|
||||
check_only,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_rate_limit_message(&mut self, id: usize, check_only: bool) -> Result<(), Error> {
|
||||
fn check_rate_limit_message(&self, id: usize, check_only: bool) -> Result<(), Error> {
|
||||
self.check_rate_limit_full(
|
||||
RateLimitType::Message,
|
||||
id,
|
||||
Settings::get().rate_limit.message,
|
||||
Settings::get().rate_limit.message_per_second,
|
||||
self.state.settings.lock().unwrap().rate_limit.message,
|
||||
self.state.settings.lock().unwrap().rate_limit.message_per_second,
|
||||
check_only,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn check_rate_limit_full(
|
||||
&mut self,
|
||||
&self,
|
||||
type_: RateLimitType,
|
||||
id: usize,
|
||||
rate: i32,
|
||||
per: i32,
|
||||
check_only: bool,
|
||||
) -> Result<(), Error> {
|
||||
if let Some(info) = self.sessions.get(&id) {
|
||||
if let Some(bucket) = self.rate_limit_buckets.get_mut(&type_) {
|
||||
if let Some(info) = self.state.sessions.lock().unwrap().get(&id) {
|
||||
if let Some(bucket) = self.state.rate_limit_buckets.lock().unwrap().get_mut(&type_) {
|
||||
if let Some(rate_limit) = bucket.get_mut(&info.ip) {
|
||||
let current = SystemTime::now();
|
||||
let time_passed = current.duration_since(rate_limit.last_checked)?.as_secs() as f64;
|
||||
|
@ -376,7 +412,7 @@ impl ChatServer {
|
|||
impl Actor for ChatServer {
|
||||
/// We are going to use simple Context, we just need ability to communicate
|
||||
/// with other actors.
|
||||
type Context = Context<Self>;
|
||||
type Context = SyncContext<Self>;
|
||||
}
|
||||
|
||||
/// Handler for Connect message.
|
||||
|
@ -385,12 +421,12 @@ impl Actor for ChatServer {
|
|||
impl Handler<Connect> for ChatServer {
|
||||
type Result = usize;
|
||||
|
||||
fn handle(&mut self, msg: Connect, _ctx: &mut Context<Self>) -> Self::Result {
|
||||
fn handle(&mut self, msg: Connect, _ctx: &mut SyncContext<Self>) -> Self::Result {
|
||||
// register session with random id
|
||||
let id = self.rng.gen::<usize>();
|
||||
let id = rand::thread_rng().gen::<usize>();
|
||||
info!("{} joined", &msg.ip);
|
||||
|
||||
self.sessions.insert(
|
||||
self.state.sessions.lock().unwrap().insert(
|
||||
id,
|
||||
SessionInfo {
|
||||
addr: msg.addr,
|
||||
|
@ -399,13 +435,16 @@ impl Handler<Connect> for ChatServer {
|
|||
);
|
||||
|
||||
for rate_limit_type in RateLimitType::iter() {
|
||||
if self.rate_limit_buckets.get(&rate_limit_type).is_none() {
|
||||
if self.state.rate_limit_buckets.lock().unwrap().get(&rate_limit_type).is_none() {
|
||||
self
|
||||
.state
|
||||
.rate_limit_buckets
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(rate_limit_type, HashMap::new());
|
||||
}
|
||||
|
||||
if let Some(bucket) = self.rate_limit_buckets.get_mut(&rate_limit_type) {
|
||||
if let Some(bucket) = self.state.rate_limit_buckets.lock().unwrap().get_mut(&rate_limit_type) {
|
||||
if bucket.get(&msg.ip).is_none() {
|
||||
bucket.insert(
|
||||
msg.ip.to_owned(),
|
||||
|
@ -426,18 +465,18 @@ impl Handler<Connect> for ChatServer {
|
|||
impl Handler<Disconnect> for ChatServer {
|
||||
type Result = ();
|
||||
|
||||
fn handle(&mut self, msg: Disconnect, _: &mut Context<Self>) {
|
||||
fn handle(&mut self, msg: Disconnect, _: &mut SyncContext<Self>) {
|
||||
// Remove connections from sessions and all 3 scopes
|
||||
if self.sessions.remove(&msg.id).is_some() {
|
||||
for sessions in self.user_rooms.values_mut() {
|
||||
if self.state.sessions.lock().unwrap().remove(&msg.id).is_some() {
|
||||
for sessions in self.state.user_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&msg.id);
|
||||
}
|
||||
|
||||
for sessions in self.post_rooms.values_mut() {
|
||||
for sessions in self.state.post_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&msg.id);
|
||||
}
|
||||
|
||||
for sessions in self.community_rooms.values_mut() {
|
||||
for sessions in self.state.community_rooms.lock().unwrap().values_mut() {
|
||||
sessions.remove(&msg.id);
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +487,7 @@ impl Handler<Disconnect> for ChatServer {
|
|||
impl Handler<StandardMessage> for ChatServer {
|
||||
type Result = MessageResult<StandardMessage>;
|
||||
|
||||
fn handle(&mut self, msg: StandardMessage, _: &mut Context<Self>) -> Self::Result {
|
||||
fn handle(&mut self, msg: StandardMessage, _: &mut SyncContext<Self>) -> Self::Result {
|
||||
match parse_json_message(self, msg) {
|
||||
Ok(m) => {
|
||||
info!("Message Sent: {}", m);
|
||||
|
@ -483,6 +522,7 @@ fn do_user_operation<'a, Data, Response>(
|
|||
op: UserOperation,
|
||||
data: &str,
|
||||
conn: &PooledConnection<ConnectionManager<PgConnection>>,
|
||||
settings: &Settings,
|
||||
) -> Result<String, Error>
|
||||
where
|
||||
for<'de> Data: Deserialize<'de> + 'a,
|
||||
|
@ -490,7 +530,7 @@ where
|
|||
Oper<Data>: Perform<Response>,
|
||||
{
|
||||
let parsed_data: Data = serde_json::from_str(data)?;
|
||||
let res = Oper::new(parsed_data).perform(&conn)?;
|
||||
let res = Oper::new(parsed_data).perform(&conn, &settings)?;
|
||||
to_json_string(&op, &res)
|
||||
}
|
||||
|
||||
|
@ -501,7 +541,8 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
message: "Unknown op type".to_string(),
|
||||
})?;
|
||||
|
||||
let conn = chat.db.get()?;
|
||||
let conn = chat.state.pool.lock().unwrap().get()?;
|
||||
let settings = chat.state.settings.lock().unwrap();
|
||||
|
||||
let user_operation: UserOperation = UserOperation::from_str(&op)?;
|
||||
|
||||
|
@ -512,54 +553,54 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
chat.check_rate_limit_message(msg.id, false)?;
|
||||
|
||||
match user_operation {
|
||||
UserOperation::Login => do_user_operation::<Login, LoginResponse>(user_operation, data, &conn),
|
||||
UserOperation::Login => do_user_operation::<Login, LoginResponse>(user_operation, data, &conn, &settings),
|
||||
UserOperation::Register => {
|
||||
chat.check_rate_limit_register(msg.id, true)?;
|
||||
let register: Register = serde_json::from_str(data)?;
|
||||
let res = Oper::new(register).perform(&conn)?;
|
||||
let res = Oper::new(register).perform(&conn, &settings)?;
|
||||
chat.check_rate_limit_register(msg.id, false)?;
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::GetUserDetails => {
|
||||
do_user_operation::<GetUserDetails, GetUserDetailsResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<GetUserDetails, GetUserDetailsResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::SaveUserSettings => {
|
||||
do_user_operation::<SaveUserSettings, LoginResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<SaveUserSettings, LoginResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::AddAdmin => {
|
||||
let add_admin: AddAdmin = serde_json::from_str(data)?;
|
||||
let res = Oper::new(add_admin).perform(&conn)?;
|
||||
let res = Oper::new(add_admin).perform(&conn, &settings)?;
|
||||
let res_str = to_json_string(&user_operation, &res)?;
|
||||
chat.send_all_message(&res_str, msg.id);
|
||||
Ok(res_str)
|
||||
}
|
||||
UserOperation::BanUser => {
|
||||
let ban_user: BanUser = serde_json::from_str(data)?;
|
||||
let res = Oper::new(ban_user).perform(&conn)?;
|
||||
let res = Oper::new(ban_user).perform(&conn, &settings)?;
|
||||
let res_str = to_json_string(&user_operation, &res)?;
|
||||
chat.send_all_message(&res_str, msg.id);
|
||||
Ok(res_str)
|
||||
}
|
||||
UserOperation::GetReplies => {
|
||||
do_user_operation::<GetReplies, GetRepliesResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<GetReplies, GetRepliesResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::GetUserMentions => {
|
||||
do_user_operation::<GetUserMentions, GetUserMentionsResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<GetUserMentions, GetUserMentionsResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::EditUserMention => {
|
||||
do_user_operation::<EditUserMention, UserMentionResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<EditUserMention, UserMentionResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::MarkAllAsRead => {
|
||||
do_user_operation::<MarkAllAsRead, GetRepliesResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<MarkAllAsRead, GetRepliesResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::GetCommunity => {
|
||||
let get_community: GetCommunity = serde_json::from_str(data)?;
|
||||
let mut res = Oper::new(get_community).perform(&conn)?;
|
||||
let mut res = Oper::new(get_community).perform(&conn, &settings)?;
|
||||
let community_id = res.community.id;
|
||||
|
||||
chat.join_community_room(community_id, msg.id);
|
||||
|
||||
res.online = if let Some(community_users) = chat.community_rooms.get(&community_id) {
|
||||
res.online = if let Some(community_users) = chat.state.community_rooms.lock().unwrap().get(&community_id) {
|
||||
community_users.len()
|
||||
} else {
|
||||
0
|
||||
|
@ -568,18 +609,18 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::ListCommunities => {
|
||||
do_user_operation::<ListCommunities, ListCommunitiesResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<ListCommunities, ListCommunitiesResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::CreateCommunity => {
|
||||
chat.check_rate_limit_register(msg.id, true)?;
|
||||
let create_community: CreateCommunity = serde_json::from_str(data)?;
|
||||
let res = Oper::new(create_community).perform(&conn)?;
|
||||
let res = Oper::new(create_community).perform(&conn, &settings)?;
|
||||
chat.check_rate_limit_register(msg.id, false)?;
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::EditCommunity => {
|
||||
let edit_community: EditCommunity = serde_json::from_str(data)?;
|
||||
let res = Oper::new(edit_community).perform(&conn)?;
|
||||
let res = Oper::new(edit_community).perform(&conn, &settings)?;
|
||||
let mut community_sent: CommunityResponse = res.clone();
|
||||
community_sent.community.user_id = None;
|
||||
community_sent.community.subscribed = None;
|
||||
|
@ -588,16 +629,16 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::FollowCommunity => {
|
||||
do_user_operation::<FollowCommunity, CommunityResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<FollowCommunity, CommunityResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::GetFollowedCommunities => do_user_operation::<
|
||||
GetFollowedCommunities,
|
||||
GetFollowedCommunitiesResponse,
|
||||
>(user_operation, data, &conn),
|
||||
>(user_operation, data, &conn, &settings),
|
||||
UserOperation::BanFromCommunity => {
|
||||
let ban_from_community: BanFromCommunity = serde_json::from_str(data)?;
|
||||
let community_id = ban_from_community.community_id;
|
||||
let res = Oper::new(ban_from_community).perform(&conn)?;
|
||||
let res = Oper::new(ban_from_community).perform(&conn, &settings)?;
|
||||
let res_str = to_json_string(&user_operation, &res)?;
|
||||
chat.send_community_room_message(community_id, &res_str, msg.id);
|
||||
Ok(res_str)
|
||||
|
@ -605,21 +646,21 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
UserOperation::AddModToCommunity => {
|
||||
let mod_add_to_community: AddModToCommunity = serde_json::from_str(data)?;
|
||||
let community_id = mod_add_to_community.community_id;
|
||||
let res = Oper::new(mod_add_to_community).perform(&conn)?;
|
||||
let res = Oper::new(mod_add_to_community).perform(&conn, &settings)?;
|
||||
let res_str = to_json_string(&user_operation, &res)?;
|
||||
chat.send_community_room_message(community_id, &res_str, msg.id);
|
||||
Ok(res_str)
|
||||
}
|
||||
UserOperation::ListCategories => {
|
||||
do_user_operation::<ListCategories, ListCategoriesResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<ListCategories, ListCategoriesResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::GetPost => {
|
||||
let get_post: GetPost = serde_json::from_str(data)?;
|
||||
let post_id = get_post.id;
|
||||
chat.join_post_room(post_id, msg.id);
|
||||
let mut res = Oper::new(get_post).perform(&conn)?;
|
||||
let mut res = Oper::new(get_post).perform(&conn, &settings)?;
|
||||
|
||||
res.online = if let Some(post_users) = chat.post_rooms.get(&post_id) {
|
||||
res.online = if let Some(post_users) = chat.state.post_rooms.lock().unwrap().get(&post_id) {
|
||||
post_users.len()
|
||||
} else {
|
||||
0
|
||||
|
@ -633,7 +674,7 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
// 0 is the "all" community
|
||||
chat.join_community_room(0, msg.id);
|
||||
}
|
||||
let res = Oper::new(get_posts).perform(&conn)?;
|
||||
let res = Oper::new(get_posts).perform(&conn, &settings)?;
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::GetComments => {
|
||||
|
@ -642,118 +683,123 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
|||
// 0 is the "all" community
|
||||
chat.join_community_room(0, msg.id);
|
||||
}
|
||||
let res = Oper::new(get_comments).perform(&conn)?;
|
||||
let res = Oper::new(get_comments).perform(&conn, &settings)?;
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::CreatePost => {
|
||||
chat.check_rate_limit_post(msg.id, true)?;
|
||||
let create_post: CreatePost = serde_json::from_str(data)?;
|
||||
let res = Oper::new(create_post).perform(&conn)?;
|
||||
let res = Oper::new(create_post).perform(&conn, &settings)?;
|
||||
chat.check_rate_limit_post(msg.id, false)?;
|
||||
|
||||
chat.post_sends(UserOperation::CreatePost, res, msg.id)
|
||||
}
|
||||
UserOperation::CreatePostLike => {
|
||||
let create_post_like: CreatePostLike = serde_json::from_str(data)?;
|
||||
let res = Oper::new(create_post_like).perform(&conn)?;
|
||||
let res = Oper::new(create_post_like).perform(&conn, &settings)?;
|
||||
|
||||
chat.post_sends(UserOperation::CreatePostLike, res, msg.id)
|
||||
}
|
||||
UserOperation::EditPost => {
|
||||
let edit_post: EditPost = serde_json::from_str(data)?;
|
||||
let res = Oper::new(edit_post).perform(&conn)?;
|
||||
let res = Oper::new(edit_post).perform(&conn, &settings)?;
|
||||
|
||||
chat.post_sends(UserOperation::EditPost, res, msg.id)
|
||||
}
|
||||
UserOperation::SavePost => {
|
||||
do_user_operation::<SavePost, PostResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<SavePost, PostResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::CreateComment => {
|
||||
let create_comment: CreateComment = serde_json::from_str(data)?;
|
||||
let res = Oper::new(create_comment).perform(&conn)?;
|
||||
let res = Oper::new(create_comment).perform(&conn, &settings)?;
|
||||
|
||||
chat.comment_sends(UserOperation::CreateComment, res, msg.id)
|
||||
}
|
||||
UserOperation::EditComment => {
|
||||
let edit_comment: EditComment = serde_json::from_str(data)?;
|
||||
let res = Oper::new(edit_comment).perform(&conn)?;
|
||||
let res = Oper::new(edit_comment).perform(&conn, &settings)?;
|
||||
|
||||
chat.comment_sends(UserOperation::EditComment, res, msg.id)
|
||||
}
|
||||
UserOperation::SaveComment => {
|
||||
do_user_operation::<SaveComment, CommentResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<SaveComment, CommentResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::CreateCommentLike => {
|
||||
let create_comment_like: CreateCommentLike = serde_json::from_str(data)?;
|
||||
let res = Oper::new(create_comment_like).perform(&conn)?;
|
||||
let res = Oper::new(create_comment_like).perform(&conn, &settings)?;
|
||||
|
||||
chat.comment_sends(UserOperation::CreateCommentLike, res, msg.id)
|
||||
}
|
||||
UserOperation::GetModlog => {
|
||||
do_user_operation::<GetModlog, GetModlogResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<GetModlog, GetModlogResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::CreateSite => {
|
||||
do_user_operation::<CreateSite, SiteResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<CreateSite, SiteResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::EditSite => {
|
||||
let edit_site: EditSite = serde_json::from_str(data)?;
|
||||
let res = Oper::new(edit_site).perform(&conn)?;
|
||||
let res = Oper::new(edit_site).perform(&conn, &settings)?;
|
||||
let res_str = to_json_string(&user_operation, &res)?;
|
||||
chat.send_all_message(&res_str, msg.id);
|
||||
Ok(res_str)
|
||||
}
|
||||
UserOperation::GetSite => {
|
||||
let get_site: GetSite = serde_json::from_str(data)?;
|
||||
let mut res = Oper::new(get_site).perform(&conn)?;
|
||||
res.online = chat.sessions.len();
|
||||
let mut res = Oper::new(get_site).perform(&conn, &settings)?;
|
||||
res.online = chat.state.sessions.lock().unwrap().len();
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::GetSiteConfig => {
|
||||
let get_site_config: GetSiteConfig = serde_json::from_str(data)?;
|
||||
let res = Oper::new(get_site_config).perform(&conn)?;
|
||||
let res = Oper::new(get_site_config).perform(&conn, &settings)?;
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::SaveSiteConfig => {
|
||||
let save_site_config: SaveSiteConfig = serde_json::from_str(data)?;
|
||||
let res = Oper::new(save_site_config).perform(&conn)?;
|
||||
let res = Oper::new(save_site_config).perform(&conn, &settings)?;
|
||||
let mut new_settings = chat.state.settings.lock().unwrap();
|
||||
*new_settings = match Settings::init() {
|
||||
Ok(c) => c,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
UserOperation::Search => {
|
||||
do_user_operation::<Search, SearchResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<Search, SearchResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::TransferCommunity => {
|
||||
do_user_operation::<TransferCommunity, GetCommunityResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<TransferCommunity, GetCommunityResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::TransferSite => {
|
||||
do_user_operation::<TransferSite, GetSiteResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<TransferSite, GetSiteResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::DeleteAccount => {
|
||||
do_user_operation::<DeleteAccount, LoginResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<DeleteAccount, LoginResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::PasswordReset => {
|
||||
do_user_operation::<PasswordReset, PasswordResetResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<PasswordReset, PasswordResetResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::PasswordChange => {
|
||||
do_user_operation::<PasswordChange, LoginResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<PasswordChange, LoginResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::CreatePrivateMessage => {
|
||||
let create_private_message: CreatePrivateMessage = serde_json::from_str(data)?;
|
||||
let recipient_id = create_private_message.recipient_id;
|
||||
let res = Oper::new(create_private_message).perform(&conn)?;
|
||||
let res = Oper::new(create_private_message).perform(&conn, &settings)?;
|
||||
let res_str = to_json_string(&user_operation, &res)?;
|
||||
|
||||
chat.send_user_room_message(recipient_id, &res_str, msg.id);
|
||||
Ok(res_str)
|
||||
}
|
||||
UserOperation::EditPrivateMessage => {
|
||||
do_user_operation::<EditPrivateMessage, PrivateMessageResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<EditPrivateMessage, PrivateMessageResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::GetPrivateMessages => {
|
||||
do_user_operation::<GetPrivateMessages, PrivateMessagesResponse>(user_operation, data, &conn)
|
||||
do_user_operation::<GetPrivateMessages, PrivateMessagesResponse>(user_operation, data, &conn, &settings)
|
||||
}
|
||||
UserOperation::UserJoin => {
|
||||
let user_join: UserJoin = serde_json::from_str(data)?;
|
||||
let res = Oper::new(user_join).perform(&conn)?;
|
||||
let res = Oper::new(user_join).perform(&conn, &settings)?;
|
||||
chat.join_user_room(res.user_id, msg.id);
|
||||
to_json_string(&user_operation, &res)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue