First commit
This commit is contained in:
Executable
+18
@@ -0,0 +1,18 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import Setup from "./setup";
|
||||
import Primary from "./primary";
|
||||
import Me from "./me";
|
||||
|
||||
export default async function Routes(fastify: FastifyInstance) {
|
||||
await fastify.register(Setup, {
|
||||
prefix: "/setup",
|
||||
});
|
||||
|
||||
await fastify.register(Primary, {
|
||||
prefix: "/primary",
|
||||
});
|
||||
|
||||
await fastify.register(Me, {
|
||||
prefix: "/me",
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
|
||||
export default async function Me(fastify: FastifyInstance) {
|
||||
fastify.post("/", async (req, res) => {
|
||||
if ("error" in req.token)
|
||||
return res.code(400).send(req.token);
|
||||
|
||||
const { password, email, ...safeUser } = req.token.user;
|
||||
return res.send(safeUser);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import SignUp from "./signup";
|
||||
import SignIn from "./signin";
|
||||
|
||||
export default async function Primary(fastify: FastifyInstance) {
|
||||
await fastify.register(SignUp, {
|
||||
prefix: "/signup",
|
||||
});
|
||||
|
||||
await fastify.register(SignIn, {
|
||||
prefix: "/signin",
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { DatabaseError, ErrorBase, InputError } from "@/errors";
|
||||
import logger from "@/lib/logger";
|
||||
import { TokenEntity } from "@/modules/entities/Token";
|
||||
import { UserEntity } from "@/modules/entities/User";
|
||||
import { UserRepository } from "@/modules/repositories/User";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
|
||||
export default function SignIn(fastify: FastifyInstance) {
|
||||
fastify.post("/", async (req, res) => {
|
||||
res.header("Content-Type", "application/json");
|
||||
|
||||
const schema = UserRepository.schema.pick({
|
||||
userid: true,
|
||||
password: true,
|
||||
});
|
||||
|
||||
const result = schema.safeParse(req.body);
|
||||
|
||||
if (!result.success) {
|
||||
return res.code(400).send(InputError(result.error.issues));
|
||||
}
|
||||
|
||||
try {
|
||||
const user = await fastify.orm.em.getRepository(UserEntity).authUser(result.data);
|
||||
|
||||
if (typeof user === "string") {
|
||||
return res.code(400).send(ErrorBase({
|
||||
bad: "client",
|
||||
code: "auth_input_wrong",
|
||||
message: "ユーザー名かパスワードが違います。",
|
||||
}));
|
||||
}
|
||||
|
||||
const token = await fastify.orm.em.getRepository(TokenEntity).createToken(user, true);
|
||||
|
||||
return res.send({
|
||||
success: true,
|
||||
token: token,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("Database Error: User auth or token create failed.", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { UserEntity } from "@/modules/entities/User";
|
||||
import logger from "@/lib/logger";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { UserRepository } from "@/modules/repositories/User";
|
||||
import { DatabaseError, InputError } from "@/errors";
|
||||
|
||||
export default function SignUp(fastify: FastifyInstance) {
|
||||
fastify.post("/", async (req, res) => {
|
||||
res.header("Content-Type", "application/json");
|
||||
|
||||
const result = UserRepository.schema.safeParse(req.body);
|
||||
|
||||
if (!result.success) {
|
||||
return res.code(400).send(InputError(result.error.issues));
|
||||
}
|
||||
|
||||
try {
|
||||
await fastify.orm.em.getRepository(UserEntity).createUser(result.data);
|
||||
|
||||
return res.code(200).send({
|
||||
success: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("Database Error: User create failed.", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { ConfigEntity } from "@/modules/entities/Config";
|
||||
import { UserEntity } from "@/modules/entities/User";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
|
||||
export default async function ServerInfo(fastify: FastifyInstance) {
|
||||
fastify.post("/", async (req, res) => {
|
||||
const config = fastify.orm.em.getRepository(ConfigEntity);
|
||||
const user = fastify.orm.em.getRepository(UserEntity);
|
||||
const configCount = await config.count();
|
||||
const userCount = await user.count();
|
||||
|
||||
return res.send({
|
||||
isInitialized: configCount > 0,
|
||||
isFirstAdminExists: userCount > 0,
|
||||
userCount,
|
||||
});
|
||||
});
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import { UserEntity } from "@/modules/entities/User";
|
||||
import logger from "@/lib/logger";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import { UserRepository } from "@/modules/repositories/User";
|
||||
import { DatabaseError, ErrorBase, InputError } from "@/errors";
|
||||
import { ConfigEntity } from "@/modules/entities/Config";
|
||||
|
||||
export default function CreateAdmin(fastify: FastifyInstance) {
|
||||
fastify.post("/", async (req, res) => {
|
||||
res.header("Content-Type", "application/json");
|
||||
|
||||
const result = UserRepository.schema.omit({ isAdmin: true }).safeParse(req.body);
|
||||
|
||||
if (!result.success) {
|
||||
return res.code(400).send(InputError(result.error.issues));
|
||||
}
|
||||
|
||||
try {
|
||||
const configCount = await fastify.orm.em.count(ConfigEntity);
|
||||
|
||||
if (configCount === 0) {
|
||||
return res.code(409).send(ErrorBase({
|
||||
bad: "client",
|
||||
code: "yet_initialization",
|
||||
message: "初期設定が行われていません。",
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("Database Error: Could not check if already initialization:", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
|
||||
try {
|
||||
const userCount = await fastify.orm.em.getRepository(UserEntity).count();
|
||||
|
||||
if (userCount > 0) {
|
||||
return res.code(409).send(ErrorBase({
|
||||
bad: "client",
|
||||
code: "first_admin_already_exists",
|
||||
message: "最初の管理者ユーザーは既に存在します。",
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("Database Error: Could not check if administrator exists:", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
|
||||
try {
|
||||
await fastify.orm.em.getRepository(UserEntity).createUser({
|
||||
...result.data,
|
||||
isAdmin: true,
|
||||
});
|
||||
|
||||
logger.warn("First administrator account has been created.")
|
||||
|
||||
return res.code(200).send({
|
||||
success: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("Database Error: Admin user create failed.", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
});
|
||||
}
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import CreateAdmin from "./create-admin";
|
||||
import Initialization from "./initialization";
|
||||
|
||||
export default async function Setup(fastify: FastifyInstance) {
|
||||
await fastify.register(Initialization, {
|
||||
prefix: "/initialization",
|
||||
});
|
||||
|
||||
await fastify.register(CreateAdmin, {
|
||||
prefix: "/create-admin",
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { DatabaseError, ErrorBase, InputError } from "@/errors";
|
||||
import logger from "@/lib/logger";
|
||||
import { ConfigEntity } from "@/modules/entities/Config";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import z from "zod/v3";
|
||||
|
||||
export default function Initialization(fastify: FastifyInstance) {
|
||||
fastify.post("/", async (req, res) => {
|
||||
res.header("Content-Type", "application/json");
|
||||
|
||||
const bodySchema = z.object({
|
||||
name: z.string().trim().min(1).max(20),
|
||||
description: z.string().trim().min(1),
|
||||
requiredInvitationCode: z.boolean(),
|
||||
force: z.literal("use_force_initialization").refine(() => process.env.NODE_ENV !== "production").optional(),
|
||||
});
|
||||
|
||||
const result = bodySchema.safeParse(req.body);
|
||||
|
||||
if (!result.success) {
|
||||
return res.code(400).send(InputError(result.error.issues));
|
||||
}
|
||||
|
||||
try {
|
||||
if (result.data.force) {
|
||||
await fastify.orm.em.nativeDelete(ConfigEntity, {});
|
||||
fastify.orm.em.clear();
|
||||
}
|
||||
|
||||
const configCount = await fastify.orm.em.count(ConfigEntity);
|
||||
|
||||
if (configCount > 0) {
|
||||
return res.code(409).send(ErrorBase({
|
||||
bad: "client",
|
||||
code: "already_initialization",
|
||||
message: "既に初期設定が行われています。",
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("Database Error: Could not check if yet initialization:", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
|
||||
try {
|
||||
const entries = Object.entries(result.data).filter(([key]) => key !== "force");
|
||||
|
||||
for (const [key, value] of entries) {
|
||||
const entity = fastify.orm.em.create(ConfigEntity, {
|
||||
name: key,
|
||||
value: typeof value === "string"
|
||||
? value
|
||||
: String(value),
|
||||
});
|
||||
|
||||
fastify.orm.em.persist(entity);
|
||||
}
|
||||
|
||||
await fastify.orm.em.flush();
|
||||
|
||||
return res.code(200).send({
|
||||
success: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("Database Error: Server initialization failed:", err);
|
||||
|
||||
return res.code(500).send(DatabaseError());
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user