From 45a8a2678e91f73bc0a0baf9af8056185c7bd74d Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Fri, 1 Dec 2023 13:44:48 -1000 Subject: [PATCH 01/86] feat: Add following and followers endpoints --- README.md | 123 +------------------ server/api/api/v1/accounts/[id]/followers.ts | 89 ++++++++++++++ server/api/api/v1/accounts/[id]/following.ts | 89 ++++++++++++++ 3 files changed, 180 insertions(+), 121 deletions(-) create mode 100644 server/api/api/v1/accounts/[id]/followers.ts create mode 100644 server/api/api/v1/accounts/[id]/following.ts diff --git a/README.md b/README.md index b23635cf..47f174ba 100644 --- a/README.md +++ b/README.md @@ -259,12 +259,13 @@ Tests needed but completed: - `/api/v1/media/:id` - `/api/v1/favourites` +- `/api/v1/accounts/:id/followers` +- `/api/v1/accounts/:id/following` Endpoints left: - `/api/v1/reports` - `/api/v1/accounts/:id/lists` -- `/api/v1/accounts/:id/following` - `/api/v1/follow_requests` - `/api/v1/follow_requests/:account_id/authorize` - `/api/v1/follow_requests/:account_id/reject` @@ -330,126 +331,6 @@ Endpoints left: WebSocket Streaming API also needed to be added (and push notifications) -## Configuration Values - -Configuration can be found inside the `config.toml` file. The following values are available: - -### Database - -- `host`: The hostname or IP address of the database server. Example: `"localhost"` -- `port`: The port number to use for the database connection. Example: `48654` -- `username`: The username to use for the database connection. Example: `"lysand"` -- `password`: The password to use for the database connection. Example: `"mycoolpassword"` -- `database`: The name of the database to use. Example: `"lysand"` - -### HTTP - -- `base_url`: The base URL for the HTTP server. Example: `"https://lysand.social"` -- `bind`: The hostname or IP address to bind the HTTP server to. Example: `"http://localhost"` -- `bind_port`: The port number to bind the HTTP server to. Example: `"8080"` - -#### Security - -- `banned_ips`: An array of strings representing banned IPv4 or IPv6 IPs. Wildcards, networks and ranges are supported. Example: `[ "192.168.0.*" ]` (empty array) - -### Media - -- `backend`: Specifies the backend to use for media storage. Can be "local" or "s3", "local" uploads the file to the local filesystem. -- `deduplicate_media`: When set to true, the hash of media is checked when uploading to avoid duplication. - -#### Conversion - -- `convert_images`: Whether to convert uploaded images to another format. Example: `true` -- `convert_to`: The format to convert uploaded images to. Example: `"webp"`. Can be "jxl", "webp", "avif", "png", "jpg" or "gif". - -### S3 - -- `endpoint`: The endpoint to use for the S3 server. Example: `"https://s3.example.com"` -- `access_key`: Access key to use for S3 -- `secret_access_key`: Secret access key to use for S3 -- `bucket_name`: The bucket to use for S3 (can be left empty) -- `region`: The region to use for S3 (can be left empty) -- `public_url`: The public URL to access uploaded media. Example: `"https://cdn.example.com"` - -### SMTP - -- `server`: The SMTP server to use for sending emails. Example: `"smtp.example.com"` -- `port`: The port number to use for the SMTP server. Example: `465` -- `username`: The username to use for the SMTP server. Example: `"test@example.com"` -- `password`: The password to use for the SMTP server. Example: `"password123"` -- `tls`: Whether to use TLS for the SMTP server. Example: `true` - -### Email - -- `send_on_report`: Whether to send an email to moderators when a report is received. Example: `false` -- `send_on_suspend`: Whether to send an email to moderators when a user is suspended. Example: `true` -- `send_on_unsuspend`: Whether to send an email to moderators when a user is unsuspended. Example: `false` - -### Validation - -- `max_displayname_size`: The maximum size of a user's display name, in characters. Example: `30` -- `max_bio_size`: The maximum size of a user's bio, in characters. Example: `160` -- `max_note_size`: The maximum size of a user's note, in characters. Example: `500` -- `max_avatar_size`: The maximum size of a user's avatar image, in bytes. Example: `1048576` (1 MB) -- `max_header_size`: The maximum size of a user's header image, in bytes. Example: `2097152` (2 MB) -- `max_media_size`: The maximum size of a media attachment, in bytes. Example: `5242880` (5 MB) -- `max_media_attachments`: The maximum number of media attachments allowed per post. Example: `4` -- `max_media_description_size`: The maximum size of a media attachment's description, in characters. Example: `100` -- `max_username_size`: The maximum size of a user's username, in characters. Example: `20` -- `username_blacklist`: An array of strings representing usernames that are not allowed to be used by users. Defaults are from Akkoma. Example: `["admin", "moderator"]` -- `blacklist_tempmail`: Whether to blacklist known temporary email providers. Example: `true` -- `email_blacklist`: Additional email providers to blacklist. Example: `["example.com", "test.com"]` -- `url_scheme_whitelist`: An array of strings representing valid URL schemes. URLs that do not use one of these schemes will be parsed as text. Example: `["http", "https"]` -- `allowed_mime_types`: An array of strings representing allowed MIME types for media attachments. Example: `["image/jpeg", "image/png", "video/mp4"]` - -### Defaults - -- `visibility`: The default visibility for new notes. Example: `"public"` -- `language`: The default language for new notes. Example: `"en"` -- `avatar`: The default avatar URL. Example: `""` (empty string) -- `header`: The default header URL. Example: `""` (empty string) - -### ActivityPub - -> **Note**: These options do nothing and date back to when Lysand had ActivityPub support. They will be removed in a future version. - -- `use_tombstones`: Whether to use ActivityPub Tombstones instead of deleting objects. Example: `true` -- `fetch_all_collection_members`: Whether to fetch all members of collections (followers, following, etc) when receiving them. Example: `false` -- `reject_activities`: An array of instance domain names without "https" or glob patterns. Rejects all activities from these instances, simply doesn't save them at all. Example: `[ "mastodon.social" ]` -- `force_followers_only`: An array of instance domain names without "https" or glob patterns. Force posts from this instance to be followers only. Example: `[ "mastodon.social" ]` -- `discard_reports`: An array of instance domain names without "https" or glob patterns. Discard all reports from these instances. Example: `[ "mastodon.social" ]` -- `discard_deletes`: An array of instance domain names without "https" or glob patterns. Discard all deletes from these instances. Example: `[ "mastodon.social" ]` -- `discard_updates`: An array of instance domain names without "https" or glob patterns. Discard all updates (edits) from these instances. Example: `[]` -- `discard_banners`: An array of instance domain names without "https" or glob patterns. Discard all banners from these instances. Example: `[ "mastodon.social" ]` -- `discard_avatars`: An array of instance domain names without "https" or glob patterns. Discard all avatars from these instances. Example: `[ "mastodon.social" ]` -- `discard_follows`: An array of instance domain names without "https" or glob patterns. Discard all follow requests from these instances. Example: `[]` -- `force_sensitive`: An array of instance domain names without "https" or glob patterns. Force set these instances' media as sensitive. Example: `[ "mastodon.social" ]` -- `remove_media`: An array of instance domain names without "https" or glob patterns. Remove these instances' media. Example: `[ "mastodon.social" ]` - -### Filters - -- `note_filters`: An array of regex filters to drop notes from new activities. Example: `["(https?://)?(www\\.)?youtube\\.com/watch\\?v=[a-zA-Z0-9_-]+", "(https?://)?(www\\.)?youtu\\.be/[a-zA-Z0-9_-]+"]` -- `username_filters`: An array of regex filters to drop users from new activities based on their username. Example: `[ "^spammer-[a-z]" ]` -- `displayname_filters`: An array of regex filters to drop users from new activities based on their display name. Example: `[ "^spammer-[a-z]" ]` -- `bio_filters`: An array of regex filters to drop users from new activities based on their bio. Example: `[ "badword" ]` -- `emoji_filters`: An array of regex filters to drop users from new activities based on their emoji usage. Example: `[ ":bademoji:" ]` - -### Logging - -- `log_requests`: Whether to log all requests. Example: `true` -- `log_requests_verbose`: Whether to log request and their contents. Example: `false` -- `log_filters`: Whether to log all filtered objects. Example: `true` - -### Ratelimits - -- `duration_coeff`: The amount to multiply every route's duration by. Example: `1.0` -- `max_coeff`: The amount to multiply every route's max by. Example: `1.0` - -### Custom Ratelimits - -- `"/api/v1/timelines/public"`: An object representing a custom ratelimit for the specified API route. Example: `{ duration = 60, max = 200 }` - - ## License This project is licensed under the [AGPL-3.0](LICENSE). \ No newline at end of file diff --git a/server/api/api/v1/accounts/[id]/followers.ts b/server/api/api/v1/accounts/[id]/followers.ts new file mode 100644 index 00000000..af85ffdf --- /dev/null +++ b/server/api/api/v1/accounts/[id]/followers.ts @@ -0,0 +1,89 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import { errorResponse, jsonResponse } from "@response"; +import type { MatchedRoute } from "bun"; +import { userRelations, userToAPI } from "~database/entities/User"; +import { applyConfig } from "@api"; +import { client } from "~database/datasource"; + +export const meta = applyConfig({ + allowedMethods: ["GET"], + ratelimits: { + max: 60, + duration: 60, + }, + route: "/accounts/:id/followers", + auth: { + required: false, + }, +}); + +/** + * Fetch all statuses for a user + */ +export default async ( + req: Request, + matchedRoute: MatchedRoute +): Promise => { + const id = matchedRoute.params.id; + + // TODO: Add pinned + const { + max_id, + min_id, + since_id, + limit = 20, + }: { + max_id?: string; + since_id?: string; + min_id?: string; + limit?: number; + } = matchedRoute.query; + + const user = await client.user.findUnique({ + where: { id }, + include: userRelations, + }); + + if (limit < 1 || limit > 40) return errorResponse("Invalid limit", 400); + + if (!user) return errorResponse("User not found", 404); + + const objects = await client.user.findMany({ + where: { + relationships: { + some: { + subjectId: user.id, + following: true, + }, + }, + id: { + lt: max_id, + gt: min_id, + gte: since_id, + }, + }, + include: userRelations, + take: Number(limit), + orderBy: { + id: "desc", + }, + }); + + // Constuct HTTP Link header (next and prev) + const linkHeader = []; + if (objects.length > 0) { + const urlWithoutQuery = req.url.split("?")[0]; + linkHeader.push( + `<${urlWithoutQuery}?max_id=${objects.at(-1)?.id}>; rel="next"`, + `<${urlWithoutQuery}?min_id=${objects[0].id}>; rel="prev"` + ); + } + + return jsonResponse( + await Promise.all(objects.map(object => userToAPI(object))), + 200, + { + Link: linkHeader.join(", "), + } + ); +}; diff --git a/server/api/api/v1/accounts/[id]/following.ts b/server/api/api/v1/accounts/[id]/following.ts new file mode 100644 index 00000000..2f9d8142 --- /dev/null +++ b/server/api/api/v1/accounts/[id]/following.ts @@ -0,0 +1,89 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import { errorResponse, jsonResponse } from "@response"; +import type { MatchedRoute } from "bun"; +import { userRelations, userToAPI } from "~database/entities/User"; +import { applyConfig } from "@api"; +import { client } from "~database/datasource"; + +export const meta = applyConfig({ + allowedMethods: ["GET"], + ratelimits: { + max: 60, + duration: 60, + }, + route: "/accounts/:id/following", + auth: { + required: false, + }, +}); + +/** + * Fetch all statuses for a user + */ +export default async ( + req: Request, + matchedRoute: MatchedRoute +): Promise => { + const id = matchedRoute.params.id; + + // TODO: Add pinned + const { + max_id, + min_id, + since_id, + limit = 20, + }: { + max_id?: string; + since_id?: string; + min_id?: string; + limit?: number; + } = matchedRoute.query; + + const user = await client.user.findUnique({ + where: { id }, + include: userRelations, + }); + + if (limit < 1 || limit > 40) return errorResponse("Invalid limit", 400); + + if (!user) return errorResponse("User not found", 404); + + const objects = await client.user.findMany({ + where: { + relationshipSubjects: { + some: { + ownerId: user.id, + following: true, + }, + }, + id: { + lt: max_id, + gt: min_id, + gte: since_id, + }, + }, + include: userRelations, + take: Number(limit), + orderBy: { + id: "desc", + }, + }); + + // Constuct HTTP Link header (next and prev) + const linkHeader = []; + if (objects.length > 0) { + const urlWithoutQuery = req.url.split("?")[0]; + linkHeader.push( + `<${urlWithoutQuery}?max_id=${objects.at(-1)?.id}>; rel="next"`, + `<${urlWithoutQuery}?min_id=${objects[0].id}>; rel="prev"` + ); + } + + return jsonResponse( + await Promise.all(objects.map(object => userToAPI(object))), + 200, + { + Link: linkHeader.join(", "), + } + ); +}; From aa0813fef8a3c112e3eeb8d665ae1586b71e90a6 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:11:30 -1000 Subject: [PATCH 02/86] feat: Add Meilisearch integration, begin work on search endpoint --- bun.lockb | Bin 345808 -> 349144 bytes cli.ts | 77 ++++++++- config/config.example.toml | 6 + database/entities/Notification.ts | 2 +- database/entities/Status.ts | 127 +++++++++++++- index.ts | 5 + package.json | 4 + .../20231202001242_add_source/migration.sql | 2 + prisma/schema.prisma | 1 + server/api/api/v1/statuses/[id]/index.ts | 155 +++++++++++++++++- server/api/api/v1/statuses/[id]/source.ts | 49 ++++++ server/api/api/v2/search/index.ts | 60 +++++++ utils/config.ts | 13 ++ utils/meilisearch.ts | 111 +++++++++++++ 14 files changed, 605 insertions(+), 7 deletions(-) create mode 100644 prisma/migrations/20231202001242_add_source/migration.sql create mode 100644 server/api/api/v1/statuses/[id]/source.ts create mode 100644 server/api/api/v2/search/index.ts create mode 100644 utils/meilisearch.ts diff --git a/bun.lockb b/bun.lockb index ae9680ac77bc0a147c4a52dc86b8a85ddf415c7e..eda9a2f4b8f0397e42b323658663418e9c3ffefd 100755 GIT binary patch delta 67769 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 z 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 O)I3~eN1h#wR{R(AaPF`G delta 66378 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 F{{;@f6)6A! diff --git a/cli.ts b/cli.ts index a42f4d77..a21d9000 100644 --- a/cli.ts +++ b/cli.ts @@ -3,6 +3,7 @@ import chalk from "chalk"; import { client } from "~database/datasource"; import { createNewLocalUser } from "~database/entities/User"; import Table from "cli-table"; +import { rebuildSearchIndexes, SonicIndexType } from "@meilisearch"; const args = process.argv; @@ -86,7 +87,20 @@ ${chalk.bold("Commands:")} ${chalk.bold("Example:")} ${chalk.bgGray( `bun cli note search hello` )} - + ${alignDots(chalk.blue("index"), 24)} Manage user and status indexes + ${alignDots(chalk.blue("rebuild"))} Rebuild the index + ${alignDotsSmall( + chalk.green("batch-size") + )} The number of items to index at once (optional, default 100) + ${alignDotsSmall( + chalk.yellow("--statuses") + )} Only rebuild the statuses index (optional) + ${alignDotsSmall( + chalk.yellow("--users") + )} Only rebuild the users index (optional) + ${chalk.bold("Example:")} ${chalk.bgGray( + `bun cli index rebuild --users 200` + )} `; if (args.length < 3) { @@ -504,10 +518,71 @@ switch (command) { console.log(`Unknown command ${chalk.blue(command)}`); break; } + break; + } + case "index": { + switch (args[3]) { + case "rebuild": { + const statuses = args.includes("--statuses"); + const users = args.includes("--users"); + const argsWithoutFlags = args.filter( + arg => !arg.startsWith("--") + ); + + const batchSize = Number(argsWithoutFlags[4]) || 100; + + const neither = !statuses && !users; + + if (statuses || neither) { + console.log( + `${chalk.yellow(`⚠`)} ${chalk.bold( + `Rebuilding Meilisearch index for statuses` + )}` + ); + + await rebuildSearchIndexes( + [SonicIndexType.Statuses], + batchSize + ); + + console.log( + `${chalk.green(`✓`)} ${chalk.bold( + `Meilisearch index for statuses rebuilt` + )}` + ); + } + + if (users || neither) { + console.log( + `${chalk.yellow(`⚠`)} ${chalk.bold( + `Rebuilding Meilisearch index for users` + )}` + ); + + await rebuildSearchIndexes( + [SonicIndexType.Accounts], + batchSize + ); + + console.log( + `${chalk.green(`✓`)} ${chalk.bold( + `Meilisearch index for users rebuilt` + )}` + ); + } + + break; + } + default: + console.log(`Unknown command ${chalk.blue(command)}`); + break; + } break; } default: console.log(`Unknown command ${chalk.blue(command)}`); break; } + +process.exit(0); diff --git a/config/config.example.toml b/config/config.example.toml index 603eb05a..8af0ecd9 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -18,6 +18,12 @@ password = "" database = 1 enabled = false +[meilisearch] +host = "localhost" +port = 40007 +api_key = "" +enabled = true + [http] base_url = "https://lysand.social" bind = "http://localhost" diff --git a/database/entities/Notification.ts b/database/entities/Notification.ts index f6bd4c00..80399f30 100644 --- a/database/entities/Notification.ts +++ b/database/entities/Notification.ts @@ -13,7 +13,7 @@ export const notificationToAPI = async ( ): Promise => { return { account: userToAPI(notification.account), - created_at: notification.createdAt.toISOString(), + created_at: new Date(notification.createdAt).toISOString(), id: notification.id, type: notification.type, status: notification.status diff --git a/database/entities/Status.ts b/database/entities/Status.ts index 4b1cd2a8..d743e715 100644 --- a/database/entities/Status.ts +++ b/database/entities/Status.ts @@ -24,6 +24,10 @@ import type { APIStatus } from "~types/entities/status"; import { applicationToAPI } from "./Application"; import { attachmentToAPI } from "./Attachment"; import type { APIAttachment } from "~types/entities/attachment"; +import { sanitizeHtml } from "@sanitization"; +import { parse } from "marked"; +import linkifyStr from "linkify-string"; +import linkifyHtml from "linkify-html"; const config = getConfig(); @@ -303,7 +307,7 @@ export const createNewStatus = async (data: { visibility: APIStatus["visibility"]; sensitive: boolean; spoiler_text: string; - emojis: Emoji[]; + emojis?: Emoji[]; content_type?: string; uri?: string; mentions?: User[]; @@ -320,6 +324,8 @@ export const createNewStatus = async (data: { let mentions = data.mentions || []; + // TODO: Parse emojis + // Get list of mentioned users if (mentions.length === 0) { mentions = await client.user.findMany({ @@ -335,17 +341,36 @@ export const createNewStatus = async (data: { }); } + let formattedContent; + + // Get HTML version of content + if (data.content_type === "text/markdown") { + formattedContent = linkifyHtml(await sanitizeHtml(parse(data.content))); + } else if (data.content_type === "text/x.misskeymarkdown") { + // Parse as MFM + } else { + // Parse as plaintext + formattedContent = linkifyStr(data.content); + + // Split by newline and add

