diff --git a/packages/backend/src/modules/repositories/User.ts b/packages/backend/src/modules/repositories/User.ts index 6ec8812..6496ee8 100644 --- a/packages/backend/src/modules/repositories/User.ts +++ b/packages/backend/src/modules/repositories/User.ts @@ -1,8 +1,10 @@ import { EntityRepository } from "@mikro-orm/postgresql"; import { UserEntity } from "@/modules/entities/User"; +import { ConfigEntity } from "@/modules/entities/Config"; import { hash, argon2id, verify as argon2Verify } from "argon2"; import z from "zod/v3"; import EmailRegex from "@/regexs/email"; +import { ErrorBase } from "@/errors"; export class UserRepository extends EntityRepository { public static schema = z.object({ @@ -15,7 +17,18 @@ export class UserRepository extends EntityRepository { isAdmin: z.boolean(), }); - async createUser(data: Pick, "userid" | "email" | "password" | "isAdmin">) { + async createUser(data: Pick, "userid" | "email" | "password" | "isAdmin"> & { + invitationCode?: string; + }) { + const requiredInvitationCode = await this.em.getRepository(ConfigEntity).get("requiredInvitationCode", "true") as string; + if (requiredInvitationCode && !data.invitationCode) { + return ErrorBase({ + bad: "client", + code: "invitation_code_invalid", + message: "招待コードが無効です。", + }); + } + const hashed = await hash(data.password, { type: argon2id, memoryCost: 2 ** 16, diff --git a/packages/backend/src/routes/primary/signup.ts b/packages/backend/src/routes/primary/signup.ts index e0616b7..3f0fac4 100644 --- a/packages/backend/src/routes/primary/signup.ts +++ b/packages/backend/src/routes/primary/signup.ts @@ -3,6 +3,8 @@ import Logger from "@/lib/logger"; import type { FastifyInstance } from "fastify"; import { UserRepository } from "@/modules/repositories/User"; import { DatabaseError, InputError } from "@/errors"; +import { ConfigEntity } from "@/modules/entities/Config"; +import z, { ZodObject } from "zod/v3"; export default function PrimarySignUp(fastify: FastifyInstance) { const logger = new Logger("Endpoint | primary/signup"); @@ -10,23 +12,38 @@ export default function PrimarySignUp(fastify: FastifyInstance) { fastify.post("/", async (req, res) => { res.header("Content-Type", "application/json"); - const result = UserRepository.schema.pick({ - userid: true, - email: true, - password: true, - }).safeParse(req.body); - - if (!result.success) { - console.log(result.error.issues) - return res.code(400).send(InputError(result.error.issues)); - } - try { - await fastify.orm.em.getRepository(UserEntity).createUser({ - ...result.data, + const requiredInvitationCode = await fastify.orm.em.getRepository(ConfigEntity).get("requiredInvitationCode", "true") as string; + + let reqInvCodeSchema: ZodObject; + if (requiredInvitationCode !== "true") { + reqInvCodeSchema = z.object({}); + } else { + reqInvCodeSchema = z.object({ + invitationCode: z.string().trim().min(1), + }); + } + + const result = UserRepository.schema.pick({ + userid: true, + email: true, + password: true, + }).merge(reqInvCodeSchema).safeParse(req.body); + + if (!result.success) { + console.log(result.error.issues) + return res.code(400).send(InputError(result.error.issues)); + } + + const error = await fastify.orm.em.getRepository(UserEntity).createUser({ + ...(result.data as any), isAdmin: false, }); + if (error) { + return res.code(400).send(error); + } + return res.code(200).send({ success: true, }); diff --git a/packages/backend/src/routes/server-info.ts b/packages/backend/src/routes/server-info.ts index fec5524..e5866a0 100644 --- a/packages/backend/src/routes/server-info.ts +++ b/packages/backend/src/routes/server-info.ts @@ -15,15 +15,15 @@ export default async function ServerInfo(fastify: FastifyInstance) { const configCount = await configRepo.count(); const userCount = await userRepo.count(); - const serverName = await configRepo.findOne({ name: "name" }); - const serverDescription = await configRepo.findOne({ name: "description" }); - const serverIcon = await configRepo.findOne({ name: "icon" }); + const serverName = await configRepo.get("name"); + const serverDescription = await configRepo.get("description"); + const serverIcon = await configRepo.get("icon"); return res.send({ success: true, - name: serverName?.value ?? null, - description: serverDescription?.value ?? null, - icon: serverIcon?.value ?? null, + name: serverName ?? null, + description: serverDescription ?? null, + icon: serverIcon ?? null, isInitialized: configCount > 0, isFirstAdminExists: userCount > 0, userCount, diff --git a/packages/frontend/src/Layout.vue b/packages/frontend/src/Layout.vue index 3dc3116..b577ced 100755 --- a/packages/frontend/src/Layout.vue +++ b/packages/frontend/src/Layout.vue @@ -43,6 +43,7 @@
@@ -245,7 +246,7 @@ import { RouterView, RouterLink, useRouter, useRoute } from "vue-router"; import routerStatus, { title } from "@/lib/router"; import { Icon } from "@iconify/vue"; import Progress from "@/components/Progress.vue"; -import { communitys, serverInfo } from "@/lib/account"; +import { account, communitys, serverInfo } from "@/lib/account"; import { computed, onBeforeUnmount, onMounted, watch } from "vue"; import { createModal } from "@/lib/modal"; import ErrorModal from "@/components/Modal/Error.vue"; diff --git a/packages/frontend/src/main.ts b/packages/frontend/src/main.ts index 3dc9aa9..0703d2d 100755 --- a/packages/frontend/src/main.ts +++ b/packages/frontend/src/main.ts @@ -46,6 +46,13 @@ const router = createRouter({ }, component: () => import("@/routes/signin.vue"), }, + { + path: "/signup", + meta: { + title: "サインアップ", + }, + component: () => import("@/routes/signup.vue"), + }, { path: "/community/:communityId", meta: { diff --git a/packages/frontend/src/routes/signin.vue b/packages/frontend/src/routes/signin.vue index ea79059..207506d 100644 --- a/packages/frontend/src/routes/signin.vue +++ b/packages/frontend/src/routes/signin.vue @@ -33,6 +33,8 @@ color="accent" :disabled="!result.success || isProcessing" /> + + アカウントをお持ちでないですか? diff --git a/packages/frontend/src/routes/signup.vue b/packages/frontend/src/routes/signup.vue new file mode 100644 index 0000000..14e5d5a --- /dev/null +++ b/packages/frontend/src/routes/signup.vue @@ -0,0 +1,227 @@ + + + + + \ No newline at end of file