2nd pass. JWT now uses local_user_id

This commit is contained in:
Dessalines 2021-03-11 17:47:44 -05:00
parent 7d04f371a5
commit 7c039340ed
15 changed files with 82 additions and 93 deletions

View file

@ -103,11 +103,9 @@ pub(crate) async fn get_local_user_view_from_jwt(
Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
};
let person_id = claims.id;
let local_user_view = blocking(pool, move |conn| {
LocalUserView::read_person(conn, person_id)
})
.await??;
let local_user_id = claims.id;
let local_user_view =
blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
// Check for a site ban
if local_user_view.person.banned {
return Err(ApiError::err("site_ban").into());
@ -133,9 +131,9 @@ pub(crate) async fn get_local_user_settings_view_from_jwt(
Ok(claims) => claims.claims,
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
};
let person_id = claims.id;
let local_user_id = claims.id;
let local_user_view = blocking(pool, move |conn| {
LocalUserSettingsView::read(conn, person_id)
LocalUserSettingsView::read(conn, local_user_id)
})
.await??;
// Check for a site ban
@ -185,21 +183,21 @@ pub(crate) async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result
/// or if a community_id is supplied validates the user is a moderator
/// of that community and returns the community id in a vec
///
/// * `user_id` - the user id of the moderator
/// * `person_id` - the person id of the moderator
/// * `community_id` - optional community id to check for moderator privileges
/// * `pool` - the diesel db pool
pub(crate) async fn collect_moderated_communities(
user_id: i32,
person_id: i32,
community_id: Option<i32>,
pool: &DbPool,
) -> Result<Vec<i32>, LemmyError> {
if let Some(community_id) = community_id {
// if the user provides a community_id, just check for mod/admin privileges
is_mod_or_admin(pool, user_id, community_id).await?;
is_mod_or_admin(pool, person_id, community_id).await?;
Ok(vec![community_id])
} else {
let ids = blocking(pool, move |conn: &'_ _| {
CommunityModerator::get_person_moderated_communities(conn, user_id)
CommunityModerator::get_person_moderated_communities(conn, person_id)
})
.await??;
Ok(ids)

View file

@ -129,7 +129,7 @@ impl Perform for Login {
// Return the jwt
Ok(LoginResponse {
jwt: Claims::jwt(local_user_view.person.id, Settings::get().hostname())?,
jwt: Claims::jwt(local_user_view.local_user.id, Settings::get().hostname())?,
})
}
}
@ -243,7 +243,7 @@ impl Perform for Register {
send_notifications_to_email: Some(false),
};
match blocking(context.pool(), move |conn| {
let inserted_local_user = match blocking(context.pool(), move |conn| {
LocalUser::register(conn, &local_user_form)
})
.await?
@ -332,7 +332,7 @@ impl Perform for Register {
// Return the jwt
Ok(LoginResponse {
jwt: Claims::jwt(inserted_person.id, Settings::get().hostname())?,
jwt: Claims::jwt(inserted_local_user.id, Settings::get().hostname())?,
})
}
}
@ -479,7 +479,7 @@ impl Perform for SaveUserSettings {
Person::update(conn, person_id, &person_form)
})
.await?;
let updated_person: Person = match person_res {
let _updated_person: Person = match person_res {
Ok(p) => p,
Err(_) => {
return Err(ApiError::err("user_already_exists").into());
@ -505,8 +505,8 @@ impl Perform for SaveUserSettings {
LocalUser::update(conn, local_user_id, &local_user_form)
})
.await?;
match local_user_res {
Ok(user) => user,
let updated_local_user = match local_user_res {
Ok(u) => u,
Err(e) => {
let err_type = if e.to_string()
== "duplicate key value violates unique constraint \"local_user_email_key\""
@ -522,7 +522,7 @@ impl Perform for SaveUserSettings {
// Return the jwt
Ok(LoginResponse {
jwt: Claims::jwt(updated_person.id, Settings::get().hostname())?,
jwt: Claims::jwt(updated_local_user.id, Settings::get().hostname())?,
})
}
}

View file

@ -21,8 +21,7 @@ impl Perform for UserJoin {
if let Some(ws_id) = websocket_id {
context.chat_server().do_send(JoinUserRoom {
// TODO this should probably be the local_user_id
user_id: local_user_view.person.id,
local_user_id: local_user_view.local_user.id,
id: ws_id,
});
}

View file

@ -90,7 +90,7 @@ fn do_send_local_notifs(
// TODO
// At some point, make it so you can't tag the parent creator either
// This can cause two notifications, one for reply and the other for mention
recipient_ids.push(mention_user_view.person.id);
recipient_ids.push(mention_user_view.local_user.id);
let user_mention_form = PersonMentionForm {
recipient_id: mention_user_view.person.id,
@ -102,7 +102,7 @@ fn do_send_local_notifs(
// Let the uniqueness handle this fail
PersonMention::create(&conn, &user_mention_form).ok();
// Send an email to those users that have notifications on
// Send an email to those local users that have notifications on
if do_send_email && mention_user_view.local_user.send_notifications_to_email {
send_email_to_user(
mention_user_view,
@ -121,7 +121,7 @@ fn do_send_local_notifs(
if parent_comment.creator_id != person.id {
if let Ok(parent_user_view) = LocalUserView::read_person(&conn, parent_comment.creator_id)
{
recipient_ids.push(parent_user_view.person.id);
recipient_ids.push(parent_user_view.local_user.id);
if do_send_email && parent_user_view.local_user.send_notifications_to_email {
send_email_to_user(
@ -139,7 +139,7 @@ fn do_send_local_notifs(
None => {
if post.creator_id != person.id {
if let Ok(parent_user_view) = LocalUserView::read_person(&conn, post.creator_id) {
recipient_ids.push(parent_user_view.person.id);
recipient_ids.push(parent_user_view.local_user.id);
if do_send_email && parent_user_view.local_user.send_notifications_to_email {
send_email_to_user(

View file

@ -47,7 +47,7 @@ pub trait Followable<T> {
fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn follow_accepted(conn: &PgConnection, community_id: i32, user_id: i32) -> Result<Self, Error>
fn follow_accepted(conn: &PgConnection, community_id: i32, person_id: i32) -> Result<Self, Error>
where
Self: Sized;
fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error>
@ -69,7 +69,7 @@ pub trait Likeable<T> {
fn like(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn remove(conn: &PgConnection, user_id: i32, item_id: i32) -> Result<usize, Error>
fn remove(conn: &PgConnection, person_id: i32, item_id: i32) -> Result<usize, Error>
where
Self: Sized;
}

View file

@ -1,9 +1,9 @@
use crate::{Crud, ToSafeSettings};
use crate::Crud;
use bcrypt::{hash, DEFAULT_COST};
use diesel::{dsl::*, result::Error, *};
use lemmy_db_schema::{
schema::local_user::dsl::*,
source::local_user::{LocalUser, LocalUserForm, LocalUserSettings},
source::local_user::{LocalUser, LocalUserForm},
};
mod safe_type {
@ -70,7 +70,6 @@ pub trait LocalUser_ {
new_password: &str,
) -> Result<LocalUser, Error>;
fn add_admin(conn: &PgConnection, local_user_id: i32, added: bool) -> Result<LocalUser, Error>;
fn find_by_person(conn: &PgConnection, from_person_id: i32) -> Result<LocalUser, Error>;
}
impl LocalUser_ for LocalUser {
@ -83,7 +82,6 @@ impl LocalUser_ for LocalUser {
Self::create(&conn, &edited_user)
}
// TODO do more individual updates like these
fn update_password(
conn: &PgConnection,
local_user_id: i32,
@ -96,19 +94,11 @@ impl LocalUser_ for LocalUser {
.get_result::<Self>(conn)
}
// TODO is this used?
fn add_admin(conn: &PgConnection, local_user_id: i32, added: bool) -> Result<Self, Error> {
diesel::update(local_user.find(local_user_id))
.set(admin.eq(added))
.get_result::<Self>(conn)
}
// TODO is this used?
fn find_by_person(conn: &PgConnection, for_person_id: i32) -> Result<LocalUser, Error> {
local_user
.filter(person_id.eq(for_person_id))
.first::<LocalUser>(conn)
}
}
impl Crud<LocalUserForm> for LocalUser {
@ -129,18 +119,3 @@ impl Crud<LocalUserForm> for LocalUser {
.get_result::<Self>(conn)
}
}
// TODO is this used?
pub trait LocalUserSettings_ {
fn read(conn: &PgConnection, user_id: i32) -> Result<LocalUserSettings, Error>;
}
// TODO is this used?
impl LocalUserSettings_ for LocalUserSettings {
fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
local_user
.select(LocalUser::safe_settings_columns_tuple())
.find(user_id)
.first::<Self>(conn)
}
}

View file

@ -192,7 +192,6 @@ impl Person_ for Person {
.get_result::<Self>(conn)
}
// TODO is this used?
fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
person
.filter(deleted.eq(false))

View file

@ -26,7 +26,7 @@ pub struct Person {
pub shared_inbox_url: Option<DbUrl>,
}
/// A safe representation of user, without the sensitive info
/// A safe representation of person, without the sensitive info
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "person"]
pub struct PersonSafe {

View file

@ -367,7 +367,7 @@ impl<'a> CommentQueryBuilder<'a> {
query = match self.listing_type {
// ListingType::Subscribed => query.filter(community_follower::subscribed.eq(true)),
ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)),
ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
ListingType::Local => query.filter(community::local.eq(true)),
_ => query,
};

View file

@ -11,42 +11,60 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct LocalUserView {
pub local_user: LocalUser,
pub person: Person,
pub counts: PersonAggregates,
pub local_user: LocalUser,
}
type LocalUserViewTuple = (Person, PersonAggregates, LocalUser);
type LocalUserViewTuple = (LocalUser, Person, PersonAggregates);
impl LocalUserView {
pub fn read_person(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
let (person, counts, local_user) = person::table
.find(person_id)
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
pub fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.find(local_user_id)
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
local_user,
person,
counts,
})
}
pub fn read_person(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.filter(person::id.eq(person_id))
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
local_user,
person,
counts,
})
}
// TODO check where this is used
pub fn read_from_name(conn: &PgConnection, name: &str) -> Result<Self, Error> {
let (person, counts, local_user) = person::table
let (local_user, person, counts) = local_user::table
.filter(person::name.eq(name))
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
@ -57,18 +75,18 @@ impl LocalUserView {
}
pub fn find_by_email_or_name(conn: &PgConnection, name_or_email: &str) -> Result<Self, Error> {
let (person, counts, local_user) = person::table
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
let (local_user, person, counts) = local_user::table
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.filter(
person::name
.ilike(name_or_email)
.or(local_user::email.ilike(name_or_email)),
)
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
@ -79,14 +97,14 @@ impl LocalUserView {
}
pub fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<Self, Error> {
let (person, counts, local_user) = person::table
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
let (local_user, person, counts) = local_user::table
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.filter(local_user::email.eq(from_email))
.select((
local_user::all_columns,
person::all_columns,
person_aggregates::all_columns,
local_user::all_columns,
))
.first::<LocalUserViewTuple>(conn)?;
Ok(Self {
@ -99,23 +117,23 @@ impl LocalUserView {
#[derive(Debug, Serialize, Clone)]
pub struct LocalUserSettingsView {
pub local_user: LocalUserSettings,
pub person: PersonSafe,
pub counts: PersonAggregates,
pub local_user: LocalUserSettings,
}
type LocalUserSettingsViewTuple = (PersonSafe, PersonAggregates, LocalUserSettings);
type LocalUserSettingsViewTuple = (LocalUserSettings, PersonSafe, PersonAggregates);
impl LocalUserSettingsView {
pub fn read(conn: &PgConnection, person_id: i32) -> Result<Self, Error> {
let (person, counts, local_user) = person::table
.find(person_id)
.inner_join(person_aggregates::table)
.inner_join(local_user::table)
pub fn read(conn: &PgConnection, local_user_id: i32) -> Result<Self, Error> {
let (local_user, person, counts) = local_user::table
.find(local_user_id)
.inner_join(person::table)
.inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
.select((
LocalUser::safe_settings_columns_tuple(),
Person::safe_columns_tuple(),
person_aggregates::all_columns,
LocalUser::safe_settings_columns_tuple(),
))
.first::<LocalUserSettingsViewTuple>(conn)?;
Ok(Self {

View file

@ -7,7 +7,7 @@ use lemmy_utils::{
settings::structs::Settings,
LemmyError,
WEBFINGER_COMMUNITY_REGEX,
WEBFINGER_USER_REGEX,
WEBFINGER_USERNAME_REGEX,
};
use lemmy_websocket::LemmyContext;
use serde::Deserialize;
@ -41,7 +41,7 @@ async fn get_webfinger_response(
.map(|c| c.get(1))
.flatten();
let user_regex_parsed = WEBFINGER_USER_REGEX
let username_regex_parsed = WEBFINGER_USERNAME_REGEX
.captures(&info.resource)
.map(|c| c.get(1))
.flatten();
@ -55,9 +55,9 @@ async fn get_webfinger_response(
.await?
.map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))?
.actor_id
} else if let Some(person_name) = user_regex_parsed {
} else if let Some(person_name) = username_regex_parsed {
let person_name = person_name.as_str().to_owned();
// Make sure the requested user exists.
// Make sure the requested person exists.
blocking(context.pool(), move |conn| {
Person::find_by_name(conn, &person_name)
})

View file

@ -23,9 +23,9 @@ impl Claims {
)
}
pub fn jwt(user_id: i32, hostname: String) -> Result<Jwt, jsonwebtoken::errors::Error> {
pub fn jwt(local_user_id: i32, hostname: String) -> Result<Jwt, jsonwebtoken::errors::Error> {
let my_claims = Claims {
id: user_id,
id: local_user_id,
iss: hostname,
};
encode(

View file

@ -87,7 +87,7 @@ lazy_static! {
Settings::get().hostname()
))
.expect("compile webfinger regex");
pub static ref WEBFINGER_USER_REGEX: Regex = Regex::new(&format!(
pub static ref WEBFINGER_USERNAME_REGEX: Regex = Regex::new(&format!(
"^acct:([a-z0-9_]{{3, 20}})@{}$",
Settings::get().hostname()
))

View file

@ -155,7 +155,7 @@ impl Handler<JoinUserRoom> for ChatServer {
type Result = ();
fn handle(&mut self, msg: JoinUserRoom, _: &mut Context<Self>) {
self.join_user_room(msg.user_id, msg.id).ok();
self.join_user_room(msg.local_user_id, msg.id).ok();
}
}

View file

@ -91,7 +91,7 @@ pub struct SendComment {
#[derive(Message)]
#[rtype(result = "()")]
pub struct JoinUserRoom {
pub user_id: UserId,
pub local_user_id: UserId,
pub id: ConnectionId,
}