mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 00:18:19 +01:00
fix(api): 🐛 Fix incorrect database columns in status queries
Column instanceId of status didn't actually do anything and it was removed
This commit is contained in:
parent
8fc725639c
commit
19f442ec65
19
cli.ts
19
cli.ts
|
|
@ -8,7 +8,15 @@ import { CliBuilder, CliCommand } from "cli-parser";
|
|||
import { CliParameterType } from "cli-parser/cli-builder.type";
|
||||
import Table from "cli-table";
|
||||
import { config } from "config-manager";
|
||||
import { type SQL, eq, inArray, isNotNull, isNull, like } from "drizzle-orm";
|
||||
import {
|
||||
type SQL,
|
||||
eq,
|
||||
inArray,
|
||||
isNotNull,
|
||||
isNull,
|
||||
like,
|
||||
sql,
|
||||
} from "drizzle-orm";
|
||||
import extract from "extract-zip";
|
||||
import { MediaBackend } from "media-manager";
|
||||
import { lookup } from "mime-types";
|
||||
|
|
@ -948,16 +956,15 @@ const cliBuilder = new CliBuilder([
|
|||
return 1;
|
||||
}
|
||||
|
||||
let instanceQuery: SQL<unknown> | undefined = isNull(
|
||||
status.instanceId,
|
||||
);
|
||||
let instanceQuery: SQL<unknown> | undefined =
|
||||
sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NULL)`;
|
||||
|
||||
if (local && remote) {
|
||||
instanceQuery = undefined;
|
||||
} else if (local) {
|
||||
instanceQuery = isNull(status.instanceId);
|
||||
instanceQuery = sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NULL)`;
|
||||
} else if (remote) {
|
||||
instanceQuery = isNotNull(status.instanceId);
|
||||
instanceQuery = sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NOT NULL)`;
|
||||
}
|
||||
|
||||
const notes = await findManyStatuses({
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ export default {
|
|||
out: "./drizzle",
|
||||
schema: "./drizzle/schema.ts",
|
||||
dbCredentials: {
|
||||
/* host: "localhost",
|
||||
port: 40000,
|
||||
user: "lysand",
|
||||
password: "lysand",
|
||||
database: "lysand", */
|
||||
host: config.database.host,
|
||||
port: Number(config.database.port),
|
||||
user: config.database.username,
|
||||
|
|
|
|||
3
drizzle/0007_naive_sleeper.sql
Normal file
3
drizzle/0007_naive_sleeper.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE "Status" DROP CONSTRAINT "Status_instanceId_Instance_id_fk";
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "Status" DROP COLUMN IF EXISTS "instanceId";
|
||||
1753
drizzle/meta/0007_snapshot.json
Normal file
1753
drizzle/meta/0007_snapshot.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,55 +1,62 @@
|
|||
{
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1712805159664,
|
||||
"tag": "0000_illegal_living_lightning",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "5",
|
||||
"when": 1713055774123,
|
||||
"tag": "0001_salty_night_thrasher",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "5",
|
||||
"when": 1713056370431,
|
||||
"tag": "0002_stiff_ares",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "5",
|
||||
"when": 1713056528340,
|
||||
"tag": "0003_spicy_arachne",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"version": "5",
|
||||
"when": 1713056712218,
|
||||
"tag": "0004_burly_lockjaw",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "5",
|
||||
"when": 1713056917973,
|
||||
"tag": "0005_sleepy_puma",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "5",
|
||||
"when": 1713057159867,
|
||||
"tag": "0006_messy_network",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1712805159664,
|
||||
"tag": "0000_illegal_living_lightning",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "5",
|
||||
"when": 1713055774123,
|
||||
"tag": "0001_salty_night_thrasher",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "5",
|
||||
"when": 1713056370431,
|
||||
"tag": "0002_stiff_ares",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "5",
|
||||
"when": 1713056528340,
|
||||
"tag": "0003_spicy_arachne",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"version": "5",
|
||||
"when": 1713056712218,
|
||||
"tag": "0004_burly_lockjaw",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "5",
|
||||
"when": 1713056917973,
|
||||
"tag": "0005_sleepy_puma",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "5",
|
||||
"when": 1713057159867,
|
||||
"tag": "0006_messy_network",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "5",
|
||||
"when": 1713227918208,
|
||||
"tag": "0007_naive_sleeper",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -223,10 +223,6 @@ export const status = pgTable(
|
|||
visibility: text("visibility").notNull(),
|
||||
inReplyToPostId: uuid("inReplyToPostId"),
|
||||
quotingPostId: uuid("quotingPostId"),
|
||||
instanceId: uuid("instanceId").references(() => instance.id, {
|
||||
onDelete: "cascade",
|
||||
onUpdate: "cascade",
|
||||
}),
|
||||
sensitive: boolean("sensitive").notNull(),
|
||||
spoilerText: text("spoiler_text").default("").notNull(),
|
||||
applicationId: uuid("applicationId").references(() => application.id, {
|
||||
|
|
@ -683,7 +679,6 @@ export const emojiRelations = relations(emoji, ({ one, many }) => ({
|
|||
|
||||
export const instanceRelations = relations(instance, ({ many }) => ({
|
||||
users: many(user),
|
||||
statuses: many(status),
|
||||
emojis: many(emoji),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { apiRoute, applyConfig } from "@api";
|
||||
import { jsonResponse } from "@response";
|
||||
import { and, count, countDistinct, eq, gte, isNull } from "drizzle-orm";
|
||||
import { and, count, countDistinct, eq, gte, isNull, sql } from "drizzle-orm";
|
||||
import { findFirstUser, userToAPI } from "~database/entities/User";
|
||||
import { db } from "~drizzle/db";
|
||||
import { instance, status, user } from "~drizzle/schema";
|
||||
|
|
@ -31,7 +31,9 @@ export default apiRoute(async (req, matchedRoute, extraData) => {
|
|||
count: count(),
|
||||
})
|
||||
.from(status)
|
||||
.where(isNull(status.instanceId))
|
||||
.where(
|
||||
sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NULL)`,
|
||||
)
|
||||
)[0].count;
|
||||
|
||||
const userCount = (
|
||||
|
|
|
|||
|
|
@ -51,10 +51,6 @@ export default apiRoute<typeof meta, typeof schema>(
|
|||
),
|
||||
or(
|
||||
eq(status.authorId, user.id),
|
||||
/* inArray(
|
||||
status.authorId,
|
||||
followers.map((f) => f.ownerId),
|
||||
), */
|
||||
// All statuses where the user is mentioned, using table _StatusToUser which has a: status.id and b: user.id
|
||||
// WHERE format (... = ...)
|
||||
sql`EXISTS (SELECT 1 FROM "StatusToMentions" WHERE "StatusToMentions"."statusId" = ${status.id} AND "StatusToMentions"."userId" = ${user.id})`,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,59 @@ describe(meta.route, () => {
|
|||
}
|
||||
});
|
||||
|
||||
test("should only fetch local statuses", async () => {
|
||||
const response = await sendTestRequest(
|
||||
new Request(
|
||||
new URL(
|
||||
`${meta.route}?limit=20&local=true`,
|
||||
config.http.base_url,
|
||||
),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[0].accessToken}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
const objects = (await response.json()) as APIStatus[];
|
||||
|
||||
expect(objects.length).toBe(20);
|
||||
for (const [index, status] of objects.entries()) {
|
||||
expect(status.account).toBeDefined();
|
||||
expect(status.account.id).toBe(users[0].id);
|
||||
expect(status.content).toBeDefined();
|
||||
expect(status.created_at).toBeDefined();
|
||||
expect(status.id).toBe(timeline[index].id);
|
||||
}
|
||||
});
|
||||
|
||||
test("should only fetch remote statuses (0)", async () => {
|
||||
const response = await sendTestRequest(
|
||||
new Request(
|
||||
new URL(
|
||||
`${meta.route}?limit=20&remote=true`,
|
||||
config.http.base_url,
|
||||
),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[0].accessToken}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("content-type")).toBe("application/json");
|
||||
|
||||
const objects = (await response.json()) as APIStatus[];
|
||||
|
||||
expect(objects.length).toBe(0);
|
||||
});
|
||||
|
||||
describe("should paginate properly", async () => {
|
||||
test("should send correct Link header", async () => {
|
||||
const response = await sendTestRequest(
|
||||
|
|
|
|||
|
|
@ -50,10 +50,11 @@ export default apiRoute<typeof meta, typeof schema>(
|
|||
max_id ? lt(status.id, max_id) : undefined,
|
||||
since_id ? gte(status.id, since_id) : undefined,
|
||||
min_id ? gt(status.id, min_id) : undefined,
|
||||
// use authorId to grab user, then use user.instanceId to filter local/remote statuses
|
||||
remote
|
||||
? isNotNull(status.instanceId)
|
||||
? sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NOT NULL)`
|
||||
: local
|
||||
? isNull(status.instanceId)
|
||||
? sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NULL)`
|
||||
: undefined,
|
||||
only_media
|
||||
? sql`EXISTS (SELECT 1 FROM "Attachment" WHERE "Attachment"."statusId" = ${status.id})`
|
||||
|
|
|
|||
Loading…
Reference in a new issue