mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
Add interface to view post and user JSON data
This commit is contained in:
parent
342a8011f1
commit
db37510370
|
|
@ -260,7 +260,7 @@ export const createNewStatus = async (data: {
|
|||
.join("\n");
|
||||
}
|
||||
|
||||
let status = await client.status.create({
|
||||
const status = await client.status.create({
|
||||
data: {
|
||||
authorId: data.account.id,
|
||||
applicationId: data.application?.id,
|
||||
|
|
@ -290,12 +290,7 @@ export const createNewStatus = async (data: {
|
|||
quotingPostId: data.quote?.id,
|
||||
instanceId: data.account.instanceId || undefined,
|
||||
isReblog: false,
|
||||
uri:
|
||||
data.uri ||
|
||||
new URL(
|
||||
`/statuses/FAKE-${crypto.randomUUID()}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
uri: data.uri || null,
|
||||
mentions: {
|
||||
connect: mentions.map((mention) => {
|
||||
return {
|
||||
|
|
@ -307,22 +302,6 @@ export const createNewStatus = async (data: {
|
|||
include: statusAndUserRelations,
|
||||
});
|
||||
|
||||
// Update URI
|
||||
status = await client.status.update({
|
||||
where: {
|
||||
id: status.id,
|
||||
},
|
||||
data: {
|
||||
uri:
|
||||
data.uri ||
|
||||
new URL(
|
||||
`/statuses/${status.id}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
},
|
||||
include: statusAndUserRelations,
|
||||
});
|
||||
|
||||
// Create notification
|
||||
if (status.inReplyToPost) {
|
||||
await client.notification.create({
|
||||
|
|
@ -503,9 +482,19 @@ export const statusToAPI = async (
|
|||
sensitive: status.sensitive,
|
||||
spoiler_text: status.spoilerText,
|
||||
tags: [],
|
||||
uri: new URL(`/statuses/${status.id}`, config.http.base_url).toString(),
|
||||
uri:
|
||||
status.uri ||
|
||||
new URL(
|
||||
`/@${status.author.username}/${status.id}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
visibility: "public",
|
||||
url: new URL(`/statuses/${status.id}`, config.http.base_url).toString(),
|
||||
url:
|
||||
status.uri ||
|
||||
new URL(
|
||||
`/@${status.author.username}/${status.id}`,
|
||||
config.http.base_url,
|
||||
).toString(),
|
||||
bookmarked: false,
|
||||
quote: status.quotingPost
|
||||
? await statusToAPI(
|
||||
|
|
@ -584,8 +573,8 @@ export const statusToLysand = (status: StatusWithRelations): Note => {
|
|||
// TODO: Add attachments
|
||||
attachments: [],
|
||||
is_sensitive: status.sensitive,
|
||||
mentions: status.mentions.map((mention) => mention.uri),
|
||||
quotes: status.quotingPost ? [status.quotingPost.uri] : [],
|
||||
mentions: status.mentions.map((mention) => mention.uri || ""),
|
||||
quotes: status.quotingPost ? [status.quotingPost.uri || ""] : [],
|
||||
replies_to: status.inReplyToPostId ? [status.inReplyToPostId] : [],
|
||||
subject: status.spoilerText,
|
||||
extensions: {
|
||||
|
|
|
|||
|
|
@ -262,7 +262,6 @@ export const createNewLocalUser = async (data: {
|
|||
avatar: data.avatar ?? config.defaults.avatar,
|
||||
header: data.header ?? config.defaults.avatar,
|
||||
isAdmin: data.admin ?? false,
|
||||
uri: "",
|
||||
publicKey: keys.public_key,
|
||||
privateKey: keys.private_key,
|
||||
source: {
|
||||
|
|
@ -273,20 +272,13 @@ export const createNewLocalUser = async (data: {
|
|||
fields: [],
|
||||
},
|
||||
},
|
||||
include: userRelations,
|
||||
});
|
||||
|
||||
// Add to Meilisearch
|
||||
await addUserToMeilisearch(user);
|
||||
|
||||
return await client.user.update({
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
data: {
|
||||
uri: new URL(`/users/${user.id}`, config.http.base_url).toString(),
|
||||
},
|
||||
include: userRelations,
|
||||
});
|
||||
return user;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -408,7 +400,9 @@ export const userToAPI = (
|
|||
username: user.username,
|
||||
display_name: user.displayName,
|
||||
note: user.note,
|
||||
url: user.uri,
|
||||
url:
|
||||
user.uri ||
|
||||
new URL(`/@${user.username}`, config.http.base_url).toString(),
|
||||
avatar: getAvatarUrl(user, config),
|
||||
header: getHeaderUrl(user, config),
|
||||
locked: user.isLocked,
|
||||
|
|
@ -458,7 +452,7 @@ export const userToLysand = (user: UserWithRelations): LysandUser => {
|
|||
return {
|
||||
id: user.id,
|
||||
type: "User",
|
||||
uri: user.uri,
|
||||
uri: user.uri || "",
|
||||
bio: [
|
||||
{
|
||||
content: user.note,
|
||||
|
|
|
|||
|
|
@ -61,10 +61,12 @@
|
|||
"@types/jsonld": "^1.5.13",
|
||||
"@typescript-eslint/eslint-plugin": "latest",
|
||||
"@unocss/cli": "latest",
|
||||
"@unocss/transformer-directives": "^0.59.0",
|
||||
"@vitejs/plugin-vue": "latest",
|
||||
"@vueuse/head": "^2.0.0",
|
||||
"activitypub-types": "^1.0.3",
|
||||
"bun-types": "latest",
|
||||
"shiki": "^1.2.4",
|
||||
"typescript": "latest",
|
||||
"unocss": "latest",
|
||||
"untyped": "^1.4.2",
|
||||
|
|
|
|||
65
pages/pages/[username]/[uuid].vue
Normal file
65
pages/pages/[username]/[uuid].vue
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<div class="flex min-h-screen flex-col justify-center px-6 py-12 lg:px-8 relative">
|
||||
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true">
|
||||
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)" />
|
||||
</div>
|
||||
<div class="code" v-html="code">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from "vue-router";
|
||||
import { getHighlighterCore } from "shiki/core";
|
||||
import getWasm from "shiki/wasm";
|
||||
|
||||
const location = window.location;
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const data = await fetch(
|
||||
new URL(`/api/v1/statuses/${route.params.uuid}`, location.origin),
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
},
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.catch(() => ({
|
||||
error: "Failed to fetch status (it probably doesn't exist)",
|
||||
}));
|
||||
|
||||
const highlighter = await getHighlighterCore({
|
||||
themes: [import("shiki/themes/rose-pine.mjs")],
|
||||
langs: [import("shiki/langs/json.mjs")],
|
||||
loadWasm: getWasm,
|
||||
});
|
||||
|
||||
const code = highlighter.codeToHtml(JSON.stringify(data, null, 4), {
|
||||
lang: "json",
|
||||
theme: "rose-pine",
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.code pre:has(code) {
|
||||
word-wrap: normal;
|
||||
background: transparent;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
white-space: pre;
|
||||
word-break: normal;
|
||||
word-spacing: normal;
|
||||
overflow-x: auto;
|
||||
--at-apply: "ring-1 ring-white/10 mt-4 bg-white/5 px-4 py-3 rounded";
|
||||
}
|
||||
|
||||
.code pre code {
|
||||
--at-apply: "block p-0";
|
||||
}
|
||||
</style>
|
||||
82
pages/pages/[username]/index.vue
Normal file
82
pages/pages/[username]/index.vue
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<div class="flex min-h-screen flex-col justify-center px-6 py-12 lg:px-8 relative">
|
||||
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80" aria-hidden="true">
|
||||
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)" />
|
||||
</div>
|
||||
<div class="code" v-html="code">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from "vue-router";
|
||||
import { getHighlighterCore } from "shiki/core";
|
||||
import getWasm from "shiki/wasm";
|
||||
|
||||
const location = window.location;
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const username = (route.params.username as string).replace("@", "");
|
||||
|
||||
const id = await fetch(
|
||||
new URL(`/api/v1/accounts/search?q=${username}`, location.origin),
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
},
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.catch(() => null);
|
||||
|
||||
let data = null;
|
||||
|
||||
if (id && id.length > 0) {
|
||||
data = await fetch(
|
||||
new URL(`/api/v1/accounts/${id[0].id}`, location.origin),
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
},
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.catch(() => ({
|
||||
error: "Failed to fetch user (it probably doesn't exist)",
|
||||
}));
|
||||
}
|
||||
|
||||
const highlighter = await getHighlighterCore({
|
||||
themes: [import("shiki/themes/rose-pine.mjs")],
|
||||
langs: [import("shiki/langs/json.mjs")],
|
||||
loadWasm: getWasm,
|
||||
});
|
||||
|
||||
const code = highlighter.codeToHtml(JSON.stringify(data, null, 4), {
|
||||
lang: "json",
|
||||
theme: "rose-pine",
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.code pre:has(code) {
|
||||
word-wrap: normal;
|
||||
background: transparent;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
white-space: pre;
|
||||
word-break: normal;
|
||||
word-spacing: normal;
|
||||
overflow-x: auto;
|
||||
--at-apply: "ring-1 ring-white/10 mt-4 bg-white/5 px-4 py-3 rounded";
|
||||
}
|
||||
|
||||
.code pre code {
|
||||
--at-apply: "block p-0";
|
||||
}
|
||||
</style>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form class="space-y-6" method="POST"
|
||||
:action="`/auth/login?redirect_uri=${redirect_uri}&response_type=${response_type}&client_id=${client_id}&scope=${scope}`">
|
||||
:action="`/api/auth/login?redirect_uri=${redirect_uri}&response_type=${response_type}&client_id=${client_id}&scope=${scope}`">
|
||||
<div>
|
||||
<h1 class="font-bold text-2xl text-center tracking-tight">Login to your account</h1>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form class="space-y-6" method="POST"
|
||||
:action="`/auth/redirect?redirect_uri=${encodeURIComponent(redirect_uri)}&client_id=${client_id}&code=${code}`">
|
||||
:action="`/api/auth/redirect?redirect_uri=${encodeURIComponent(redirect_uri)}&client_id=${client_id}&code=${code}`">
|
||||
<div class="flex flex-col items-center gap-y-5">
|
||||
<h1 class="font-bold text-2xl text-center tracking-tight">Allow this application to access your
|
||||
account?</h1>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import authorizeVue from "./pages/oauth/authorize.vue";
|
|||
import redirectVue from "./pages/oauth/redirect.vue";
|
||||
import registerIndexVue from "./pages/register/index.vue";
|
||||
import successVue from "./pages/register/success.vue";
|
||||
import statusVue from "./pages/[username]/[uuid].vue";
|
||||
import userVue from "./pages/[username]/index.vue";
|
||||
|
||||
export default [
|
||||
{ path: "/", component: indexVue },
|
||||
|
|
@ -11,4 +13,6 @@ export default [
|
|||
{ path: "/oauth/redirect", component: redirectVue },
|
||||
{ path: "/register", component: registerIndexVue },
|
||||
{ path: "/register/success", component: successVue },
|
||||
{ path: "/:username/:uuid", component: statusVue },
|
||||
{ path: "/:username", component: userVue },
|
||||
] as RouteRecordRaw[];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Status" ALTER COLUMN "uri" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ALTER COLUMN "uri" DROP NOT NULL;
|
||||
|
|
@ -104,7 +104,7 @@ model Relationship {
|
|||
|
||||
model Status {
|
||||
id String @id @default(dbgenerated("uuid_generate_v7()")) @db.Uuid
|
||||
uri String @unique
|
||||
uri String? @unique
|
||||
author User @relation("UserStatuses", fields: [authorId], references: [id], onDelete: Cascade)
|
||||
authorId String @db.Uuid
|
||||
createdAt DateTime @default(now())
|
||||
|
|
@ -228,7 +228,7 @@ model Notification {
|
|||
|
||||
model User {
|
||||
id String @id @default(dbgenerated("uuid_generate_v7()")) @db.Uuid
|
||||
uri String @unique
|
||||
uri String? @unique
|
||||
username String @unique
|
||||
displayName String
|
||||
password String? // Nullable
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ export const rawRoutes = {
|
|||
"/api/v1/timelines/public": "./server/api/api/v1/timelines/public",
|
||||
"/api/v2/media": "./server/api/api/v2/media/index",
|
||||
"/api/v2/search": "./server/api/api/v2/search/index",
|
||||
"/auth/login": "./server/api/auth/login/index",
|
||||
"/auth/redirect": "./server/api/auth/redirect/index",
|
||||
"/api/auth/login": "./server/api/api/auth/login/index",
|
||||
"/api/auth/redirect": "./server/api/api/auth/redirect/index",
|
||||
"/nodeinfo/2.0": "./server/api/nodeinfo/2.0/index",
|
||||
"/oauth/authorize-external": "./server/api/oauth/authorize-external/index",
|
||||
"/oauth/providers": "./server/api/oauth/providers/index",
|
||||
|
|
|
|||
109
server.ts
109
server.ts
|
|
@ -124,7 +124,7 @@ export const createServer = (
|
|||
|
||||
// Check for allowed requests
|
||||
// @ts-expect-error Stupid error
|
||||
if (!meta.allowedMethods.includes(req.method as string)) {
|
||||
if (!meta.allowedMethods.includes(req.method)) {
|
||||
return errorResponse(
|
||||
`Method not allowed: allowed methods are: ${meta.allowedMethods.join(
|
||||
", ",
|
||||
|
|
@ -137,17 +137,15 @@ export const createServer = (
|
|||
const auth = await getFromRequest(req);
|
||||
|
||||
// Check for authentication if required
|
||||
if (meta.auth.required) {
|
||||
if (!auth.user) {
|
||||
return errorResponse("Unauthorized", 401);
|
||||
}
|
||||
} else if (
|
||||
// @ts-expect-error Stupid error
|
||||
(meta.auth.requiredOnMethods ?? []).includes(req.method)
|
||||
if (
|
||||
(meta.auth.required ||
|
||||
(meta.auth.requiredOnMethods ?? []).includes(
|
||||
// @ts-expect-error Stupid error
|
||||
req.method,
|
||||
)) &&
|
||||
!auth.user
|
||||
) {
|
||||
if (!auth.user) {
|
||||
return errorResponse("Unauthorized", 401);
|
||||
}
|
||||
return errorResponse("Unauthorized", 401);
|
||||
}
|
||||
|
||||
let parsedRequest = {};
|
||||
|
|
@ -172,68 +170,53 @@ export const createServer = (
|
|||
},
|
||||
});
|
||||
}
|
||||
if (matchedRoute?.name === "/[...404]" || !matchedRoute) {
|
||||
if (new URL(req.url).pathname.startsWith("/api")) {
|
||||
return errorResponse("Route not found", 404);
|
||||
|
||||
if (new URL(req.url).pathname.startsWith("/api")) {
|
||||
return errorResponse("Route not found", 404);
|
||||
}
|
||||
|
||||
// Proxy response from Vite at localhost:5173 if in development mode
|
||||
if (isProd) {
|
||||
let file = Bun.file("./pages/dist/index.html");
|
||||
if (new URL(req.url).pathname.startsWith("/assets")) {
|
||||
file = Bun.file(`./pages/dist${new URL(req.url).pathname}`);
|
||||
}
|
||||
|
||||
// Proxy response from Vite at localhost:5173 if in development mode
|
||||
if (isProd) {
|
||||
if (new URL(req.url).pathname.startsWith("/assets")) {
|
||||
const file = Bun.file(
|
||||
`./pages/dist${new URL(req.url).pathname}`,
|
||||
);
|
||||
|
||||
// Serve from pages/dist/assets
|
||||
if (await file.exists()) {
|
||||
return clientResponse(file, 200, {
|
||||
"Content-Type": file.type,
|
||||
});
|
||||
}
|
||||
return errorResponse("Asset not found", 404);
|
||||
}
|
||||
if (new URL(req.url).pathname.startsWith("/api")) {
|
||||
return errorResponse("Route not found", 404);
|
||||
}
|
||||
|
||||
const file = Bun.file("./pages/dist/index.html");
|
||||
|
||||
// Serve from pages/dist
|
||||
// Serve from pages/dist/assets
|
||||
if (await file.exists()) {
|
||||
return clientResponse(file, 200, {
|
||||
"Content-Type": file.type,
|
||||
});
|
||||
}
|
||||
const proxy = await fetch(
|
||||
req.url.replace(
|
||||
return errorResponse("Asset not found", 404);
|
||||
}
|
||||
|
||||
const proxy = await fetch(
|
||||
req.url.replace(config.http.base_url, "http://localhost:5173"),
|
||||
).catch(async (e) => {
|
||||
await logger.logError(
|
||||
LogLevel.ERROR,
|
||||
"Server.Proxy",
|
||||
e as Error,
|
||||
);
|
||||
await logger.log(
|
||||
LogLevel.ERROR,
|
||||
"Server.Proxy",
|
||||
`The development Vite server is not running or the route is not found: ${req.url.replace(
|
||||
config.http.base_url,
|
||||
"http://localhost:5173",
|
||||
),
|
||||
).catch(async (e) => {
|
||||
await logger.logError(
|
||||
LogLevel.ERROR,
|
||||
"Server.Proxy",
|
||||
e as Error,
|
||||
);
|
||||
await logger.log(
|
||||
LogLevel.ERROR,
|
||||
"Server.Proxy",
|
||||
`The development Vite server is not running or the route is not found: ${req.url.replace(
|
||||
config.http.base_url,
|
||||
"http://localhost:5173",
|
||||
)}`,
|
||||
);
|
||||
return errorResponse("Route not found", 404);
|
||||
});
|
||||
|
||||
if (
|
||||
proxy.status !== 404 &&
|
||||
!(await proxy.clone().text()).includes("404 Not Found")
|
||||
) {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
)}`,
|
||||
);
|
||||
return errorResponse("Route not found", 404);
|
||||
});
|
||||
|
||||
if (
|
||||
proxy.status !== 404 &&
|
||||
!(await proxy.clone().text()).includes("404 Not Found")
|
||||
) {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return errorResponse("Route not found", 404);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ export const meta = applyConfig({
|
|||
* Default catch-all route, returns a 404 error.
|
||||
*/
|
||||
export default apiRoute(() => {
|
||||
return errorResponse("This API route does not exist", 404);
|
||||
return errorResponse("Route not found", 404);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const meta = applyConfig({
|
|||
max: 4,
|
||||
duration: 60,
|
||||
},
|
||||
route: "/auth/login",
|
||||
route: "/api/auth/login",
|
||||
auth: {
|
||||
required: false,
|
||||
},
|
||||
|
|
@ -8,7 +8,7 @@ export const meta = applyConfig({
|
|||
max: 4,
|
||||
duration: 60,
|
||||
},
|
||||
route: "/auth/redirect",
|
||||
route: "/api/auth/redirect",
|
||||
auth: {
|
||||
required: false,
|
||||
},
|
||||
|
|
@ -13,7 +13,7 @@ export const meta = applyConfig({
|
|||
},
|
||||
route: "/api/v1/accounts/:id",
|
||||
auth: {
|
||||
required: true,
|
||||
required: false,
|
||||
oauthPermissions: [],
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const meta = applyConfig({
|
|||
duration: 60,
|
||||
},
|
||||
auth: {
|
||||
required: true,
|
||||
required: false,
|
||||
oauthPermissions: ["read:accounts"],
|
||||
},
|
||||
});
|
||||
|
|
@ -25,11 +25,6 @@ export default apiRoute<{
|
|||
following?: boolean;
|
||||
}>(async (req, matchedRoute, extraData) => {
|
||||
// TODO: Add checks for disabled or not email verified accounts
|
||||
|
||||
const { user } = extraData.auth;
|
||||
|
||||
if (!user) return errorResponse("Unauthorized", 401);
|
||||
|
||||
const {
|
||||
following = false,
|
||||
limit = 40,
|
||||
|
|
@ -37,6 +32,10 @@ export default apiRoute<{
|
|||
q,
|
||||
} = extraData.parsedRequest;
|
||||
|
||||
const { user } = extraData.auth;
|
||||
|
||||
if (!user && following) return errorResponse("Unauthorized", 401);
|
||||
|
||||
if (limit < 1 || limit > 80) {
|
||||
return errorResponse("Limit must be between 1 and 80", 400);
|
||||
}
|
||||
|
|
@ -60,7 +59,7 @@ export default apiRoute<{
|
|||
relationshipSubjects: following
|
||||
? {
|
||||
some: {
|
||||
ownerId: user.id,
|
||||
ownerId: user?.id,
|
||||
following,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ describe("API Tests", () => {
|
|||
expect(account.statuses_count).toBe(0);
|
||||
expect(account.note).toBe("");
|
||||
expect(account.url).toBe(
|
||||
new URL(`/users/${user.id}`, config.http.base_url).toString(),
|
||||
new URL(`/@${user.username}`, config.http.base_url).toString(),
|
||||
);
|
||||
expect(account.avatar).toBeDefined();
|
||||
expect(account.avatar_static).toBeDefined();
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ describe("POST /api/v1/apps/", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("POST /auth/login/", () => {
|
||||
describe("POST /api/auth/login/", () => {
|
||||
test("should get a code", async () => {
|
||||
const formData = new FormData();
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ describe("POST /auth/login/", () => {
|
|||
const response = await sendTestRequest(
|
||||
new Request(
|
||||
wrapRelativeUrl(
|
||||
`/auth/login/?client_id=${client_id}&redirect_uri=https://example.com&response_type=code&scope=read+write`,
|
||||
`/api/auth/login/?client_id=${client_id}&redirect_uri=https://example.com&response_type=code&scope=read+write`,
|
||||
base_url,
|
||||
),
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { presetForms } from "@julr/unocss-preset-forms";
|
||||
import transformerDirectives from "@unocss/transformer-directives";
|
||||
|
||||
import {
|
||||
defineConfig,
|
||||
presetTypography,
|
||||
|
|
@ -19,4 +21,5 @@ export default defineConfig({
|
|||
presetWebFonts(),
|
||||
presetForms(),
|
||||
],
|
||||
transformers: [transformerDirectives()],
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue