From b7c096b3ec5836ca081b2f1ce028e57ad02e10ff Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Fri, 29 Mar 2024 15:14:20 +0000 Subject: [PATCH] chore: general house keeping --- .data/.gitignore | 3 +- .env.local.example | 10 +++ app/api/.gitignore | 1 + app/panel/about/page.tsx | 26 ------ app/panel/cases/[id]/Cat.tsx | 132 ++++++++++++++++++++++++++++++ bun.lockb | Bin 258372 -> 262211 bytes lib/auth/index.ts | 16 ++++ lib/core/index.ts | 138 +++++++++++++++++++++++++++++++ lib/db/enums.ts | 87 ++++++++++++++++++++ lib/db/types.ts | 153 +++++++++++++++++++++++++++++++++-- lib/events/index.ts | 15 +++- lib/query/queryProvider.tsx | 16 ++++ lib/winbox/WindowTrigger.tsx | 30 +++++++ lib/winbox/index.ts | 3 + middleware.js | 2 +- package.json | 6 +- 16 files changed, 602 insertions(+), 36 deletions(-) create mode 100644 app/api/.gitignore delete mode 100644 app/panel/about/page.tsx create mode 100644 app/panel/cases/[id]/Cat.tsx create mode 100644 lib/core/index.ts create mode 100644 lib/db/enums.ts create mode 100644 lib/query/queryProvider.tsx create mode 100644 lib/winbox/WindowTrigger.tsx create mode 100644 lib/winbox/index.ts diff --git a/.data/.gitignore b/.data/.gitignore index d6f0da1..2467226 100644 --- a/.data/.gitignore +++ b/.data/.gitignore @@ -1,2 +1,3 @@ antispam -**/*.json \ No newline at end of file +**/*.json +_disabled \ No newline at end of file diff --git a/.env.local.example b/.env.local.example index 9ccad9d..e0d3205 100644 --- a/.env.local.example +++ b/.env.local.example @@ -27,3 +27,13 @@ NTFY_PASSWORD= # Platform Account ID PLATFORM_ACCOUNT_ID=01FC17E1WTM2BGE4F3ARN3FDAF + +# Integrations +INTEGRATION_ZAMMAD_ENDPOINT=https://help.revolt.chat/api/v1 +INTEGRATION_ZAMMAD_ACCESS_TOKEN= +INTEGRATION_AUTHENTIK_ENDPOINT=https://sso.revolt.chat/api/v3 +INTEGRATION_AUTHENTIK_API_TOKEN= +INTEGRATION_PLANE_ENDPOINT=https://plane.revolt.chat/api/v1 +INTEGRATION_PLANE_API_TOKEN= +INTEGRATION_AFFINE_ENDPOINT=https://affine.revolt.wtf/api/demon-core +INTEGRATION_AFFINE_TOKEN= diff --git a/app/api/.gitignore b/app/api/.gitignore new file mode 100644 index 0000000..8a1778b --- /dev/null +++ b/app/api/.gitignore @@ -0,0 +1 @@ +tempGdpr \ No newline at end of file diff --git a/app/panel/about/page.tsx b/app/panel/about/page.tsx deleted file mode 100644 index f4151ba..0000000 --- a/app/panel/about/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { PageTitle } from "@/components/common/navigation/PageTitle"; -import { Metadata } from "next"; - -import { Text } from "@radix-ui/themes"; - -import pkg from "../../../package.json"; - -export const metadata: Metadata = { - title: "About", - description: - "Version information and other useful tidbits about this software.", -}; - -export default async function About() { - return ( - <> - - - Version {pkg.version} ·{" "} - - Source code - - - - ); -} diff --git a/app/panel/cases/[id]/Cat.tsx b/app/panel/cases/[id]/Cat.tsx new file mode 100644 index 0000000..57c3ada --- /dev/null +++ b/app/panel/cases/[id]/Cat.tsx @@ -0,0 +1,132 @@ +import { Badge, Flex, Text } from "@radix-ui/themes"; + +export function Cat() { + return ( + <> + + Problems with the case + + + + Invalid Report(s) don't make sense + + + False Report(s) are clearly false + + + Spam Report(s) are clearly spam + + + Not Enough Evidence Not enough evidence to act on report + + + Clarification Needed More information is needed + + + Acknowledge Report(s) will be acknowledged but no action taken + + + Ignore + + + + + Reasons for acting on case + + + + Extremism Violent extremism + {" "} + + Misinformation Misinformation & conspiracy theories + {" "} + + Hate Conduct Hate speech or hateful conduct + {" "} + + Self Harm Promoting, encouraging or glorifying self-harm or + suicide + {" "} + + Illegal Behaviour Promoting, organising or engaging in illegal + behaviour + + + Off Platform Promoting off-platform content in violation of + usage policy + + + Illegal Content Content deemed illegal + + + Harassment Content designed to harass or degrade someone (incl. + death threats, doxing, ignoring someoneone's privacy) + + + Raiding Participating in a raid + + + Rights Infringement Content violating intellectual property or + other rights + + + Gore Real-life violence, gore, or animal cruelty + + + Malware + + + Impersonation + + + Underage Sexual Content Soliciting or providing sexual content + to minors + + + Underage Sexual Conduct Engaging in sexual conduct with minors + + + Underage Unsafe Conduct Minors engaging in any conduct that may + put their safety at risk + + + Explicit Content Sharing explicit content in places where it + can't be age restricted + + + Unsolicited Advertising + + + Fraud Financial scams or other types of fraud + + + Account Trade Buying or selling of Revolt accounts + + + Artificial Growth Providing or using means to artificially grow + servers + + + Evasion Evasion of permanent platform-level moderation actions + + + Hacking Engaging in hacking such as phishing, malware, DoS, etc + + + Unauthorised Access Attempts to hack or otherwise gain + unauthorised access to our service + + + Abuse Abusing our server resources + + + User Bot Automated activity from user not initiated by the user + + + Misleading Team Providing false or deceptive reports to our + team + + + + ); +} diff --git a/bun.lockb b/bun.lockb index 38069d9605f13ae35b380fb28216f41c6337818f..fc87b2c4f51568862f116c015367800d394f6310 100755 GIT binary patch delta 53514 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 delta 52214 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 diff --git a/lib/auth/index.ts b/lib/auth/index.ts index 9e63b20..5641399 100644 --- a/lib/auth/index.ts +++ b/lib/auth/index.ts @@ -1,3 +1,4 @@ +import { getServerSession } from "next-auth"; import { useSession } from "next-auth/react"; type AuthorisedUser = { @@ -41,3 +42,18 @@ export function useAuthorisedUser(allowNull = false): AuthorisedUser { }; } } + +/** + * Check whether the currently authorised user has a given scope and return them if such + * @param scope Required scope + * @returns User email + */ +export async function useScopedUser(scope: string) { + const session = await getServerSession(); + if (!session?.user?.email) throw "Unauthenticated!"; + + // TODO: RBAC code + console.debug(`Check ${session.user.email} against scope ${scope}`); + + return session.user.email; +} diff --git a/lib/core/index.ts b/lib/core/index.ts new file mode 100644 index 0000000..225c3e3 --- /dev/null +++ b/lib/core/index.ts @@ -0,0 +1,138 @@ +import { Filter } from "mongodb"; +import { Message, User } from "revolt-api"; +import { ulid } from "ulid"; + +import { + ChangeLogDocument, + changelog, + channels, + messages, + users, +} from "../db/types"; +import { publish, publishPrivate } from "../events"; + +/** + * Send a message + * @param message Message + */ +export async function sendMessage(message: Omit) { + const doc: Message = { + _id: ulid(), + ...message, + }; + + await publish(message.channel, { + type: "Message", + ...doc, + }); + + await messages().insertOne(doc); +} + +/** + * Create or find existing DM between users + * @param userA User A + * @param userB User B + * @returns DM Channel + */ +export async function createOrFindDM(userA: string, userB: string) { + let dm = await channels().findOne({ + channel_type: "DirectMessage", + recipients: { $all: [userA, userB] }, + }); + + if (!dm) { + dm = { + _id: ulid(), + channel_type: "DirectMessage", + active: true, + recipients: [userA, userB], + }; + + await channels().insertOne(dm); + + for (const user of [userA, userB]) + await publishPrivate(user, { + type: "ChannelCreate", + ...dm, + }); + } + + return dm; +} + +/** + * Send a platform alert from moderation user + * @param userId Target user + * @param content Content to send + */ +export async function sendPlatformAlert(userId: string, content: string) { + const dm = await createOrFindDM(userId, process.env.PLATFORM_ACCOUNT_ID!); + + await sendMessage({ + channel: dm._id, + author: process.env.PLATFORM_ACCOUNT_ID!, + content, + }); +} + +/** + * Create a changelog entry + * @param userEmail User email + * @param change Change + */ +export async function createChangelog( + userEmail: string, + change: Omit, +) { + const document = { + _id: ulid(), + userEmail, + ...change, + } as ChangeLogDocument; + await changelog().insertOne(document); + return document; +} + +/** + * Fetch messages from channel with authors + */ +export async function fetchMessages(query: Filter): Promise<{ + messages: Message[]; + authors: Record; +}> { + const recentMessages = await messages() + .find(query, { + sort: { + _id: -1, + }, + limit: 200, + }) + .toArray(); + + const authors = await users() + .find( + { + _id: { + $in: [...new Set(recentMessages.map((message) => message.author))], + }, + }, + { + projection: { + _id: 1, + username: 1, + discriminator: 1, + avatar: 1, + }, + }, + ) + .toArray() + .then((arr) => + arr.reduce((d, v) => ({ ...d, [v._id]: v }), {} as Record), + ); + + return { + messages: recentMessages, + authors, + }; +} diff --git a/lib/db/enums.ts b/lib/db/enums.ts new file mode 100644 index 0000000..bd650f8 --- /dev/null +++ b/lib/db/enums.ts @@ -0,0 +1,87 @@ +import { CaseDocument } from "./types"; + +export const TYPES_PROBLEM_WITH_CASE = { + Invalid: "Report(s) don't make sense or there isn't a rule violation", + False: "Clearly false", + "Report Spam": "Clearly spam", + "Not Enough Evidence": "Not enough evidence to act on report", + "Clarification Needed": "More information is needed", + "Bridged Content": "Content came from a remote service", + Acknowledge: "Report(s) will be acknowledged but no action taken", + Duplicate: "Reported content has already been dealt with", + Ignore: "", +}; + +export const TYPES_PROBLEM_WITH_CASE_KEYS = Object.keys( + TYPES_PROBLEM_WITH_CASE, +).toSorted() as (keyof typeof TYPES_PROBLEM_WITH_CASE)[]; + +export const TYPES_VALID_CATEGORY = { + Extremism: "Violent extremism", + Misinformation: "Misinformation & conspiracy theories", + "Hate Conduct": "Hate speech or hateful conduct", + "Self Harm": "Promoting, encouraging or glorifying self-harm or suicide", + "Illegal Behaviour": "Promoting, organising or engaging in illegal behaviour", + "Off Platform": "Promoting off-platform content in violation of usage policy", + "Illegal Content": "Content deemed illegal", + Harassment: + "Content designed to harass or degrade someone (incl. death threats, doxing, ignoring someone's privacy)", + Raiding: "Participating in a raid", + "Rights Infringement": + "Content violating intellectual property or other rights", + Gore: "Real-life violence, gore, or animal cruelty", + Malware: "", + Impersonation: "", + Underage: "User is not within platform age requirements", + "Underage Sexual Content": "Soliciting or providing sexual content to minors", + "Underage Sexual Conduct": "Engaging in sexual conduct with minors", + "Underage Unsafe Conduct": + "Minors engaging in any conduct that may put their safety at risk", + "Explicit Content": + "Sharing explicit content in places where it can't be age restricted", + "Unsolicited Advertising": "", + Fraud: "Financial scams or other types of fraud", + "Account Trade": "Buying or selling of Revolt accounts", + "Artificial Growth": "Providing or using means to artificially grow servers", + Evasion: "Evasion of permanent platform-level moderation actions", + Hacking: "Engaging in hacking such as phishing, malware, DoS, etc", + "Unauthorised Access": + "Attempts to hack or otherwise gain unauthorised access to our service", + Abuse: "Abusing our server resources", + Spam: "Content or users with only intent to spam", + "User Bot": "Automated activity from user not initiated by the user", + "Misleading Team": "Providing false or deceptive reports to our team", +}; + +export const TYPES_VALID_CATEGORY_KEYS = Object.keys( + TYPES_VALID_CATEGORY, +).toSorted() as (keyof typeof TYPES_VALID_CATEGORY)[]; + +export function reportCategoryTemplateResolutionResponse( + key: CaseDocument["category"], +) { + switch (key[0]) { + case "Invalid": + return "These report(s) are invalid and no further action can be taken at this time.\nThis may be because:\n- No platform rules are being broken\n- The report doesn't make any sense\n- The reason provided doesn't apply to the content reported"; + case "False": + return "These report(s) are clearly false and no action will be taken.\nRepeated false reports may lead to additional action against your account."; + case "Report Spam": + return "Report spam may lead to additional action against your account."; + case "Not Enough Evidence": + return "These report(s) have not been actioned at this time due to a lack of supporting evidence, if you have additional information to support your report, please either report individual relevant messages or send an email to contact@revolt.chat."; + case "Clarification Needed": + return "These report(s) need clarification and no further action can be taken at this time.\nIf you have additional information to support your report, please either report individual relevant messages or send an email to contact@revolt.chat."; + case "Bridged Content": + return "These report(s) concern bridged content and we cannot take any further action.\nIf appropriate, the content has been deleted.\nPlease notify the server's moderation team to deal with the matter on their end.\nIf you find the moderation team to be unresponsive, please follow up by reporting the server."; + case "Acknowledge": + return "These report(s) have been acknowledged, however no action will be taken at this time."; + case "Duplicate": + return "Appropriate action has already been taken in regards to the reported content, no further action will be taken."; + case "Ignore": + return "-no valid response-"; + default: + if (key.length === 0) return "-no category selected-"; + + return "Report(s) have been actioned and appropriate action has been taken."; + } +} diff --git a/lib/db/types.ts b/lib/db/types.ts index 9648ec3..c438be6 100644 --- a/lib/db/types.ts +++ b/lib/db/types.ts @@ -1,12 +1,97 @@ import { + Bot, Channel, + Invite, Member, Message, ReportedContent, Server, User, } from "revolt-api"; -import { col } from "."; + +import { col, db } from "."; +import { TYPES_PROBLEM_WITH_CASE, TYPES_VALID_CATEGORY } from "./enums"; + +export type ChangeLogDocument = { + _id: string; + userEmail: string; +} & ( + | ({ + object: { + type: "Server"; + id: string; + }; + } & ( + | { + type: "comment"; + text: string; + } + | { + type: "server/discover/approve"; + } + | { + type: "server/discover/reject" | "server/discover/delist"; + reason: string; + } + )) + | ({ + object: { + type: "Bot"; + id: string; + }; + } & ( + | { + type: "comment"; + text: string; + } + | { + type: "bot/discover/approve"; + } + | { + type: "bot/discover/reject" | "bot/discover/delist"; + reason: string; + } + )) + | ({ + object: { + type: "Case"; + id: string; + }; + } & ( + | { + type: "comment"; + text: string; + } + | { + type: "case/categorise"; + category: CaseDocument["category"]; + } + | { + type: "case/status"; + status: CaseDocument["status"]; + } + | { + type: "case/title"; + title: string; + } + | { + type: "case/add_report"; + reportId: string; + } + | { + type: "case/notify"; + userIds: string; + content: string; + } + )) +); + +/** + * Use `revolt_admin/changelog` collection + */ +export function changelog() { + return db("revolt_admin").collection("changelog"); +} export type CaseDocument = { _id: string; @@ -14,7 +99,11 @@ export type CaseDocument = { notes?: string; author: string; status: "Open" | "Closed"; - closed_at?: string; + category: ( + | keyof typeof TYPES_PROBLEM_WITH_CASE + | keyof typeof TYPES_VALID_CATEGORY + )[]; + closed_at?: Date; }; /** @@ -30,14 +119,15 @@ export type ReportDocument = { content: ReportedContent; additional_context: string; case_id?: string; + _temp_escalated?: boolean; } & ( | { status: "Created" } | ({ - type: "Rejected" | "Resolved"; + status: "Rejected" | "Resolved"; closed_at?: string; } & ( - | { type: "Rejected"; rejection_reason?: string } - | { type: "Resolved" } + | { status: "Rejected"; rejection_reason?: string } + | { status: "Resolved" } )) ); @@ -77,6 +167,57 @@ export function servers() { return col("servers"); } +/** + * Use `invites` collection + */ +export function invites() { + return col("channel_invites"); +} + +/** + * Use `analytics/servers` collection + */ +export function serverAnalytics() { + return db("analytics").collection<{ + _id: string; + members: number; + volume: number; + discoverable: boolean; + }>("servers"); +} + +export type DiscoverRequestDocument = { + _id: string; +} & ({ type: "Server"; serverId: string } | { type: "Bot"; botId: string }); + +/** + * Use `revolt_admin/discover_requests` collection + */ +export function adminDiscoverRequests() { + return db("revolt_admin").collection( + "discover_requests", + ); +} + +/** + * Use `bots` collection + */ +export function bots() { + return col("bots"); +} + +/** + * Use `analytics/bots` collection + */ +export function botAnalytics() { + return db("analytics").collection<{ + _id: string; + servers: number; + usage: number; + discoverable: boolean; + }>("bots"); +} + /** * Use `channels` collection */ @@ -110,7 +251,7 @@ export function messages() { */ export function accounts() { return col<{ _id: string; email: string; disabled: boolean; spam: boolean }>( - "accounts" + "accounts", ); } diff --git a/lib/events/index.ts b/lib/events/index.ts index 9ae190f..f885c84 100644 --- a/lib/events/index.ts +++ b/lib/events/index.ts @@ -1,4 +1,4 @@ -import { createClient, RedisClientType } from "@redis/client"; +import { RedisClientType, createClient } from "@redis/client"; import type { ProtocolV1 } from "revolt.js/lib/events/v1"; export { RedisEventListener } from "./eventListener"; @@ -39,3 +39,16 @@ export async function newRedis() { export async function publish(topic: string, message: ProtocolV1["server"]) { (await redis()).publish(topic, JSON.stringify(message)); } + +/** + * Publish to private topic + * @param topic Topic + * @param message Message + */ +export async function publishPrivate( + topic: string, + message: ProtocolV1["server"], +) { + const privateTopic = `${topic}!`; + await publish(privateTopic, message); +} diff --git a/lib/query/queryProvider.tsx b/lib/query/queryProvider.tsx new file mode 100644 index 0000000..39a03fb --- /dev/null +++ b/lib/query/queryProvider.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { ReactNode } from "react"; + +export const queryClient = new QueryClient(); + +export async function ClientQueryProvider({ + children, +}: { + children: ReactNode; +}) { + return ( + {children} + ); +} diff --git a/lib/winbox/WindowTrigger.tsx b/lib/winbox/WindowTrigger.tsx new file mode 100644 index 0000000..1244ec0 --- /dev/null +++ b/lib/winbox/WindowTrigger.tsx @@ -0,0 +1,30 @@ +"use client"; + +import { ReactNode } from "react"; + +export function WindowTrigger({ + url, + title, + children, +}: { + url: string; + title: string; + children: ReactNode; +}) { + return ( + { + e.stopPropagation(); + new window.WinBox(title, { + url, + }); + }} + > + {children} + + ); +} diff --git a/lib/winbox/index.ts b/lib/winbox/index.ts new file mode 100644 index 0000000..499983a --- /dev/null +++ b/lib/winbox/index.ts @@ -0,0 +1,3 @@ +"use client"; + +import "winbox"; diff --git a/middleware.js b/middleware.js index a2bad88..0a74270 100644 --- a/middleware.js +++ b/middleware.js @@ -1,7 +1,7 @@ export { default } from "next-auth/middleware"; export const config = { - matcher: ["/panel"], + matcher: ["/panel", "/panel/:path*"], pages: { signIn: "/", }, diff --git a/package.json b/package.json index 0d682ec..42bee4d 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@colors/colors": "^1.6.0", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/themes": "^2.0.3", + "@tanstack/react-query": "^5.24.2", "@tensorflow/tfjs-node": "^4.17.0", "dayjs": "^1.11.10", "lru-cache": "^10.2.0", @@ -28,7 +29,8 @@ "revolt.js": "^7.0.0-beta.11", "scikitjs": "^1.24.0", "string-comparison": "^1.3.0", - "ulid": "^2.3.0" + "ulid": "^2.3.0", + "winbox": "^0.2.82" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", @@ -36,6 +38,8 @@ "@types/node-cron": "^3.0.11", "@types/react": "^18", "@types/react-dom": "^18", + "@types/winbox": "^0.2.5", + "@typescript-eslint/parser": "^7.0.2", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.0.4",