fix: profile shows only own reviews, federation display name in community
- diary API accepts user_id filter, profile page passes it - movie social feed joins ap_remote_actors for handle resolution - COALESCE prefers actor handle for remote reviews, email for local
This commit is contained in:
@@ -343,7 +343,8 @@ impl DiaryRepository for PostgresDiaryRepository {
|
|||||||
to_char(r.created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS') AS created_at,
|
to_char(r.created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS') AS created_at,
|
||||||
r.remote_actor_url,
|
r.remote_actor_url,
|
||||||
r.watch_medium,
|
r.watch_medium,
|
||||||
COALESCE(u.email, a.handle, r.remote_actor_url) AS user_email
|
CASE WHEN r.remote_actor_url IS NOT NULL THEN COALESCE(a.handle, r.remote_actor_url)
|
||||||
|
ELSE COALESCE(u.email, r.user_id) END AS user_email
|
||||||
FROM reviews r
|
FROM reviews r
|
||||||
INNER JOIN movies m ON m.id = r.movie_id
|
INNER JOIN movies m ON m.id = r.movie_id
|
||||||
LEFT JOIN users u ON u.id = r.user_id
|
LEFT JOIN users u ON u.id = r.user_id
|
||||||
@@ -522,12 +523,13 @@ impl DiaryRepository for PostgresDiaryRepository {
|
|||||||
to_char(r.watched_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS') AS watched_at,
|
to_char(r.watched_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS') AS watched_at,
|
||||||
to_char(r.created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS') AS created_at,
|
to_char(r.created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS') AS created_at,
|
||||||
r.remote_actor_url,
|
r.remote_actor_url,
|
||||||
CASE WHEN r.remote_actor_url IS NOT NULL THEN r.remote_actor_url
|
r.watch_medium,
|
||||||
WHEN u.email IS NOT NULL THEN u.email
|
CASE WHEN r.remote_actor_url IS NOT NULL THEN COALESCE(a.handle, r.remote_actor_url)
|
||||||
ELSE r.user_id END AS user_email
|
ELSE COALESCE(u.email, r.user_id) END AS user_email
|
||||||
FROM reviews r
|
FROM reviews r
|
||||||
INNER JOIN movies m ON m.id = r.movie_id
|
INNER JOIN movies m ON m.id = r.movie_id
|
||||||
LEFT JOIN users u ON u.id = r.user_id
|
LEFT JOIN users u ON u.id = r.user_id
|
||||||
|
LEFT JOIN ap_remote_actors a ON a.url = r.remote_actor_url
|
||||||
WHERE r.movie_id = $1
|
WHERE r.movie_id = $1
|
||||||
ORDER BY r.watched_at DESC
|
ORDER BY r.watched_at DESC
|
||||||
LIMIT $2 OFFSET $3",
|
LIMIT $2 OFFSET $3",
|
||||||
|
|||||||
@@ -309,7 +309,8 @@ impl DiaryRepository for SqliteDiaryRepository {
|
|||||||
"SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path,
|
"SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path,
|
||||||
r.id AS review_id, r.movie_id, r.user_id, r.rating, r.comment,
|
r.id AS review_id, r.movie_id, r.user_id, r.rating, r.comment,
|
||||||
r.watched_at, r.created_at, r.remote_actor_url, r.watch_medium,
|
r.watched_at, r.created_at, r.remote_actor_url, r.watch_medium,
|
||||||
COALESCE(u.email, a.handle, r.remote_actor_url) AS user_email
|
CASE WHEN r.remote_actor_url IS NOT NULL THEN COALESCE(a.handle, r.remote_actor_url)
|
||||||
|
ELSE COALESCE(u.email, r.user_id) END AS user_email
|
||||||
FROM reviews r
|
FROM reviews r
|
||||||
INNER JOIN movies m ON m.id = r.movie_id
|
INNER JOIN movies m ON m.id = r.movie_id
|
||||||
LEFT JOIN users u ON u.id = r.user_id
|
LEFT JOIN users u ON u.id = r.user_id
|
||||||
@@ -476,12 +477,12 @@ impl DiaryRepository for SqliteDiaryRepository {
|
|||||||
"SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path,
|
"SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path,
|
||||||
r.id AS review_id, r.movie_id, r.user_id, r.rating, r.comment,
|
r.id AS review_id, r.movie_id, r.user_id, r.rating, r.comment,
|
||||||
r.watched_at, r.created_at, r.remote_actor_url, r.watch_medium,
|
r.watched_at, r.created_at, r.remote_actor_url, r.watch_medium,
|
||||||
CASE WHEN r.remote_actor_url IS NOT NULL THEN r.remote_actor_url
|
CASE WHEN r.remote_actor_url IS NOT NULL THEN COALESCE(a.handle, r.remote_actor_url)
|
||||||
WHEN u.email IS NOT NULL THEN u.email
|
ELSE COALESCE(u.email, r.user_id) END AS user_email
|
||||||
ELSE r.user_id END AS user_email
|
|
||||||
FROM reviews r
|
FROM reviews r
|
||||||
INNER JOIN movies m ON m.id = r.movie_id
|
INNER JOIN movies m ON m.id = r.movie_id
|
||||||
LEFT JOIN users u ON u.id = r.user_id
|
LEFT JOIN users u ON u.id = r.user_id
|
||||||
|
LEFT JOIN ap_remote_actors a ON a.url = r.remote_actor_url
|
||||||
WHERE r.movie_id = ?
|
WHERE r.movie_id = ?
|
||||||
ORDER BY r.watched_at DESC
|
ORDER BY r.watched_at DESC
|
||||||
LIMIT ? OFFSET ?",
|
LIMIT ? OFFSET ?",
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ pub struct DiaryQueryParams {
|
|||||||
pub offset: Option<u32>,
|
pub offset: Option<u32>,
|
||||||
pub sort_by: Option<String>,
|
pub sort_by: Option<String>,
|
||||||
pub movie_id: Option<Uuid>,
|
pub movie_id: Option<Uuid>,
|
||||||
|
pub user_id: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
|
#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ pub fn to_diary_query(p: DiaryQueryParams) -> GetDiaryQuery {
|
|||||||
_ => SortDirection::Descending,
|
_ => SortDirection::Descending,
|
||||||
}),
|
}),
|
||||||
movie_id: p.movie_id,
|
movie_id: p.movie_id,
|
||||||
user_id: None,
|
user_id: p.user_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ fn sort_by_asc_string_becomes_ascending() {
|
|||||||
limit: None,
|
limit: None,
|
||||||
offset: None,
|
offset: None,
|
||||||
movie_id: None,
|
movie_id: None,
|
||||||
|
user_id: None,
|
||||||
};
|
};
|
||||||
let query = to_diary_query(params);
|
let query = to_diary_query(params);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
@@ -99,6 +100,7 @@ fn sort_by_other_string_becomes_descending() {
|
|||||||
limit: None,
|
limit: None,
|
||||||
offset: None,
|
offset: None,
|
||||||
movie_id: None,
|
movie_id: None,
|
||||||
|
user_id: None,
|
||||||
};
|
};
|
||||||
let query = to_diary_query(params);
|
let query = to_diary_query(params);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
|
|||||||
@@ -141,10 +141,10 @@ function StatCell({ label, value }: { label: string; value: string | number }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function DiaryTab({ sortBy, search }: { sortBy: string; userId?: string; search?: string }) {
|
function DiaryTab({ sortBy, userId, search }: { sortBy: string; userId?: string; search?: string }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { data, isPending, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
const { data, isPending, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||||
useInfiniteDiary({ sort_by: sortBy, movie_id: undefined })
|
useInfiniteDiary({ sort_by: sortBy, user_id: userId })
|
||||||
const items = data?.pages.flatMap((p) => p.items) ?? []
|
const items = data?.pages.flatMap((p) => p.items) ?? []
|
||||||
const filtered = search
|
const filtered = search
|
||||||
? items.filter((e) =>
|
? items.filter((e) =>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const diaryQueryParamsSchema = z.object({
|
|||||||
offset: z.number().optional(),
|
offset: z.number().optional(),
|
||||||
sort_by: z.string().optional(),
|
sort_by: z.string().optional(),
|
||||||
movie_id: z.string().uuid().optional(),
|
movie_id: z.string().uuid().optional(),
|
||||||
|
user_id: z.string().uuid().optional(),
|
||||||
})
|
})
|
||||||
export type DiaryQueryParams = z.infer<typeof diaryQueryParamsSchema>
|
export type DiaryQueryParams = z.infer<typeof diaryQueryParamsSchema>
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ function ProfilePage() {
|
|||||||
|
|
||||||
<ProfileView
|
<ProfileView
|
||||||
data={data}
|
data={data}
|
||||||
|
userId={auth.user_id}
|
||||||
search={search}
|
search={search}
|
||||||
onSearchChange={setSearch}
|
onSearchChange={setSearch}
|
||||||
actions={
|
actions={
|
||||||
|
|||||||
Reference in New Issue
Block a user