tags + formattedContent = formattedContent + .split("\n") + .map(line => `

${line}

`) + .join("\n"); + } + let status = await client.status.create({ data: { authorId: data.account.id, applicationId: data.application?.id, - content: data.content, + content: formattedContent, + contentSource: data.content, contentType: data.content_type, visibility: data.visibility, sensitive: data.sensitive, spoilerText: data.spoiler_text, emojis: { - connect: data.emojis.map(emoji => { + connect: data.emojis?.map(emoji => { return { id: emoji.id, }; @@ -405,6 +430,102 @@ export const createNewStatus = async (data: { return status; }; +export const editStatus = async ( + status: StatusWithRelations, + data: { + content: string; + visibility?: APIStatus["visibility"]; + sensitive: boolean; + spoiler_text: string; + emojis?: Emoji[]; + content_type?: string; + uri?: string; + mentions?: User[]; + media_attachments?: string[]; + } +) => { + // Get people mentioned in the content (match @username or @username@domain.com mentions + const mentionedPeople = + data.content.match(/@[a-zA-Z0-9_]+(@[a-zA-Z0-9_]+)?/g) ?? []; + + let mentions = data.mentions || []; + + // TODO: Parse emojis + + // Get list of mentioned users + if (mentions.length === 0) { + mentions = await client.user.findMany({ + where: { + OR: mentionedPeople.map(person => ({ + username: person.split("@")[1], + instance: { + base_url: person.split("@")[2], + }, + })), + }, + include: userRelations, + }); + } + + let formattedContent; + + // Get HTML version of content + if (data.content_type === "text/markdown") { + formattedContent = linkifyHtml(await sanitizeHtml(parse(data.content))); + } else if (data.content_type === "text/x.misskeymarkdown") { + // Parse as MFM + } else { + // Parse as plaintext + formattedContent = linkifyStr(data.content); + + // Split by newline and add

tags + formattedContent = formattedContent + .split("\n") + .map(line => `

${line}

`) + .join("\n"); + } + + const newStatus = await client.status.update({ + where: { + id: status.id, + }, + data: { + content: formattedContent, + contentSource: data.content, + contentType: data.content_type, + visibility: data.visibility, + sensitive: data.sensitive, + spoilerText: data.spoiler_text, + emojis: { + connect: data.emojis?.map(emoji => { + return { + id: emoji.id, + }; + }), + }, + attachments: data.media_attachments + ? { + connect: data.media_attachments.map(attachment => { + return { + id: attachment, + }; + }), + } + : undefined, + mentions: { + connect: mentions.map(mention => { + return { + id: mention.id, + }; + }), + }, + }, + include: statusAndUserRelations, + }); + + return newStatus; +}; + export const isFavouritedBy = async (status: Status, user: User) => { return !!(await client.like.findFirst({ where: { diff --git a/index.ts b/index.ts index 38a9de04..031db5b3 100644 --- a/index.ts +++ b/index.ts @@ -12,6 +12,7 @@ import { client } from "~database/datasource"; import type { PrismaClientInitializationError } from "@prisma/client/runtime/library"; import { HookTypes, Server } from "~plugins/types"; import { initializeRedisCache } from "@redis"; +import { connectMeili } from "@meilisearch"; const timeAtStart = performance.now(); const server = new Server(); @@ -36,6 +37,10 @@ if (!(await requests_log.exists())) { const redisCache = await initializeRedisCache(); +if (config.meilisearch.enabled) { + await connectMeili(); +} + if (redisCache) { client.$use(redisCache); } diff --git a/package.json b/package.json index 224545b0..d8ce8262 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,11 @@ "iso-639-1": "^3.1.0", "isomorphic-dompurify": "^1.10.0", "jsonld": "^8.3.1", + "linkify-html": "^4.1.3", + "linkify-string": "^4.1.3", + "linkifyjs": "^4.1.3", "marked": "^9.1.2", + "meilisearch": "^0.36.0", "prisma": "^5.6.0", "prisma-redis-middleware": "^4.8.0", "semver": "^7.5.4", diff --git a/prisma/migrations/20231202001242_add_source/migration.sql b/prisma/migrations/20231202001242_add_source/migration.sql new file mode 100644 index 00000000..272e2eb2 --- /dev/null +++ b/prisma/migrations/20231202001242_add_source/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Status" ADD COLUMN "contentSource" TEXT NOT NULL DEFAULT ''; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 86874950..bbba2240 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -103,6 +103,7 @@ model Status { isReblog Boolean content String @default("") contentType String @default("text/plain") + contentSource String @default("") visibility String inReplyToPost Status? @relation("StatusToStatusReply", fields: [inReplyToPostId], references: [id], onDelete: SetNull) inReplyToPostId String? @db.Uuid diff --git a/server/api/api/v1/statuses/[id]/index.ts b/server/api/api/v1/statuses/[id]/index.ts index ad7b7cee..60722cbb 100644 --- a/server/api/api/v1/statuses/[id]/index.ts +++ b/server/api/api/v1/statuses/[id]/index.ts @@ -1,8 +1,13 @@ import { applyConfig } from "@api"; +import { getConfig } from "@config"; +import { parseRequest } from "@request"; import { errorResponse, jsonResponse } from "@response"; +import { sanitizeHtml } from "@sanitization"; import type { MatchedRoute } from "bun"; +import { parse } from "marked"; import { client } from "~database/datasource"; import { + editStatus, isViewableByUser, statusAndUserRelations, statusToAPI, @@ -11,7 +16,7 @@ import { getFromRequest } from "~database/entities/User"; import type { APIRouteMeta } from "~types/api"; export const meta: APIRouteMeta = applyConfig({ - allowedMethods: ["GET", "DELETE"], + allowedMethods: ["GET", "DELETE", "PUT"], ratelimits: { max: 100, duration: 60, @@ -19,7 +24,7 @@ export const meta: APIRouteMeta = applyConfig({ route: "/api/v1/statuses/:id", auth: { required: false, - requiredOnMethods: ["DELETE"], + requiredOnMethods: ["DELETE", "PUT"], }, }); @@ -39,6 +44,8 @@ export default async ( include: statusAndUserRelations, }); + const config = getConfig(); + // Check if user is authorized to view this status (if it's private) if (!status || !isViewableByUser(status, user)) return errorResponse("Record not found", 404); @@ -69,6 +76,150 @@ export default async ( }, 200 ); + } else if (req.method == "PUT") { + if (status.authorId !== user?.id) { + return errorResponse("Unauthorized", 401); + } + + const { + status: statusText, + content_type, + "poll[expires_in]": expires_in, + "poll[options][]": options, + "media_ids[]": media_ids, + spoiler_text, + sensitive, + } = await parseRequest<{ + status?: string; + spoiler_text?: string; + sensitive?: boolean; + language?: string; + content_type?: string; + "media_ids[]"?: string[]; + "poll[options][]"?: string[]; + "poll[expires_in]"?: number; + "poll[multiple]"?: boolean; + "poll[hide_totals]"?: boolean; + }>(req); + + // TODO: Add Poll support + // Validate status + if (!statusText && !(media_ids && media_ids.length > 0)) { + return errorResponse( + "Status is required unless media is attached", + 422 + ); + } + + // Validate media_ids + if (media_ids && !Array.isArray(media_ids)) { + return errorResponse("Media IDs must be an array", 422); + } + + // Validate poll options + if (options && !Array.isArray(options)) { + return errorResponse("Poll options must be an array", 422); + } + + if (options && options.length > 4) { + return errorResponse("Poll options must be less than 5", 422); + } + + if (media_ids && media_ids.length > 0) { + // Disallow poll + if (options) { + return errorResponse("Cannot attach poll to media", 422); + } + if (media_ids.length > 4) { + return errorResponse("Media IDs must be less than 5", 422); + } + } + + if (options && options.length > config.validation.max_poll_options) { + return errorResponse( + `Poll options must be less than ${config.validation.max_poll_options}`, + 422 + ); + } + + if ( + options && + options.some( + option => option.length > config.validation.max_poll_option_size + ) + ) { + return errorResponse( + `Poll options must be less than ${config.validation.max_poll_option_size} characters`, + 422 + ); + } + + if (expires_in && expires_in < config.validation.min_poll_duration) { + return errorResponse( + `Poll duration must be greater than ${config.validation.min_poll_duration} seconds`, + 422 + ); + } + + if (expires_in && expires_in > config.validation.max_poll_duration) { + return errorResponse( + `Poll duration must be less than ${config.validation.max_poll_duration} seconds`, + 422 + ); + } + + let sanitizedStatus: string; + + if (content_type === "text/markdown") { + sanitizedStatus = await sanitizeHtml(parse(statusText ?? "")); + } else if (content_type === "text/x.misskeymarkdown") { + // Parse as MFM + // TODO: Parse as MFM + sanitizedStatus = await sanitizeHtml(parse(statusText ?? "")); + } else { + sanitizedStatus = await sanitizeHtml(statusText ?? ""); + } + + if (sanitizedStatus.length > config.validation.max_note_size) { + return errorResponse( + `Status must be less than ${config.validation.max_note_size} characters`, + 400 + ); + } + + // Check if status body doesnt match filters + if ( + config.filters.note_filters.some( + filter => statusText?.match(filter) + ) + ) { + return errorResponse("Status contains blocked words", 422); + } + + // Check if media attachments are all valid + + const foundAttachments = await client.attachment.findMany({ + where: { + id: { + in: media_ids ?? [], + }, + }, + }); + + if (foundAttachments.length !== (media_ids ?? []).length) { + return errorResponse("Invalid media IDs", 422); + } + + // Update status + const newStatus = await editStatus(status, { + content: sanitizedStatus, + content_type, + media_attachments: media_ids, + spoiler_text: spoiler_text ?? "", + sensitive: sensitive ?? false, + }); + + return jsonResponse(await statusToAPI(newStatus, user)); } return jsonResponse({}); diff --git a/server/api/api/v1/statuses/[id]/source.ts b/server/api/api/v1/statuses/[id]/source.ts new file mode 100644 index 00000000..ae9defbc --- /dev/null +++ b/server/api/api/v1/statuses/[id]/source.ts @@ -0,0 +1,49 @@ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import { applyConfig } from "@api"; +import { errorResponse, jsonResponse } from "@response"; +import type { MatchedRoute } from "bun"; +import { client } from "~database/datasource"; +import { createLike } from "~database/entities/Like"; +import { + isViewableByUser, + statusAndUserRelations, + statusToAPI, +} from "~database/entities/Status"; +import { getFromRequest } from "~database/entities/User"; +import type { APIRouteMeta } from "~types/api"; +import type { APIStatus } from "~types/entities/status"; + +export const meta: APIRouteMeta = applyConfig({ + allowedMethods: ["GET"], + ratelimits: { + max: 100, + duration: 60, + }, + route: "/api/v1/statuses/:id/source", + auth: { + required: true, + }, +}); + +/** + * Favourite a post + */ +export default async ( + req: Request, + matchedRoute: MatchedRoute +): Promise => { + const id = matchedRoute.params.id; + + const { user } = await getFromRequest(req); + + if (!user) return errorResponse("Unauthorized", 401); + + const status = await client.status.findUnique({ + where: { id }, + include: statusAndUserRelations, + }); + + // Check if user is authorized to view this status (if it's private) + if (!status || !isViewableByUser(status, user)) + return errorResponse("Record not found", 404); +}; diff --git a/server/api/api/v2/search/index.ts b/server/api/api/v2/search/index.ts new file mode 100644 index 00000000..5e260867 --- /dev/null +++ b/server/api/api/v2/search/index.ts @@ -0,0 +1,60 @@ +import { applyConfig } from "@api"; +import { parseRequest } from "@request"; +import { errorResponse, jsonResponse } from "@response"; +import { getFromRequest } from "~database/entities/User"; +import type { APIRouteMeta } from "~types/api"; + +export const meta: APIRouteMeta = applyConfig({ + allowedMethods: ["GET"], + ratelimits: { + max: 10, + duration: 60, + }, + route: "/api/v2/search", + auth: { + required: false, + oauthPermissions: ["read:search"], + }, +}); + +/** + * Upload new media + */ +export default async (req: Request): Promise => { + const { user } = await getFromRequest(req); + + const { + q, + type, + resolve, + following, + account_id, + max_id, + min_id, + limit, + offset, + } = await parseRequest<{ + q?: string; + type?: string; + resolve?: boolean; + following?: boolean; + account_id?: string; + max_id?: string; + min_id?: string; + limit?: number; + offset?: number; + }>(req); + + if (!user && (resolve || offset)) { + return errorResponse( + "Cannot use resolve or offset without being authenticated", + 401 + ); + } + + return jsonResponse({ + accounts: [], + statuses: [], + hashtags: [], + }); +}; diff --git a/utils/config.ts b/utils/config.ts index 92553c16..f8a9d12c 100644 --- a/utils/config.ts +++ b/utils/config.ts @@ -25,6 +25,13 @@ export interface ConfigType { }; }; + meilisearch: { + host: string; + port: number; + api_key: string; + enabled: boolean; + }; + http: { base_url: string; bind: string; @@ -176,6 +183,12 @@ export const configDefaults: ConfigType = { enabled: false, }, }, + meilisearch: { + host: "localhost", + port: 1491, + api_key: "", + enabled: false, + }, instance: { banner: "", description: "", diff --git a/utils/meilisearch.ts b/utils/meilisearch.ts new file mode 100644 index 00000000..ba097d0b --- /dev/null +++ b/utils/meilisearch.ts @@ -0,0 +1,111 @@ +import { getConfig } from "@config"; +import chalk from "chalk"; +import { client } from "~database/datasource"; +import { Meilisearch } from "meilisearch"; + +const config = getConfig(); + +export const meilisearch = new Meilisearch({ + host: `${config.meilisearch.host}:${config.meilisearch.port}`, + apiKey: config.meilisearch.api_key, +}); + +export const connectMeili = async () => { + if (!config.meilisearch.enabled) return; + + if (await meilisearch.isHealthy()) { + console.log( + `${chalk.green(`✓`)} ${chalk.bold(`Connected to Meilisearch`)}` + ); + } else { + console.error( + `${chalk.red(`✗`)} ${chalk.bold( + `Error while connecting to Meilisearch` + )}` + ); + process.exit(1); + } +}; + +export enum SonicIndexType { + Accounts = "accounts", + Statuses = "statuses", +} + +export const getNthDatabaseAccountBatch = ( + n: number, + batchSize = 1000 +): Promise[]> => { + return client.user.findMany({ + skip: n * batchSize, + take: batchSize, + select: { + id: true, + username: true, + displayName: true, + note: true, + }, + }); +}; + +export const getNthDatabaseStatusBatch = ( + n: number, + batchSize = 1000 +): Promise[]> => { + return client.status.findMany({ + skip: n * batchSize, + take: batchSize, + select: { + id: true, + authorId: true, + content: true, + }, + }); +}; + +export const rebuildSearchIndexes = async ( + indexes: SonicIndexType[], + batchSize = 100 +) => { + if (indexes.includes(SonicIndexType.Accounts)) { + // await sonicIngestor.flushc(SonicIndexType.Accounts); + + const accountCount = await client.user.count(); + + for (let i = 0; i < accountCount / batchSize; i++) { + const accounts = await getNthDatabaseAccountBatch(i, batchSize); + + const progress = Math.round((i / (accountCount / batchSize)) * 100); + + console.log(`${chalk.green(`✓`)} ${progress}%`); + + // Sync with Meilisearch + await meilisearch + .index(SonicIndexType.Accounts) + .addDocuments(accounts); + } + + console.log(`${chalk.green(`✓`)} ${chalk.bold(`Done!`)}`); + } + + if (indexes.includes(SonicIndexType.Statuses)) { + // await sonicIngestor.flushc(SonicIndexType.Statuses); + + const statusCount = await client.status.count(); + + for (let i = 0; i < statusCount / batchSize; i++) { + const statuses = await getNthDatabaseStatusBatch(i, batchSize); + + const progress = Math.round((i / (statusCount / batchSize)) * 100); + + console.log(`${chalk.green(`✓`)} ${progress}%`); + + // Sync with Meilisearch + await meilisearch + .index(SonicIndexType.Statuses) + .addDocuments(statuses); + } + + console.log(`${chalk.green(`✓`)} ${chalk.bold(`Done!`)}`); + } +}; From 553b558c1abdfff2dc80c84bb8e57dc2455cebd8 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:40:10 -1000 Subject: [PATCH 03/86] feat: Add Search endpoint --- cli.ts | 6 +- server/api/api/v2/search/index.ts | 91 +++++++++++++++++++++++++++++-- utils/meilisearch.ts | 65 +++++++++++++++++----- 3 files changed, 138 insertions(+), 24 deletions(-) diff --git a/cli.ts b/cli.ts index a21d9000..1d619948 100644 --- a/cli.ts +++ b/cli.ts @@ -3,7 +3,7 @@ import chalk from "chalk"; import { client } from "~database/datasource"; import { createNewLocalUser } from "~database/entities/User"; import Table from "cli-table"; -import { rebuildSearchIndexes, SonicIndexType } from "@meilisearch"; +import { rebuildSearchIndexes, MeiliIndexType } from "@meilisearch"; const args = process.argv; @@ -542,7 +542,7 @@ switch (command) { ); await rebuildSearchIndexes( - [SonicIndexType.Statuses], + [MeiliIndexType.Statuses], batchSize ); @@ -561,7 +561,7 @@ switch (command) { ); await rebuildSearchIndexes( - [SonicIndexType.Accounts], + [MeiliIndexType.Accounts], batchSize ); diff --git a/server/api/api/v2/search/index.ts b/server/api/api/v2/search/index.ts index 5e260867..958238cd 100644 --- a/server/api/api/v2/search/index.ts +++ b/server/api/api/v2/search/index.ts @@ -1,7 +1,14 @@ import { applyConfig } from "@api"; +import { MeiliIndexType, meilisearch } from "@meilisearch"; import { parseRequest } from "@request"; import { errorResponse, jsonResponse } from "@response"; -import { getFromRequest } from "~database/entities/User"; +import { client } from "~database/datasource"; +import { statusAndUserRelations, statusToAPI } from "~database/entities/Status"; +import { + getFromRequest, + userRelations, + userToAPI, +} from "~database/entities/User"; import type { APIRouteMeta } from "~types/api"; export const meta: APIRouteMeta = applyConfig({ @@ -29,9 +36,9 @@ export default async (req: Request): Promise => { resolve, following, account_id, - max_id, - min_id, - limit, + // max_id, + // min_id, + limit = 20, offset, } = await parseRequest<{ q?: string; @@ -52,9 +59,81 @@ export default async (req: Request): Promise => { ); } + if (limit < 1 || limit > 40) { + return errorResponse("Limit must be between 1 and 40", 400); + } + + let accountResults: { id: string }[] = []; + let statusResults: { id: string }[] = []; + + if (!type || type === "accounts") { + accountResults = ( + await meilisearch.index(MeiliIndexType.Accounts).search<{ + id: string; + }>(q, { + limit: Number(limit) || 10, + offset: Number(offset) || 0, + sort: ["createdAt:desc"], + }) + ).hits; + } + + if (!type || type === "statuses") { + statusResults = ( + await meilisearch.index(MeiliIndexType.Statuses).search<{ + id: string; + }>(q, { + limit: Number(limit) || 10, + offset: Number(offset) || 0, + sort: ["createdAt:desc"], + }) + ).hits; + } + + const accounts = await client.user.findMany({ + where: { + id: { + in: accountResults.map(hit => hit.id), + }, + relationshipSubjects: { + some: { + subjectId: user?.id, + following: following ? true : undefined, + }, + }, + }, + orderBy: { + createdAt: "desc", + }, + include: userRelations, + }); + + const statuses = await client.status.findMany({ + where: { + id: { + in: statusResults.map(hit => hit.id), + }, + author: { + relationshipSubjects: { + some: { + subjectId: user?.id, + following: following ? true : undefined, + }, + }, + }, + authorId: account_id ? account_id : undefined, + }, + orderBy: { + createdAt: "desc", + }, + include: statusAndUserRelations, + }); + return jsonResponse({ - accounts: [], - statuses: [], + accounts: accounts.map(account => userToAPI(account)), + statuses: await Promise.all( + statuses.map(status => statusToAPI(status)) + ), hashtags: [], }); }; diff --git a/utils/meilisearch.ts b/utils/meilisearch.ts index ba097d0b..1a50ff8d 100644 --- a/utils/meilisearch.ts +++ b/utils/meilisearch.ts @@ -14,6 +14,22 @@ export const connectMeili = async () => { if (!config.meilisearch.enabled) return; if (await meilisearch.isHealthy()) { + await meilisearch + .index(MeiliIndexType.Accounts) + .updateSortableAttributes(["createdAt"]); + + await meilisearch + .index(MeiliIndexType.Accounts) + .updateSearchableAttributes(["username", "displayName", "note"]); + + await meilisearch + .index(MeiliIndexType.Statuses) + .updateSortableAttributes(["createdAt"]); + + await meilisearch + .index(MeiliIndexType.Statuses) + .updateSearchableAttributes(["content"]); + console.log( `${chalk.green(`✓`)} ${chalk.bold(`Connected to Meilisearch`)}` ); @@ -27,7 +43,7 @@ export const connectMeili = async () => { } }; -export enum SonicIndexType { +export enum MeiliIndexType { Accounts = "accounts", Statuses = "statuses", } @@ -35,7 +51,7 @@ export enum SonicIndexType { export const getNthDatabaseAccountBatch = ( n: number, batchSize = 1000 -): Promise[]> => { +): Promise[]> => { return client.user.findMany({ skip: n * batchSize, take: batchSize, @@ -44,6 +60,10 @@ export const getNthDatabaseAccountBatch = ( username: true, displayName: true, note: true, + createdAt: true, + }, + orderBy: { + createdAt: "asc", }, }); }; @@ -51,25 +71,26 @@ export const getNthDatabaseAccountBatch = ( export const getNthDatabaseStatusBatch = ( n: number, batchSize = 1000 -): Promise[]> => { +): Promise[]> => { return client.status.findMany({ skip: n * batchSize, take: batchSize, select: { id: true, - authorId: true, content: true, + createdAt: true, + }, + orderBy: { + createdAt: "asc", }, }); }; export const rebuildSearchIndexes = async ( - indexes: SonicIndexType[], + indexes: MeiliIndexType[], batchSize = 100 ) => { - if (indexes.includes(SonicIndexType.Accounts)) { - // await sonicIngestor.flushc(SonicIndexType.Accounts); - + if (indexes.includes(MeiliIndexType.Accounts)) { const accountCount = await client.user.count(); for (let i = 0; i < accountCount / batchSize; i++) { @@ -81,16 +102,22 @@ export const rebuildSearchIndexes = async ( // Sync with Meilisearch await meilisearch - .index(SonicIndexType.Accounts) + .index(MeiliIndexType.Accounts) .addDocuments(accounts); } - console.log(`${chalk.green(`✓`)} ${chalk.bold(`Done!`)}`); + const meiliAccountCount = ( + await meilisearch.index(MeiliIndexType.Accounts).getStats() + ).numberOfDocuments; + + console.log( + `${chalk.green(`✓`)} ${chalk.bold( + `Done! ${meiliAccountCount} accounts indexed` + )}` + ); } - if (indexes.includes(SonicIndexType.Statuses)) { - // await sonicIngestor.flushc(SonicIndexType.Statuses); - + if (indexes.includes(MeiliIndexType.Statuses)) { const statusCount = await client.status.count(); for (let i = 0; i < statusCount / batchSize; i++) { @@ -102,10 +129,18 @@ export const rebuildSearchIndexes = async ( // Sync with Meilisearch await meilisearch - .index(SonicIndexType.Statuses) + .index(MeiliIndexType.Statuses) .addDocuments(statuses); } - console.log(`${chalk.green(`✓`)} ${chalk.bold(`Done!`)}`); + const meiliStatusCount = ( + await meilisearch.index(MeiliIndexType.Statuses).getStats() + ).numberOfDocuments; + + console.log( + `${chalk.green(`✓`)} ${chalk.bold( + `Done! ${meiliStatusCount} statuses indexed` + )}` + ); } }; From b5913b163cf63068029415403c14058b6ac909c3 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:45:01 -1000 Subject: [PATCH 04/86] feat: Auto add new users and statuses to Meilisearch --- database/entities/Status.ts | 5 ++++- database/entities/User.ts | 7 +++++++ utils/meilisearch.ts | 27 +++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/database/entities/Status.ts b/database/entities/Status.ts index d743e715..d025f4ea 100644 --- a/database/entities/Status.ts +++ b/database/entities/Status.ts @@ -28,6 +28,7 @@ import { sanitizeHtml } from "@sanitization"; import { parse } from "marked"; import linkifyStr from "linkify-string"; import linkifyHtml from "linkify-html"; +import { addStausToMeilisearch } from "@meilisearch"; const config = getConfig(); @@ -415,7 +416,6 @@ export const createNewStatus = async (data: { }); // Create notification - if (status.inReplyToPost) { await client.notification.create({ data: { @@ -427,6 +427,9 @@ export const createNewStatus = async (data: { }); } + // Add to search index + await addStausToMeilisearch(status); + return status; }; diff --git a/database/entities/User.ts b/database/entities/User.ts index 6c781fb6..f257756e 100644 --- a/database/entities/User.ts +++ b/database/entities/User.ts @@ -9,6 +9,7 @@ import { client } from "~database/datasource"; import { addEmojiIfNotExists, emojiToAPI, emojiToLysand } from "./Emoji"; import { addInstanceIfNotExists } from "./Instance"; import type { APISource } from "~types/entities/source"; +import { addUserToMeilisearch } from "@meilisearch"; export interface AuthData { user: UserWithRelations | null; @@ -151,6 +152,9 @@ export const fetchRemoteUser = async (uri: string) => { }, }); + // Add to Meilisearch + await addUserToMeilisearch(user); + const emojis = []; for (const emoji of userEmojis) { @@ -224,6 +228,9 @@ export const createNewLocalUser = async (data: { }, }); + // Add to Meilisearch + await addUserToMeilisearch(user); + return await client.user.update({ where: { id: user.id, diff --git a/utils/meilisearch.ts b/utils/meilisearch.ts index 1a50ff8d..af4f4141 100644 --- a/utils/meilisearch.ts +++ b/utils/meilisearch.ts @@ -2,6 +2,7 @@ import { getConfig } from "@config"; import chalk from "chalk"; import { client } from "~database/datasource"; import { Meilisearch } from "meilisearch"; +import type { Status, User } from "@prisma/client"; const config = getConfig(); @@ -48,6 +49,32 @@ export enum MeiliIndexType { Statuses = "statuses", } +export const addStausToMeilisearch = async (status: Status) => { + if (!config.meilisearch.enabled) return; + + await meilisearch.index(MeiliIndexType.Statuses).addDocuments([ + { + id: status.id, + content: status.content, + createdAt: status.createdAt, + }, + ]); +}; + +export const addUserToMeilisearch = async (user: User) => { + if (!config.meilisearch.enabled) return; + + await meilisearch.index(MeiliIndexType.Accounts).addDocuments([ + { + id: user.id, + username: user.username, + displayName: user.displayName, + note: user.note, + createdAt: user.createdAt, + }, + ]); +}; + export const getNthDatabaseAccountBatch = ( n: number, batchSize = 1000 From 34faf28088c9d46f466fa69baea6a4a12546a442 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:46:13 -1000 Subject: [PATCH 05/86] feat: Add error when searching without Meilisearch --- server/api/api/v2/search/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/api/api/v2/search/index.ts b/server/api/api/v2/search/index.ts index 958238cd..1aef1f7c 100644 --- a/server/api/api/v2/search/index.ts +++ b/server/api/api/v2/search/index.ts @@ -1,4 +1,5 @@ import { applyConfig } from "@api"; +import { getConfig } from "@config"; import { MeiliIndexType, meilisearch } from "@meilisearch"; import { parseRequest } from "@request"; import { errorResponse, jsonResponse } from "@response"; @@ -52,6 +53,12 @@ export default async (req: Request): Promise => { offset?: number; }>(req); + const config = getConfig(); + + if (!config.meilisearch.enabled) { + return errorResponse("Meilisearch is not enabled", 501); + } + if (!user && (resolve || offset)) { return errorResponse( "Cannot use resolve or offset without being authenticated", From 04ff66ad8b420f6ad640667268555c20dce03ccd Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:55:19 -1000 Subject: [PATCH 06/86] chore: Add docs for Meilisearch setup --- README.md | 9 +++++++++ docker-compose.yml | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/README.md b/README.md index 47f174ba..f531dae2 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Lysand is extremely fast and can handle tens of thousands of HTTP requests per s - The [Bun Runtime](https://bun.sh), version 1.0.5 or later (usage of the latest version is recommended) - A PostgreSQL database - (Optional but recommended) A Linux-based operating system +- (Optional if you want search) A working Meiliseach instance > **Note**: We will not be offerring support to Windows or MacOS users. If you are using one of these operating systems, please use a virtual machine or container to run Lysand. @@ -125,6 +126,10 @@ RUN chmod +x /docker-entrypoint-initdb.d/init.sh bun migrate ``` +6. (If you want search) +Create a Meilisearch instance (using Docker is recommended). For a [`docker-compose`] file, copy the `meilisearch` service from the [`docker-compose.yml`](docker-compose.yml) file. + +Set up Meiliseach's API key by passing the `MEILI_MASTER_KEY` environment variable to the server. Then, enale and configure search in the config file. ### Running To run the server, simply run the following command: @@ -149,6 +154,10 @@ Some CLI commands that return data as tables can be used in scripts. To do so, y Flags can be used in any order and anywhere in the script (except for the `bun cli` command itself). The command arguments themselves must be in the correct order, however. +### Rebuilding the Search Index + +You may use the `bun cli index rebuild` command to automatically push all posts and users to Meilisearch, if it is configured. This is useful if you have just set up Meilisearch, or if you accidentally deleted something. + ### Using Database Commands The `bun prisma` commands allows you to use Prisma commands without needing to add in environment variables for the database config. Just run Prisma commands as you would normally, replacing `bunx prisma` with `bun prisma`. diff --git a/docker-compose.yml b/docker-compose.yml index e8100507..c0cf5c38 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,6 +35,17 @@ services: restart: unless-stopped networks: - lysand-net + meilisearch: + stdin_open: true + environment: + - MEILI_MASTER_KEY=add_your_key_here + tty: true + networks: + - lysand-net + volumes: + - ./meili-data:/meili_data + image: getmeili/meilisearch:v1.5 + container_name: lysand-meilisearch networks: lysand-net: From e3f5b494cd352fb477339edc918f8877e55e78a4 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:55:42 -1000 Subject: [PATCH 07/86] feat: Better indexing CLI --- cli.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/cli.ts b/cli.ts index 1d619948..ba0b7a72 100644 --- a/cli.ts +++ b/cli.ts @@ -4,6 +4,7 @@ import { client } from "~database/datasource"; import { createNewLocalUser } from "~database/entities/User"; import Table from "cli-table"; import { rebuildSearchIndexes, MeiliIndexType } from "@meilisearch"; +import { getConfig } from "@config"; const args = process.argv; @@ -110,6 +111,8 @@ if (args.length < 3) { const command = args[2]; +const config = getConfig(); + switch (command) { case "help": console.log(help); @@ -521,6 +524,12 @@ switch (command) { break; } case "index": { + if (!config.meilisearch.enabled) { + console.log( + `${chalk.red(`✗`)} Meilisearch is not enabled in the config` + ); + process.exit(1); + } switch (args[3]) { case "rebuild": { const statuses = args.includes("--statuses"); @@ -541,6 +550,8 @@ switch (command) { )}` ); + const timeBefore = performance.now(); + await rebuildSearchIndexes( [MeiliIndexType.Statuses], batchSize @@ -548,7 +559,9 @@ switch (command) { console.log( `${chalk.green(`✓`)} ${chalk.bold( - `Meilisearch index for statuses rebuilt` + `Meilisearch index for statuses rebuilt in ${chalk.bgGreen( + (performance.now() - timeBefore).toFixed(2) + )}ms` )}` ); } @@ -560,6 +573,8 @@ switch (command) { )}` ); + const timeBefore = performance.now(); + await rebuildSearchIndexes( [MeiliIndexType.Accounts], batchSize @@ -567,7 +582,9 @@ switch (command) { console.log( `${chalk.green(`✓`)} ${chalk.bold( - `Meilisearch index for users rebuilt` + `Meilisearch index for users rebuilt in ${chalk.bgGreen( + (performance.now() - timeBefore).toFixed(2) + )}ms` )}` ); } From e47c0f93152118391bcbd239cd5f6d019e822806 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 18:58:17 -1000 Subject: [PATCH 08/86] chore: Document new search API route --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f531dae2..6dd8cb1d 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,7 @@ Tests needed but completed: - `/api/v1/favourites` - `/api/v1/accounts/:id/followers` - `/api/v1/accounts/:id/following` +- `/api/v2/search` Endpoints left: @@ -322,7 +323,6 @@ Endpoints left: - `/api/v1/notifications/:id` - `/api/v1/notifications/clear` - `/api/v1/notifications/:id/dismiss` -- `/api/v2/search` - `/api/v2/instance` - `/api/v1/instance/peers` - `/api/v1/instance/activity` From 38e390c4180070f01c7afc3c8b093089c8bdcb6d Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 20:50:20 -1000 Subject: [PATCH 09/86] feat: Add emoji importing and creation via CLI + support in posts --- bun.lockb | Bin 349144 -> 351344 bytes cli.ts | 392 +++++++++++++++++++++++++++++++++++- database/entities/Status.ts | 14 +- package.json | 1 + 4 files changed, 402 insertions(+), 5 deletions(-) diff --git a/bun.lockb b/bun.lockb index eda9a2f4b8f0397e42b323658663418e9c3ffefd..fca0ffb24e7a955e9396cda3e900bdd5d9345705 100755 GIT binary patch delta 66702 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 H@zVbSY0F(2 delta 65598 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 diff --git a/cli.ts b/cli.ts index ba0b7a72..be12b5ee 100644 --- a/cli.ts +++ b/cli.ts @@ -5,6 +5,10 @@ import { createNewLocalUser } from "~database/entities/User"; import Table from "cli-table"; import { rebuildSearchIndexes, MeiliIndexType } from "@meilisearch"; import { getConfig } from "@config"; +import { uploadFile } from "~classes/media"; +import { getUrl } from "~database/entities/Attachment"; +import { mkdir, exists } from "fs/promises"; +import extract from "extract-zip"; const args = process.argv; @@ -101,7 +105,39 @@ ${chalk.bold("Commands:")} )} Only rebuild the users index (optional) ${chalk.bold("Example:")} ${chalk.bgGray( `bun cli index rebuild --users 200` - )} + )} + ${alignDots(chalk.blue("emoji"), 24)} Manage custom emojis + ${alignDots(chalk.blue("add"))} Add a custom emoji + ${alignDotsSmall(chalk.green("name"))} Name of the emoji + ${alignDotsSmall(chalk.green("url"))} URL of the emoji + ${chalk.bold("Example:")} ${chalk.bgGray( + `bun cli emoji add bun https://bun.com/bun.png` + )} + ${alignDots(chalk.blue("delete"))} Delete a custom emoji + ${alignDotsSmall(chalk.green("name"))} Name of the emoji + ${chalk.bold("Example:")} ${chalk.bgGray( + `bun cli emoji delete bun` + )} + ${alignDots(chalk.blue("list"))} List all custom emojis + ${chalk.bold("Example:")} ${chalk.bgGray(`bun cli emoji list`)} + ${alignDots(chalk.blue("search"))} Search for a custom emoji + ${alignDotsSmall(chalk.green("query"))} Query to search for + ${alignDotsSmall( + chalk.yellow("--local") + )} Search in local emojis (optional, default) + ${alignDotsSmall( + chalk.yellow("--remote") + )} Search in remote emojis (optional) + ${alignDotsSmall(chalk.yellow("--json"))} Output as JSON (optional) + ${alignDotsSmall(chalk.yellow("--csv"))} Output as CSV (optional) + ${chalk.bold("Example:")} ${chalk.bgGray( + `bun cli emoji search bun` + )} + ${alignDots(chalk.blue("import"))} Import a Pleroma emoji pack + ${alignDotsSmall(chalk.green("url"))} URL of the emoji pack + ${chalk.bold("Example:")} ${chalk.bgGray( + `bun cli emoji import https://site.com/neofox/manifest.json` + )} `; if (args.length < 3) { @@ -597,6 +633,360 @@ switch (command) { } break; } + case "emoji": { + switch (args[3]) { + case "add": { + const name = args[4]; + const url = args[5]; + + if (!name || !url) { + console.log(`${chalk.red(`✗`)} Missing name or URL`); + process.exit(1); + } + + const content_type = `image/${url + .split(".") + .pop() + ?.replace("jpg", "jpeg")}}`; + + const emoji = await client.emoji.create({ + data: { + shortcode: name, + url: url, + visible_in_picker: true, + content_type: content_type, + }, + }); + + console.log( + `${chalk.green(`✓`)} Created emoji ${chalk.blue( + emoji.shortcode + )}` + ); + + break; + } + case "delete": { + const name = args[4]; + + if (!name) { + console.log(`${chalk.red(`✗`)} Missing name`); + process.exit(1); + } + + const emoji = await client.emoji.findFirst({ + where: { + shortcode: name, + }, + }); + + if (!emoji) { + console.log(`${chalk.red(`✗`)} Emoji not found`); + process.exit(1); + } + + await client.emoji.delete({ + where: { + id: emoji.id, + }, + }); + + console.log( + `${chalk.green(`✓`)} Deleted emoji ${chalk.blue( + emoji.shortcode + )}` + ); + + break; + } + case "list": { + const emojis = await client.emoji.findMany(); + + console.log( + `${chalk.green(`✓`)} Found ${chalk.blue( + emojis.length + )} emojis` + ); + + for (const emoji of emojis) { + console.log( + `\t${chalk.blue(emoji.shortcode)} ${chalk.gray( + emoji.url + )}` + ); + } + break; + } + case "search": { + const argsWithoutFlags = args.filter( + arg => !arg.startsWith("--") + ); + const query = argsWithoutFlags[4]; + + if (!query) { + console.log(`${chalk.red(`✗`)} Missing query`); + process.exit(1); + } + + const local = args.includes("--local"); + const remote = args.includes("--remote"); + const json = args.includes("--json"); + const csv = args.includes("--csv"); + + const queries: Prisma.EmojiWhereInput[] = []; + + if (local) { + queries.push({ + instanceId: null, + }); + } + + if (remote) { + queries.push({ + instanceId: { + not: null, + }, + }); + } + + const emojis = await client.emoji.findMany({ + where: { + AND: queries, + shortcode: { + contains: query, + mode: "insensitive", + }, + }, + take: 40, + include: { + instance: true, + }, + }); + + if (json || csv) { + if (json) { + console.log(JSON.stringify(emojis, null, 4)); + } + if (csv) { + // Convert the outputted JSON to CSV + + // Remove all object children from each object + const items = emojis.map(emoji => { + const item = { + ...emoji, + instance: undefined, + }; + return item; + }); + const replacer = (key: string, value: any): any => + value === null ? "" : value; // Null values are returned as empty strings + const header = Object.keys(items[0]); + const csv = [ + header.join(","), // header row first + ...items.map(row => + header + .map(fieldName => + // @ts-expect-error This is fine + JSON.stringify(row[fieldName], replacer) + ) + .join(",") + ), + ].join("\r\n"); + + console.log(csv); + } + } else { + console.log( + `${chalk.green(`✓`)} Found ${chalk.blue( + emojis.length + )} emojis` + ); + + const table = new Table({ + head: [ + chalk.white(chalk.bold("Shortcode")), + chalk.white(chalk.bold("Instance URL")), + chalk.white(chalk.bold("URL")), + ], + }); + + for (const emoji of emojis) { + table.push([ + chalk.yellow(`:${emoji.shortcode}:`), + chalk.blue( + emoji.instanceId + ? emoji.instance?.base_url + : "Local" + ), + chalk.gray(emoji.url), + ]); + } + + console.log(table.toString()); + } + + break; + } + case "import": { + const url = args[4]; + + if (!url) { + console.log(`${chalk.red(`✗`)} Missing URL`); + process.exit(1); + } + + const response = await fetch(url); + + if (!response.ok) { + console.log(`${chalk.red(`✗`)} Failed to fetch emoji pack`); + process.exit(1); + } + + const res = (await response.json()) as Record< + string, + { + description: string; + files: string; + homepage: string; + src: string; + src_sha256?: string; + license?: string; + } + >; + + const pack = Object.values(res)[0]; + + // Fetch emoji list from `files`, can be a relative URL + + if (!pack.files) { + console.log(`${chalk.red(`✗`)} Missing files`); + process.exit(1); + } + + let pack_url = pack.files; + + if (!pack.files.includes("http")) { + // Is relative URL to pack manifest URL + pack_url = + url.split("/").slice(0, -1).join("/") + + "/" + + pack.files; + } + + const zip = new File( + [await (await fetch(pack.src)).arrayBuffer()], + "emoji.zip", + { + type: "application/zip", + } + ); + + // Check if the SHA256 hash matches + const hasher = new Bun.SHA256(); + + hasher.update(await zip.arrayBuffer()); + + const hash = hasher.digest("hex"); + + if (pack.src_sha256 && pack.src_sha256 !== hash) { + console.log(`${chalk.red(`✗`)} SHA256 hash does not match`); + console.log( + `${chalk.red(`✗`)} Expected ${chalk.blue( + pack.src_sha256 + )}, got ${chalk.blue(hash)}` + ); + process.exit(1); + } + + // Store file in /tmp + const tempDirectory = `/tmp/lysand-${hash}`; + + if (!(await exists(tempDirectory))) { + await mkdir(tempDirectory); + } + + await Bun.write(`${tempDirectory}/emojis.zip`, zip); + + // Extract zip + await extract(`${tempDirectory}/emojis.zip`, { + dir: tempDirectory, + }); + + // In the format + // emoji_name: emoji_url + const pack_response = (await ( + await fetch(pack_url) + ).json()) as Record; + + let emojisCreated = 0; + + for (const [name, path] of Object.entries(pack_response)) { + // Get emoji URL, as it can be relative + + const emoji = Bun.file(`${tempDirectory}/${path}`); + + const content_type = emoji.type; + + const hash = await uploadFile(emoji as File, config); + + if (!hash) { + console.log( + `${chalk.red(`✗`)} Failed to upload emoji ${name}` + ); + process.exit(1); + } + + const finalUrl = getUrl(hash, config); + + // Check if emoji already exists + const existingEmoji = await client.emoji.findFirst({ + where: { + shortcode: name, + instanceId: null, + }, + }); + + if (existingEmoji) { + console.log( + `${chalk.red(`✗`)} Emoji ${chalk.blue( + name + )} already exists` + ); + continue; + } + + // Create emoji + await client.emoji.create({ + data: { + shortcode: name, + url: finalUrl, + visible_in_picker: true, + content_type: content_type, + }, + }); + + emojisCreated++; + + console.log( + `${chalk.green(`✓`)} Created emoji ${chalk.blue(name)}` + ); + } + + console.log( + `${chalk.green(`✓`)} Imported ${chalk.blue( + emojisCreated + )} emojis` + ); + + break; + } + default: + console.log(`Unknown command ${chalk.blue(command)}`); + break; + } + + break; + } default: console.log(`Unknown command ${chalk.blue(command)}`); break; diff --git a/database/entities/Status.ts b/database/entities/Status.ts index d025f4ea..25b36b7e 100644 --- a/database/entities/Status.ts +++ b/database/entities/Status.ts @@ -325,7 +325,10 @@ export const createNewStatus = async (data: { let mentions = data.mentions || []; - // TODO: Parse emojis + // Parse emojis + const emojis = await parseEmojis(data.content); + + data.emojis = data.emojis ? [...data.emojis, ...emojis] : emojis; // Get list of mentioned users if (mentions.length === 0) { @@ -371,7 +374,7 @@ export const createNewStatus = async (data: { sensitive: data.sensitive, spoilerText: data.spoiler_text, emojis: { - connect: data.emojis?.map(emoji => { + connect: data.emojis.map(emoji => { return { id: emoji.id, }; @@ -453,7 +456,10 @@ export const editStatus = async ( let mentions = data.mentions || []; - // TODO: Parse emojis + // Parse emojis + const emojis = await parseEmojis(data.content); + + data.emojis = data.emojis ? [...data.emojis, ...emojis] : emojis; // Get list of mentioned users if (mentions.length === 0) { @@ -500,7 +506,7 @@ export const editStatus = async ( sensitive: data.sensitive, spoilerText: data.spoiler_text, emojis: { - connect: data.emojis?.map(emoji => { + connect: data.emojis.map(emoji => { return { id: emoji.id, }; diff --git a/package.json b/package.json index d8ce8262..94687490 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "chalk": "^5.3.0", "cli-table": "^0.3.11", "eventemitter3": "^5.0.1", + "extract-zip": "^2.0.1", "html-to-text": "^9.0.5", "ioredis": "^5.3.2", "ip-matching": "^2.1.2", From ab74c17ebd7d86f6c186fceec5379cd71d7b780d Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 20:55:17 -1000 Subject: [PATCH 10/86] fix: Make emoji importing warn you if the emoji already exists earlier --- cli.ts | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/cli.ts b/cli.ts index be12b5ee..3a5cd9b5 100644 --- a/cli.ts +++ b/cli.ts @@ -921,23 +921,6 @@ switch (command) { let emojisCreated = 0; for (const [name, path] of Object.entries(pack_response)) { - // Get emoji URL, as it can be relative - - const emoji = Bun.file(`${tempDirectory}/${path}`); - - const content_type = emoji.type; - - const hash = await uploadFile(emoji as File, config); - - if (!hash) { - console.log( - `${chalk.red(`✗`)} Failed to upload emoji ${name}` - ); - process.exit(1); - } - - const finalUrl = getUrl(hash, config); - // Check if emoji already exists const existingEmoji = await client.emoji.findFirst({ where: { @@ -955,6 +938,23 @@ switch (command) { continue; } + // Get emoji URL, as it can be relative + + const emoji = Bun.file(`${tempDirectory}/${path}`); + + const content_type = emoji.type; + + const hash = await uploadFile(emoji as File, config); + + if (!hash) { + console.log( + `${chalk.red(`✗`)} Failed to upload emoji ${name}` + ); + process.exit(1); + } + + const finalUrl = getUrl(hash, config); + // Create emoji await client.emoji.create({ data: { From d1f9ff650f38b79287edf74a912e5d2b33e9be15 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 20:57:28 -1000 Subject: [PATCH 11/86] chore: Add `cloc` script to count lines of code --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 94687490..f0dc9443 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "prisma": "bun run prisma.ts", "generate": "bun prisma generate", "benchmark:timeline": "bun run benchmarks/timelines.ts", + "cloc": "cloc . --exclude-dir node_modules", "cli": "bun run cli.ts" }, "trustedDependencies": [ From 43d9be5440794db259263b4201e719687157850b Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sat, 2 Dec 2023 20:57:55 -1000 Subject: [PATCH 12/86] Update Lockfile --- bun.lockb | Bin 351344 -> 351344 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bun.lockb b/bun.lockb index fca0ffb24e7a955e9396cda3e900bdd5d9345705..4ade719b0b8cbb410996a940a701ca0dd4dbb39b 100755 GIT binary patch delta 33 pcmeycL-fNA(S{br7N#xC?`N?y#u@1u=oz+uo5j5S+bou Date: Sat, 2 Dec 2023 22:56:23 -1000 Subject: [PATCH 13/86] fix: Fix broken user source --- server/api/api/v1/accounts/search/index.ts | 18 +++++++++----- .../v1/accounts/update_credentials/index.ts | 24 +++++++++++++++---- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/server/api/api/v1/accounts/search/index.ts b/server/api/api/v1/accounts/search/index.ts index 5ec36528..f523e9fe 100644 --- a/server/api/api/v1/accounts/search/index.ts +++ b/server/api/api/v1/accounts/search/index.ts @@ -48,12 +48,18 @@ export default async (req: Request): Promise => { const accounts = await client.user.findMany({ where: { - displayName: { - contains: q, - }, - username: { - contains: q, - }, + OR: [ + { + displayName: { + contains: q, + }, + }, + { + username: { + contains: q, + }, + }, + ], relationshipSubjects: following ? { some: { diff --git a/server/api/api/v1/accounts/update_credentials/index.ts b/server/api/api/v1/accounts/update_credentials/index.ts index ee54270f..cce41f73 100644 --- a/server/api/api/v1/accounts/update_credentials/index.ts +++ b/server/api/api/v1/accounts/update_credentials/index.ts @@ -1,7 +1,11 @@ import { getConfig } from "@config"; import { parseRequest } from "@request"; import { errorResponse, jsonResponse } from "@response"; -import { getFromRequest, userToAPI } from "~database/entities/User"; +import { + getFromRequest, + userRelations, + userToAPI, +} from "~database/entities/User"; import { applyConfig } from "@api"; import { sanitize } from "isomorphic-dompurify"; import { sanitizeHtml } from "@sanitization"; @@ -9,6 +13,7 @@ import { uploadFile } from "~classes/media"; import ISO6391 from "iso-639-1"; import { parseEmojis } from "~database/entities/Emoji"; import { client } from "~database/datasource"; +import type { APISource } from "~types/entities/source"; export const meta = applyConfig({ allowedMethods: ["PATCH"], @@ -63,6 +68,15 @@ export default async (req: Request): Promise => { ALLOWED_ATTR: [], }); + if (!user.source) { + user.source = { + privacy: "public", + sensitive: false, + language: "en", + note: "", + }; + } + if (display_name) { // Check if within allowed display name lengths if ( @@ -90,7 +104,7 @@ export default async (req: Request): Promise => { user.displayName = sanitizedDisplayName; } - if (note) { + if (note && user.source) { // Check if within allowed note length if (sanitizedNote.length > config.validation.max_note_size) { return errorResponse( @@ -111,6 +125,7 @@ export default async (req: Request): Promise => { // Remove emojis user.emojis = []; + (user.source as unknown as APISource).note = sanitizedNote; user.note = sanitizedNote; } @@ -220,7 +235,7 @@ export default async (req: Request): Promise => { (emoji, index, self) => self.findIndex(e => e.id === emoji.id) === index ); - await client.user.update({ + const output = await client.user.update({ where: { id: user.id }, data: { displayName: user.displayName, @@ -240,7 +255,8 @@ export default async (req: Request): Promise => { }, source: user.source || undefined, }, + include: userRelations, }); - return jsonResponse(userToAPI(user)); + return jsonResponse(userToAPI(output)); }; From 53ac9f674579cf07a8959446a5770554b2699404 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sun, 3 Dec 2023 11:27:59 -1000 Subject: [PATCH 14/86] chore: Add auto restart to Meilisearch container in example docker compose --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index c0cf5c38..4e66749e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -46,6 +46,7 @@ services: - ./meili-data:/meili_data image: getmeili/meilisearch:v1.5 container_name: lysand-meilisearch + restart: unless-stopped networks: lysand-net: From 14d96ac9e67a7f27b14f433b5b484ae6f1b59646 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Sun, 3 Dec 2023 15:25:55 -1000 Subject: [PATCH 15/86] feat: Add a Vite server and proxy all non-route requests to it --- bun.lockb | Bin 351344 -> 374984 bytes index.ts | 9 + package.json | 9 +- pages/App.vue | 8 + pages/index.html | 16 ++ pages/login.html | 445 ------------------------------------------- pages/login.vue | 42 ++++ pages/main.ts | 22 +++ pages/style.css | 0 pages/vite-env.d.ts | 1 + pages/vite.config.ts | 30 +++ tsconfig.json | 2 + 12 files changed, 138 insertions(+), 446 deletions(-) create mode 100644 pages/App.vue create mode 100644 pages/index.html delete mode 100644 pages/login.html create mode 100644 pages/login.vue create mode 100644 pages/main.ts create mode 100644 pages/style.css create mode 100644 pages/vite-env.d.ts create mode 100644 pages/vite.config.ts diff --git a/bun.lockb b/bun.lockb index 4ade719b0b8cbb410996a940a701ca0dd4dbb39b..9c4e65df46b350c9a5e5905445eebced79f506e6 100755 GIT binary patch delta 84148 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 Qnb05WjVqGtZj(j-3vbaEYybcN diff --git a/index.ts b/index.ts index 031db5b3..bb4270a4 100644 --- a/index.ts +++ b/index.ts @@ -135,6 +135,15 @@ Bun.serve({ return await file.default(req.clone(), matchedRoute, auth); } else { + // Proxy response from Vite at localhost:5173 + const proxy = await fetch( + req.url.replace(config.http.base_url, "http://localhost:5173") + ); + + if (proxy.status !== 404) { + return proxy; + } + return new Response(undefined, { status: 404, statusText: "Route not found", diff --git a/package.json b/package.json index f0dc9443..62ddf26c 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "private": true, "scripts": { "dev": "bun run index.ts", + "vite:dev": "bunx --bun vite pages", "start": "bun run index.ts", "migrate-dev": "bun prisma migrate dev", "migrate": "bun prisma migrate deploy", @@ -74,6 +75,8 @@ "dependencies": { "@aws-sdk/client-s3": "^3.461.0", "@prisma/client": "^5.6.0", + "@vitejs/plugin-vue": "^4.5.1", + "@vueuse/head": "^2.0.0", "blurhash": "^2.0.5", "bullmq": "^4.14.4", "chalk": "^5.3.0", @@ -94,6 +97,10 @@ "prisma": "^5.6.0", "prisma-redis-middleware": "^4.8.0", "semver": "^7.5.4", - "sharp": "^0.33.0-rc.2" + "sharp": "^0.33.0-rc.2", + "vite": "^5.0.4", + "vue": "^3.3.9", + "vue-router": "^4.2.5", + "vue-tsc": "^1.8.24" } } \ No newline at end of file diff --git a/pages/App.vue b/pages/App.vue new file mode 100644 index 00000000..1e5d5a5f --- /dev/null +++ b/pages/App.vue @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/pages/index.html b/pages/index.html new file mode 100644 index 00000000..03a73837 --- /dev/null +++ b/pages/index.html @@ -0,0 +1,16 @@ + + + + + + + + Vite + Vue + TS + + + +
+ + + + \ No newline at end of file diff --git a/pages/login.html b/pages/login.html deleted file mode 100644 index 4eb3abf5..00000000 --- a/pages/login.html +++ /dev/null @@ -1,445 +0,0 @@ - - - - Login with Lysand - {{STYLES}} - - - - - -
-
-
-
- -
- -
-
- -
-
- -
-
- -
-
- -
- -
-
-
-
- \ No newline at end of file diff --git a/pages/login.vue b/pages/login.vue new file mode 100644 index 00000000..7632b80e --- /dev/null +++ b/pages/login.vue @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/pages/main.ts b/pages/main.ts new file mode 100644 index 00000000..d48aedce --- /dev/null +++ b/pages/main.ts @@ -0,0 +1,22 @@ +import { createApp } from "vue"; +import "./style.css"; +import { createRouter, createWebHistory } from "vue-router"; +import Login from "./login.vue"; +import App from "./App.vue"; + +const Home = { template: "
Home
" }; + +const routes = [ + { path: "/", component: Home }, + { path: "/oauth/login", component: Login }, +]; + +const router = createRouter({ + history: createWebHistory(), + routes, +}); + +const app = createApp(App); +app.use(router); + +app.mount("#app"); diff --git a/pages/style.css b/pages/style.css new file mode 100644 index 00000000..e69de29b diff --git a/pages/vite-env.d.ts b/pages/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/pages/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/pages/vite.config.ts b/pages/vite.config.ts new file mode 100644 index 00000000..d94dfe72 --- /dev/null +++ b/pages/vite.config.ts @@ -0,0 +1,30 @@ +import { defineConfig } from "vite"; +import UnoCSS from "unocss/vite"; +import vue from "@vitejs/plugin-vue"; + +export default defineConfig({ + base: "/", + build: { + outDir: "../vite-dist", + }, + // main.ts is in pages/ directory + resolve: { + alias: { + vue: "vue/dist/vue.esm-bundler", + }, + }, + server: { + hmr: { + clientPort: 5173, + }, + }, + ssr: { + noExternal: ["@prisma/client"], + }, + plugins: [ + UnoCSS({ + mode: "vue-scoped", + }), + vue(), + ], +}); diff --git a/tsconfig.json b/tsconfig.json index 1461898f..d68e047c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,7 +31,9 @@ }, "include": [ "*.ts", + "*.vue", "**/*.ts", + "**/*.vue", "server/api/.well-known/**/*.ts" ] } From 947c1f4991f24f96c5cf5ff5939f7465b91583e4 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Wed, 6 Dec 2023 12:10:22 -1000 Subject: [PATCH 16/86] Add full OpenID connect provider support --- bun.lockb | Bin 374984 -> 386144 bytes cli.ts | 69 +++++++ config/config.example.toml | 12 ++ package.json | 4 +- pages/App.vue | 2 +- pages/components/LoginInput.vue | 29 +++ pages/login.vue | 61 ++++-- pages/main.ts | 3 +- pages/uno.css | 155 --------------- pages/vite.config.ts | 2 +- prisma.ts | 14 +- .../20231206215508_add_openid/migration.sql | 20 ++ prisma/schema.prisma | 54 +++-- server/api/auth/login/index.ts | 19 +- server/api/oauth/authorize-external/index.ts | 84 ++++++++ server/api/oauth/authorize/index.ts | 38 ---- server/api/oauth/callback/[issuer]/index.ts | 187 ++++++++++++++++++ server/api/oauth/providers/index.ts | 31 +++ temp/flow_0exywktgkcq6wjwa691mat | 1 + temp/flow_2c0ojqmxbidvqt6g964fnn | 1 + temp/flow_366pnjfy46z7a6ijrv2s2e | 1 + temp/flow_9gk2f91f7rpr4zz1lza4n8 | 1 + temp/flow_9xab9zbynrche1s5oqpko | 1 + temp/flow_adnvd9wrsykciwdbfz9da8 | 1 + temp/flow_b7w5jcwll3tee0l4tq9ejw | 1 + temp/flow_bcw2mcd2l3pbfsvwp4t1tp | 1 + temp/flow_be9y4se653i4ks1qdvhiu5 | 1 + temp/flow_bwluoig4sco7i5jrau0u | 1 + temp/flow_ckkbeibg93nohnk87ljuk | 1 + temp/flow_ggo4fp8ui1ejwinui77ycf | 1 + temp/flow_jp0vw18g9qe63tucqixezt | 1 + temp/flow_llg9kgdkbdmy8m7e023lm | 1 + temp/flow_lp0v28msillw76xmk83sx | 1 + temp/flow_lpmjxmln4o2axlfu9kb0n | 1 + temp/flow_nreir9hwdpjnylbl79ydl | 1 + temp/flow_rx8dih8r80gzhlosl1glw | 1 + temp/flow_thi2f1athskd4cculln0n | 1 + temp/flow_uiahlqg3uolo9x007xwhf | 1 + temp/flow_vf6gxl8c4s6583pxpelsc | 1 + temp/flow_vwgyv1bz05d69quclfqclo | 1 + temp/flow_w39k8p9uvnvcmj61wuzh | 1 + temp/flow_yjmm00zgy1ainhm9i6ggp | 1 + temp/flow_z26sq4gy8aiyfr835akz2d | 1 + utils/config.ts | 14 ++ utils/constants.ts | 6 + utils/oauth.ts | 2 + utils/temp.ts | 20 ++ 47 files changed, 604 insertions(+), 247 deletions(-) create mode 100644 pages/components/LoginInput.vue delete mode 100644 pages/uno.css create mode 100644 prisma/migrations/20231206215508_add_openid/migration.sql create mode 100644 server/api/oauth/authorize-external/index.ts delete mode 100644 server/api/oauth/authorize/index.ts create mode 100644 server/api/oauth/callback/[issuer]/index.ts create mode 100644 server/api/oauth/providers/index.ts create mode 100644 temp/flow_0exywktgkcq6wjwa691mat create mode 100644 temp/flow_2c0ojqmxbidvqt6g964fnn create mode 100644 temp/flow_366pnjfy46z7a6ijrv2s2e create mode 100644 temp/flow_9gk2f91f7rpr4zz1lza4n8 create mode 100644 temp/flow_9xab9zbynrche1s5oqpko create mode 100644 temp/flow_adnvd9wrsykciwdbfz9da8 create mode 100644 temp/flow_b7w5jcwll3tee0l4tq9ejw create mode 100644 temp/flow_bcw2mcd2l3pbfsvwp4t1tp create mode 100644 temp/flow_be9y4se653i4ks1qdvhiu5 create mode 100644 temp/flow_bwluoig4sco7i5jrau0u create mode 100644 temp/flow_ckkbeibg93nohnk87ljuk create mode 100644 temp/flow_ggo4fp8ui1ejwinui77ycf create mode 100644 temp/flow_jp0vw18g9qe63tucqixezt create mode 100644 temp/flow_llg9kgdkbdmy8m7e023lm create mode 100644 temp/flow_lp0v28msillw76xmk83sx create mode 100644 temp/flow_lpmjxmln4o2axlfu9kb0n create mode 100644 temp/flow_nreir9hwdpjnylbl79ydl create mode 100644 temp/flow_rx8dih8r80gzhlosl1glw create mode 100644 temp/flow_thi2f1athskd4cculln0n create mode 100644 temp/flow_uiahlqg3uolo9x007xwhf create mode 100644 temp/flow_vf6gxl8c4s6583pxpelsc create mode 100644 temp/flow_vwgyv1bz05d69quclfqclo create mode 100644 temp/flow_w39k8p9uvnvcmj61wuzh create mode 100644 temp/flow_yjmm00zgy1ainhm9i6ggp create mode 100644 temp/flow_z26sq4gy8aiyfr835akz2d create mode 100644 utils/constants.ts create mode 100644 utils/temp.ts diff --git a/bun.lockb b/bun.lockb index 9c4e65df46b350c9a5e5905445eebced79f506e6..cc2d4ad118a6d9de796f321c309f144bb87840f8 100755 GIT binary patch delta 79532 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 z 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 Yj`WB0ta1FhoBCyqYa!*k-EGeQ1CmG#vH$=8 delta 73320 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 diff --git a/cli.ts b/cli.ts index 3a5cd9b5..dbe29f0f 100644 --- a/cli.ts +++ b/cli.ts @@ -73,6 +73,19 @@ ${chalk.bold("Commands:")} ${chalk.bold("Example:")} ${chalk.bgGray( `bun cli user search admin` )} + ${alignDots( + chalk.blue("connect-openid") + )} Connect an OpenID account to a local account + ${alignDotsSmall( + chalk.green("username") + )} Username of the local account + ${alignDotsSmall(chalk.green("issuerId"))} ID of the OpenID issuer + ${alignDotsSmall( + chalk.green("serverId") + )} ID of the user on the OpenID server + ${chalk.bold("Example:")} ${chalk.bgGray( + `bun cli user connect-openid admin google 123456789` + )} ${alignDots(chalk.blue("note"), 24)} Manage notes ${alignDots(chalk.blue("delete"))} Delete a note ${alignDotsSmall(chalk.green("id"))} ID of the note @@ -403,6 +416,62 @@ switch (command) { break; } + case "connect-openid": { + const username = args[4]; + const issuerId = args[5]; + const serverId = args[6]; + + if (!username || !issuerId || !serverId) { + console.log( + `${chalk.red(`✗`)} Missing username, issuer or ID` + ); + process.exit(1); + } + + const user = await client.user.findFirst({ + where: { + username: username, + }, + }); + + if (!user) { + console.log(`${chalk.red(`✗`)} User not found`); + process.exit(1); + } + + const issuer = config.oidc.providers.find( + p => p.id === issuerId + ); + + if (!issuer) { + console.log(`${chalk.red(`✗`)} Issuer not found`); + process.exit(1); + } + + await client.user.update({ + where: { + id: user.id, + }, + data: { + linkedOpenIdAccounts: { + create: { + issuerId: issuerId, + serverId: serverId, + }, + }, + }, + }); + + console.log( + `${chalk.green( + `✓` + )} Connected OpenID account to user ${chalk.blue( + user.username + )}` + ); + + break; + } default: console.log(`Unknown command ${chalk.blue(command)}`); break; diff --git a/config/config.example.toml b/config/config.example.toml index 8af0ecd9..0d4ae856 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -24,6 +24,18 @@ port = 40007 api_key = "" enabled = true +# Delete this section if you don't want to use custom OAuth providers +# This is an example configuration +# The provider MUST support OpenID Connect with .well-known discovery +# Most notably, GitHub does not support this +[[oidc.providers]] +name = "CPlusPatch ID" +id = "cpluspatch-id" +url = "https://id.cpluspatch.com/application/o/lysand-testing/" +client_id = "XXXXXXXXXXXXXXXX" +client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +icon = "https://cpluspatch.com/images/icons/logo.svg" + [http] base_url = "https://lysand.social" bind = "http://localhost" diff --git a/package.json b/package.json index 62ddf26c..a16ddb2d 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "migrate-dev": "bun prisma migrate dev", "migrate": "bun prisma migrate deploy", "lint": "eslint --config .eslintrc.cjs --ext .ts .", - "prisma": "bun run prisma.ts", + "prisma": "DATABASE_URL=$(bun run prisma.ts) bunx prisma", "generate": "bun prisma generate", "benchmark:timeline": "bun run benchmarks/timelines.ts", "cloc": "cloc . --exclude-dir node_modules", @@ -94,11 +94,13 @@ "linkifyjs": "^4.1.3", "marked": "^9.1.2", "meilisearch": "^0.36.0", + "oauth4webapi": "^2.4.0", "prisma": "^5.6.0", "prisma-redis-middleware": "^4.8.0", "semver": "^7.5.4", "sharp": "^0.33.0-rc.2", "vite": "^5.0.4", + "vite-ssr": "^0.17.1", "vue": "^3.3.9", "vue-router": "^4.2.5", "vue-tsc": "^1.8.24" diff --git a/pages/App.vue b/pages/App.vue index 1e5d5a5f..6f8f7da5 100644 --- a/pages/App.vue +++ b/pages/App.vue @@ -1,6 +1,6 @@