update moderator view (#3820)

* update api tests for new moderator view

* chage moderator view to be a listing type in get posts

Note: Internally, the listing type is called ListingType.ModeratorView,
but it's called "Moderator View" in the api endpoint

* fix formatting

* add support for moderator view to list comments

* add api test for moderator view when listing comments

* fix api test formatting

* retry tests

* don't filter out blocked users and communities when using moderator view

* fix cargo tests failing

* fix formatting

* fix previous merge

* Adding ModeratorView to listing_type_enums

* Fixing fmt.

* Adding a default to ListingType.

* Upgrading to use new lemmy-js-client.

---------

Co-authored-by: Nutomic <me@nutomic.com>
Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
Co-authored-by: Dessalines <tyhou13@gmx.com>
This commit is contained in:
biosfood 2023-08-31 13:07:45 +02:00 committed by GitHub
parent c93bde9799
commit 384e55f0e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 140 additions and 30 deletions

View file

@ -19,7 +19,7 @@
"eslint": "^8.40.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^29.5.0",
"lemmy-js-client": "0.19.0-rc.2",
"lemmy-js-client": "0.19.0-rc.3",
"prettier": "^3.0.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4"

View file

@ -21,6 +21,8 @@ import {
registerUser,
API,
getPosts,
getComments,
createComment,
getCommunityByName,
} from "./shared";
@ -245,12 +247,17 @@ test("moderator view", async () => {
client: alpha.client,
};
expect(otherUser.auth).not.toBe("");
let otherCommunity = (await createCommunity(otherUser)).community_view;
expect(otherCommunity.community.name).toBeDefined();
let otherPost = (await createPost(otherUser, otherCommunity.community.id))
.post_view;
expect(otherPost.post.id).toBeDefined();
let otherComment = (await createComment(otherUser, otherPost.post.id))
.comment_view;
expect(otherComment.comment.id).toBeDefined();
// create a community and post on alpha
let alphaCommunity = (await createCommunity(alpha)).community_view;
expect(alphaCommunity.community.name).toBeDefined();
@ -258,27 +265,56 @@ test("moderator view", async () => {
.post_view;
expect(alphaPost.post.id).toBeDefined();
let alphaComment = (await createComment(otherUser, alphaPost.post.id))
.comment_view;
expect(alphaComment.comment.id).toBeDefined();
// other user also posts on alpha's community
let otherAlphaPost = (
await createPost(otherUser, alphaCommunity.community.id)
).post_view;
expect(otherAlphaPost.post.id).toBeDefined();
// alpha lists posts on home page, should contain all posts that were made
let posts = (await getPosts(alpha)).posts;
let otherAlphaComment = (
await createComment(otherUser, otherAlphaPost.post.id)
).comment_view;
expect(otherAlphaComment.comment.id).toBeDefined();
// alpha lists posts and comments on home page, should contain all posts that were made
let posts = (await getPosts(alpha, "All")).posts;
expect(posts).toBeDefined();
let postIds = posts.map(post => post.post.id);
let comments = (await getComments(alpha, undefined, "All")).comments;
expect(comments).toBeDefined();
let commentIds = comments.map(comment => comment.comment.id);
expect(postIds).toContain(otherPost.post.id);
expect(commentIds).toContain(otherComment.comment.id);
expect(postIds).toContain(alphaPost.post.id);
expect(commentIds).toContain(alphaComment.comment.id);
expect(postIds).toContain(otherAlphaPost.post.id);
expect(commentIds).toContain(otherAlphaComment.comment.id);
// in moderator view, alpha should not see otherPost, wich was posted on a community alpha doesn't moderate
posts = (await getPosts(alpha, true)).posts;
posts = (await getPosts(alpha, "ModeratorView")).posts;
expect(posts).toBeDefined();
postIds = posts.map(post => post.post.id);
comments = (await getComments(alpha, undefined, "ModeratorView")).comments;
expect(comments).toBeDefined();
commentIds = comments.map(comment => comment.comment.id);
expect(postIds).not.toContain(otherPost.post.id);
expect(commentIds).not.toContain(otherComment.comment.id);
expect(postIds).toContain(alphaPost.post.id);
expect(commentIds).toContain(alphaComment.comment.id);
expect(postIds).toContain(otherAlphaPost.post.id);
expect(commentIds).toContain(otherAlphaComment.comment.id);
});
test("Get community for different casing on domain", async () => {

View file

@ -4,7 +4,6 @@ import {
GetUnreadCount,
GetUnreadCountResponse,
LemmyHttp,
LocalUser,
} from "lemmy-js-client";
import { CreatePost } from "lemmy-js-client/dist/types/CreatePost";
import { DeletePost } from "lemmy-js-client/dist/types/DeletePost";
@ -69,6 +68,7 @@ import { GetPostsResponse } from "lemmy-js-client/dist/types/GetPostsResponse";
import { GetPosts } from "lemmy-js-client/dist/types/GetPosts";
import { GetPersonDetailsResponse } from "lemmy-js-client/dist/types/GetPersonDetailsResponse";
import { GetPersonDetails } from "lemmy-js-client/dist/types/GetPersonDetails";
import { ListingType } from "lemmy-js-client/dist/types/ListingType";
export interface API {
client: LemmyHttp;
@ -201,7 +201,9 @@ export async function setupLogins() {
try {
await createCommunity(alpha, "main");
await createCommunity(beta, "main");
} catch (_) {}
} catch (_) {
console.log("Communities already exist");
}
}
export async function createPost(
@ -321,11 +323,12 @@ export async function getPost(
export async function getComments(
api: API,
post_id: number,
post_id?: number,
listingType: ListingType = "All",
): Promise<GetCommentsResponse> {
let form: GetComments = {
post_id: post_id,
type_: "All",
type_: listingType,
sort: "New",
auth: api.auth,
};
@ -798,11 +801,11 @@ export async function listCommentReports(
export function getPosts(
api: API,
moderator_view = false,
listingType?: ListingType,
): Promise<GetPostsResponse> {
let form: GetPosts = {
moderator_view,
auth: api.auth,
type_: listingType,
};
return api.client.getPosts(form);
}

View file

@ -6,7 +6,7 @@
"noImplicitAny": true,
"lib": ["es2017", "es7", "es6", "dom"],
"outDir": "./dist",
"target": "ES5",
"target": "ES2015",
"strictNullChecks": true,
"moduleResolution": "Node"
},

View file

@ -2174,10 +2174,10 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
lemmy-js-client@0.19.0-rc.2:
version "0.19.0-rc.2"
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-rc.2.tgz#c3cb511b27f92538909a2b91a0f8527b1abad958"
integrity sha512-FXuf8s7bpBVkHL/OGWDb/0aGIrJ7uv3d4Xt1h6zmNDhw6MmmuD8RXgCHiS2jqhxjAEp96Dpl1NFXbpmKpix7tQ==
lemmy-js-client@0.19.0-rc.3:
version "0.19.0-rc.3"
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-rc.3.tgz#1efbfd5ce492319227a41cb020fc1cf9b2e7c075"
integrity sha512-RmibQ3+YTvqsQ89II2I29pfPmVAWiSObGAU9Nc/AGYfyvaCya7f5+TirKwHdKA2eWDWLOTnD4rm6WgcgAwvhWw==
dependencies:
cross-fetch "^3.1.5"
form-data "^4.0.0"

View file

@ -77,7 +77,6 @@ pub struct GetPosts {
pub saved_only: Option<bool>,
pub liked_only: Option<bool>,
pub disliked_only: Option<bool>,
pub moderator_view: Option<bool>,
pub auth: Option<Sensitive<String>>,
}

View file

@ -43,8 +43,6 @@ pub async fn list_posts(
return Err(LemmyError::from(LemmyErrorType::ContradictingFilters));
}
let moderator_view = data.moderator_view.unwrap_or_default();
let listing_type = Some(listing_type_with_default(
data.type_,
&local_site,
@ -59,7 +57,6 @@ pub async fn list_posts(
saved_only,
liked_only,
disliked_only,
moderator_view,
page,
limit,
..Default::default()

View file

@ -44,7 +44,9 @@ use strum_macros::{Display, EnumString};
#[cfg(feature = "full")]
use ts_rs::TS;
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
#[derive(
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default,
)]
#[cfg_attr(feature = "full", derive(DbEnum, TS))]
#[cfg_attr(
feature = "full",
@ -54,6 +56,7 @@ use ts_rs::TS;
#[cfg_attr(feature = "full", ts(export))]
/// The post sort types. See here for descriptions: https://join-lemmy.org/docs/en/users/03-votes-and-ranking.html
pub enum SortType {
#[default]
Active,
Hot,
New,
@ -99,7 +102,9 @@ pub enum PersonSortType {
PostCount,
}
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
#[derive(
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default,
)]
#[cfg_attr(feature = "full", derive(DbEnum, TS))]
#[cfg_attr(
feature = "full",
@ -112,9 +117,12 @@ pub enum ListingType {
/// Content from your own site, as well as all connected / federated sites.
All,
/// Content from your site only.
#[default]
Local,
/// Content only from communities you've subscribed to.
Subscribed,
/// Content that you can moderate (because you are a moderator of the community it is posted to)
ModeratorView,
}
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]

View file

@ -22,6 +22,7 @@ use lemmy_db_schema::{
community,
community_block,
community_follower,
community_moderator,
community_person_ban,
local_user_language,
person,
@ -101,6 +102,14 @@ fn queries<'a>() -> Queries<
.and(comment_like::person_id.eq(person_id_join)),
),
)
.left_join(
community_moderator::table.on(
post::id
.eq(comment::post_id)
.and(post::community_id.eq(community_moderator::community_id))
.and(community_moderator::person_id.eq(person_id_join)),
),
)
};
let selection = (
@ -186,6 +195,9 @@ fn queries<'a>() -> Queries<
.or(community_follower::person_id.eq(person_id_join)),
)
}
ListingType::ModeratorView => {
query = query.filter(community_moderator::person_id.is_not_null());
}
}
}
@ -222,7 +234,9 @@ fn queries<'a>() -> Queries<
query = query.filter(person::bot_account.eq(false));
};
if options.local_user.is_some() {
if options.local_user.is_some()
&& options.listing_type.unwrap_or_default() != ListingType::ModeratorView
{
// Filter out the rows with missing languages
query = query.filter(local_user_language::language_id.is_not_null());

View file

@ -258,6 +258,9 @@ fn queries<'a>() -> Queries<
.or(community_follower::person_id.eq(person_id_join)),
)
}
ListingType::ModeratorView => {
query = query.filter(community_moderator::person_id.is_not_null());
}
}
}
@ -295,10 +298,6 @@ fn queries<'a>() -> Queries<
if options.saved_only {
query = query.filter(post_saved::id.is_not_null());
}
if options.moderator_view {
query = query.filter(community_moderator::person_id.is_not_null());
}
// Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read
// setting wont be able to see saved posts.
else if !options
@ -318,16 +317,17 @@ fn queries<'a>() -> Queries<
query = query.filter(post_like::score.eq(-1));
}
if options.local_user.is_some() {
// Dont filter blocks or missing languages for moderator view type
if options.local_user.is_some()
&& options.listing_type.unwrap_or_default() != ListingType::ModeratorView
{
// Filter out the rows with missing languages
query = query.filter(local_user_language::language_id.is_not_null());
// Don't show blocked communities or persons
query = query.filter(community_block::person_id.is_null());
if !options.moderator_view {
query = query.filter(person_block::person_id.is_null());
}
}
let now = diesel::dsl::now.into_sql::<Timestamptz>();
query = match options.sort.unwrap_or(SortType::Hot) {

View file

@ -0,0 +1,49 @@
ALTER TABLE local_user
ALTER default_listing_type DROP DEFAULT;
ALTER TABLE local_site
ALTER default_post_listing_type DROP DEFAULT;
UPDATE
local_user
SET
default_listing_type = 'Local'
WHERE
default_listing_type = 'ModeratorView';
UPDATE
local_site
SET
default_post_listing_type = 'Local'
WHERE
default_post_listing_type = 'ModeratorView';
-- rename the old enum
ALTER TYPE listing_type_enum RENAME TO listing_type_enum__;
-- create the new enum
CREATE TYPE listing_type_enum AS ENUM (
'All',
'Local',
'Subscribed'
);
-- alter all your enum columns
ALTER TABLE local_user
ALTER COLUMN default_listing_type TYPE listing_type_enum
USING default_listing_type::text::listing_type_enum;
ALTER TABLE local_site
ALTER COLUMN default_post_listing_type TYPE listing_type_enum
USING default_post_listing_type::text::listing_type_enum;
-- Add back in the default
ALTER TABLE local_user
ALTER default_listing_type SET DEFAULT 'Local';
ALTER TABLE local_site
ALTER default_post_listing_type SET DEFAULT 'Local';
-- drop the old enum
DROP TYPE listing_type_enum__;

View file

@ -0,0 +1,4 @@
-- Update the listing_type_enum
ALTER TYPE listing_type_enum
ADD VALUE 'ModeratorView';