diff --git a/api/api/v1/accounts/:id/statuses.ts b/api/api/v1/accounts/:id/statuses.ts index 483ab0a3..8a1dc7b2 100644 --- a/api/api/v1/accounts/:id/statuses.ts +++ b/api/api/v1/accounts/:id/statuses.ts @@ -2,7 +2,7 @@ import { apiRoute, applyConfig, auth, idValidator } from "@/api"; import { createRoute } from "@hono/zod-openapi"; import { Note, Timeline, User } from "@versia/kit/db"; import { Notes, RolePermissions } from "@versia/kit/tables"; -import { and, eq, gt, gte, isNull, lt, sql } from "drizzle-orm"; +import { and, eq, gt, gte, inArray, isNull, lt, or, sql } from "drizzle-orm"; import { z } from "zod"; import { ErrorSchema } from "~/types/api"; @@ -122,6 +122,15 @@ export default apiRoute((app) => pinned ? sql`EXISTS (SELECT 1 FROM "UserToPinnedNotes" WHERE "UserToPinnedNotes"."noteId" = ${Notes.id} AND "UserToPinnedNotes"."userId" = ${otherUser.id})` : undefined, + // Visibility check + or( + sql`EXISTS (SELECT 1 FROM "NoteToMentions" WHERE "NoteToMentions"."noteId" = ${Notes.id} AND "NoteToMentions"."userId" = ${otherUser.id})`, + and( + sql`EXISTS (SELECT 1 FROM "Relationships" WHERE "Relationships"."subjectId" = ${Notes.authorId} AND "Relationships"."ownerId" = ${otherUser.id} AND "Relationships"."following" = true)`, + inArray(Notes.visibility, ["public", "private"]), + ), + inArray(Notes.visibility, ["public", "unlisted"]), + ), exclude_reblogs ? isNull(Notes.reblogId) : undefined, exclude_replies ? isNull(Notes.replyId) : undefined, ), diff --git a/api/api/v1/timelines/home.ts b/api/api/v1/timelines/home.ts index e1d5b687..134da221 100644 --- a/api/api/v1/timelines/home.ts +++ b/api/api/v1/timelines/home.ts @@ -2,7 +2,7 @@ import { apiRoute, applyConfig, auth, idValidator } from "@/api"; import { createRoute } from "@hono/zod-openapi"; import { Note, Timeline } from "@versia/kit/db"; import { Notes, RolePermissions } from "@versia/kit/tables"; -import { and, eq, gt, gte, lt, or, sql } from "drizzle-orm"; +import { and, eq, gt, gte, inArray, lt, or, sql } from "drizzle-orm"; import { z } from "zod"; import { ErrorSchema } from "~/types/api"; @@ -79,10 +79,15 @@ export default apiRoute((app) => since_id ? gte(Notes.id, since_id) : undefined, min_id ? gt(Notes.id, min_id) : undefined, ), + // Visibility check or( eq(Notes.authorId, user.id), sql`EXISTS (SELECT 1 FROM "NoteToMentions" WHERE "NoteToMentions"."noteId" = ${Notes.id} AND "NoteToMentions"."userId" = ${user.id})`, - sql`EXISTS (SELECT 1 FROM "Relationships" WHERE "Relationships"."subjectId" = ${Notes.authorId} AND "Relationships"."ownerId" = ${user.id} AND "Relationships"."following" = true)`, + and( + sql`EXISTS (SELECT 1 FROM "Relationships" WHERE "Relationships"."subjectId" = ${Notes.authorId} AND "Relationships"."ownerId" = ${user.id} AND "Relationships"."following" = true)`, + inArray(Notes.visibility, ["public", "private"]), + ), + eq(Notes.visibility, "public"), ), sql`NOT EXISTS (SELECT 1 FROM "Filters" WHERE "Filters"."userId" = ${user.id} AND "Filters"."filter_action" = 'hide' AND EXISTS (SELECT 1 FROM "FilterKeywords" WHERE "FilterKeywords"."filterId" = "Filters"."id" AND "Notes"."content" LIKE '%' || "FilterKeywords"."keyword" || '%') AND "Filters"."context" @> ARRAY['home'])`, ), diff --git a/api/api/v1/timelines/public.ts b/api/api/v1/timelines/public.ts index 189c81d0..acf326e3 100644 --- a/api/api/v1/timelines/public.ts +++ b/api/api/v1/timelines/public.ts @@ -2,7 +2,7 @@ import { apiRoute, applyConfig, auth, idValidator } from "@/api"; import { createRoute } from "@hono/zod-openapi"; import { Note, Timeline } from "@versia/kit/db"; import { Notes, RolePermissions } from "@versia/kit/tables"; -import { and, gt, gte, lt, sql } from "drizzle-orm"; +import { and, eq, gt, gte, inArray, lt, or, sql } from "drizzle-orm"; import { z } from "zod"; import { ErrorSchema } from "~/types/api"; @@ -97,6 +97,18 @@ export default apiRoute((app) => user ? sql`NOT EXISTS (SELECT 1 FROM "Filters" WHERE "Filters"."userId" = ${user.id} AND "Filters"."filter_action" = 'hide' AND EXISTS (SELECT 1 FROM "FilterKeywords" WHERE "FilterKeywords"."filterId" = "Filters"."id" AND "Notes"."content" LIKE '%' || "FilterKeywords"."keyword" || '%') AND "Filters"."context" @> ARRAY['public'])` : undefined, + // Visibility check + user + ? or( + eq(Notes.authorId, user.id), + sql`EXISTS (SELECT 1 FROM "NoteToMentions" WHERE "NoteToMentions"."noteId" = ${Notes.id} AND "NoteToMentions"."userId" = ${user.id})`, + and( + sql`EXISTS (SELECT 1 FROM "Relationships" WHERE "Relationships"."subjectId" = ${Notes.authorId} AND "Relationships"."ownerId" = ${user.id} AND "Relationships"."following" = true)`, + inArray(Notes.visibility, ["public", "private"]), + ), + eq(Notes.visibility, "public"), + ) + : eq(Notes.visibility, "public"), ), limit, context.req.url,