mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
Some checks failed
CodeQL Scan / Analyze (javascript-typescript) (push) Failing after 42s
Build Docker Images / lint (push) Successful in 31s
Build Docker Images / check (push) Successful in 1m3s
Build Docker Images / tests (push) Failing after 6s
Build Docker Images / build (server, Dockerfile, ${{ github.repository_owner }}/server) (push) Has been skipped
Build Docker Images / build (worker, Worker.Dockerfile, ${{ github.repository_owner }}/worker) (push) Has been skipped
Deploy Docs to GitHub Pages / build (push) Failing after 13s
Mirror to Codeberg / Mirror (push) Failing after 0s
Deploy Docs to GitHub Pages / Deploy (push) Has been skipped
Nix Build / check (push) Failing after 33m18s
81 lines
2.9 KiB
TypeScript
81 lines
2.9 KiB
TypeScript
import { apiRoute, jsonOrForm } from "@/api";
|
|
import { randomString } from "@/math";
|
|
import { createRoute, z } from "@hono/zod-openapi";
|
|
import {
|
|
Application as ApplicationSchema,
|
|
CredentialApplication as CredentialApplicationSchema,
|
|
} from "@versia/client/schemas";
|
|
import { Application } from "@versia/kit/db";
|
|
import { ApiError } from "~/classes/errors/api-error";
|
|
import { rateLimit } from "~/middlewares/rate-limit";
|
|
|
|
const route = createRoute({
|
|
method: "post",
|
|
path: "/api/v1/apps",
|
|
summary: "Create an application",
|
|
description: "Create a new application to obtain OAuth2 credentials.",
|
|
externalDocs: {
|
|
url: "https://docs.joinmastodon.org/methods/apps/#create",
|
|
},
|
|
tags: ["Apps"],
|
|
middleware: [jsonOrForm(), rateLimit(4)],
|
|
request: {
|
|
body: {
|
|
content: {
|
|
"application/json": {
|
|
schema: z.object({
|
|
client_name: ApplicationSchema.shape.name,
|
|
redirect_uris: ApplicationSchema.shape.redirect_uris.or(
|
|
ApplicationSchema.shape.redirect_uri.transform(
|
|
(u) => u.split("\n"),
|
|
),
|
|
),
|
|
scopes: z
|
|
.string()
|
|
.default("read")
|
|
.transform((s) => s.split(" "))
|
|
.openapi({
|
|
description: "Space separated list of scopes.",
|
|
}),
|
|
// Allow empty websites because Traewelling decides to give an empty
|
|
// value instead of not providing anything at all
|
|
website: ApplicationSchema.shape.website
|
|
.optional()
|
|
.or(z.literal("").transform(() => undefined)),
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
200: {
|
|
description:
|
|
"Store the client_id and client_secret in your cache, as these will be used to obtain OAuth tokens.",
|
|
content: {
|
|
"application/json": {
|
|
schema: CredentialApplicationSchema,
|
|
},
|
|
},
|
|
},
|
|
422: ApiError.validationFailed().schema,
|
|
},
|
|
});
|
|
|
|
export default apiRoute((app) =>
|
|
app.openapi(route, async (context) => {
|
|
const { client_name, redirect_uris, scopes, website } =
|
|
context.req.valid("json");
|
|
|
|
const app = await Application.insert({
|
|
name: client_name,
|
|
redirectUri: redirect_uris.join("\n"),
|
|
scopes: scopes.join(" "),
|
|
website,
|
|
clientId: randomString(32, "base64url"),
|
|
secret: randomString(64, "base64url"),
|
|
});
|
|
|
|
return context.json(app.toApiCredential(), 200);
|
|
}),
|
|
);
|