forked from peas-dev/peas
1
0
Fork 0

Compare commits

..

7 Commits

26 changed files with 1005 additions and 767 deletions

View File

@ -0,0 +1,53 @@
---
name: Bug Report
about: Bug report.
title: "[Bug]: "
ref: develop
labels:
- bug?
- bug
---
# Summary
Please provide a brief summary of the bug.
# Confirmed
## Versions
Please list the versions in which you have seen this bug.
example
```md
- v1.0.0
```
# Client Environment
Please describe your client environment.
User Agent, OS, and model are preferred.
for example
```md
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0
Model and OS of the device(s): Windows 11 23H2
Browser: Zen Browser (1.16.2b 64bit)
Server: http://localhost:3000
Peas: v1.0.0
```
# Server Environment(for server admin)
Please describe your server environment.
for example
```md
Peas: v1.0.0
Node.js: v22.16.0
Node.js Server OS and Arch: Windows 11 23H2, x86
MariaDB: 10.11.11-MariaDB-0+deb12u1
MariaDB Server OS and Arch: Raspbian Lite 64bit, ARM
```
# Expected Behavior
Please be specific about the expected behavior.
# Actual Behavior
Please be specific about the actual behavior.
# Steps to Reproduce
Please clearly describe how to reproduce it.

View File

@ -0,0 +1,20 @@
---
name: Feature Request
about: Suggest a new feature.
title: "[Feature]: "
ref: develop
labels:
- feature
---
# Summary
Please provide a brief summary of the feature.
# Purpose
Please state your purpose.
# Development
Please choose one of the following:
- Community
- Development Owner(Last2014)
- You

View File

@ -0,0 +1,18 @@
---
name: Adding i18n language
about: Adding i18n supported languages.
title: "[i18n Add Lang]: "
ref: develop
labels:
- i18n
- add
---
# Target Language
Please enter the target language.
for example: Japanese
# Translation assistance
Please choose one of the following:
- part
- all

View File

@ -0,0 +1,26 @@
---
name: i18n Fixes
about: Modifying i18n information.
title: "[i18n Fix]: "
ref: develop
labels:
- i18n
- update
- fix
---
# Information to be corrected
## Language
English
## Key
`information`
## Before
infomation
## After
information
## Reason
typos

View File

@ -0,0 +1,16 @@
---
name: Bug Fixes
about: Bug fixes.
title: "[Bug Fix]: "
ref: develop
labels:
- bug?
- bug
---
# About that bug
Please describe the bug.
Please link to any related issues.
# Changes
Please list the changes in bullet points.

View File

@ -0,0 +1,11 @@
---
name: Other
about: Other Pull Request.
ref: develop
---
# Summary
Please provide a brief summary of the changes
# Related Issues
If you have any related issues, please enter them here.

View File

@ -84,3 +84,5 @@ ERR_code_invalid: Incorrect code
ERR_code_not_found: Code not found
ERR_user_not_found: User not found
ERR_password_invalid: Incorrect password
ERR_not_mailverify: Email not verified
ERR_auth_failed: Auth failed

View File

@ -84,3 +84,5 @@ ERR_code_invalid: コードが正しくありません
ERR_code_not_found: コードが見つかりません
ERR_user_not_found: ユーザーが見つかりません
ERR_password_invalid: パスワードが異なります
ERR_not_mailverify: メール認証されていません
ERR_auth_failed: 認証に失敗しました

View File

@ -3,9 +3,6 @@
"version": "1.0.0",
"private": true,
"description": "Peas is a SNS designed for sharing profiles.",
"scripts": {
"build:locale": "tsc"
},
"keywords": [
"sns",
"profile"

View File

@ -17,6 +17,7 @@
"@types/bcrypt": "^6.0.0",
"@types/nodemailer": "^7.0.2",
"bcrypt": "^6.0.0",
"child_process": "^1.0.2",
"daisyui": "^5.1.25",
"fs": "0.0.1-security",
"globals": "^16.4.0",
@ -26,7 +27,6 @@
"nodemailer": "^7.0.6",
"path": "^0.12.7",
"tailwindcss": "^4.1.13",
"ua-parser-js": "^2.0.5",
"url": "^0.11.4",
"uuid": "^13.0.0"
},

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,40 @@ export async function getScopeAPIToken(token: string) {
[token]
);
if (tokenData === undefined) {
return false;
}
const scope: scope[] = tokenData[0].scope.split(",");
return scope;
}
export async function Auth(token: string, scopes: scope[]) {
const scope = await getScopeAPIToken(token);
if (scope === false)
return false;
if (scope.indexOf("admin:client") !== -1)
return true;
if (
scope.indexOf("user:client") !== -1 &&
!scopes.some(s => s.includes("admin"))
)
return true;
if (scopes.sort().toString() === scope.sort().toString())
return true;
return false;
}
export async function isSignin(token: string) {
return await getScopeAPIToken(token) !== false;
}
export function getHeaderToken(header: string) {
const match = header.match(/^Bearer\s(.+)$/);
if (match && match.length > 1) {
return match[1];
}
return "";
}

View File

@ -14,6 +14,9 @@ API.route("/signin", SignInAPI);
import mailverifyAPI from "./mailverify.js";
API.route("/mailverify", mailverifyAPI);
import TimeLine from "./timeline/main.js";
API.route("/timelime", TimeLine);
import NotFound from "./notfound.js";
API.route("*", NotFound);

View File

@ -5,10 +5,9 @@ import { getKeys as TurnstileKeys, isEnabled as Turnstile } from "../../lib/turn
import { getConnInfo } from "@hono/node-server/conninfo";
import { compareSync as passwordHashCheck } from "bcrypt";
import { v4 as uuid } from "uuid";
import MailVerifySend from "../../lib/mailverify.js";
import { createAPIToken } from "src/lib/token.js";
import { UAParser } from "ua-parser-js";
import { setCookie } from "hono/cookie";
import type scope from "../../../types/api/scope.js";
const SignInAPI = new Hono();
@ -26,7 +25,7 @@ SignInAPI.post("/", async (c) => {
if (
body.username.length < 3 ||
body.username.length > 15 ||
body.username.length > 20 ||
body.password.length < 8 ||
body.password.length > 15
) {
@ -95,10 +94,22 @@ SignInAPI.post("/", async (c) => {
}, 400);
}
if (user[0].mailverify === 0) {
return c.json({
success: false,
error: "not_mailverify",
}, 400);
}
if (passwordHashCheck(body.password, user[0].password)) {
const scope: scope[] = ["user:client"];
if (user[0].isAdmin === 1) {
scope.push("admin:client");
}
const token = await createAPIToken(
body.username,
["client"],
scope,
"Peas Client"
);

View File

@ -24,7 +24,7 @@ SignUpAPI.post("/", async (c) => {
if (
body.username.length < 3 ||
body.username.length > 15 ||
body.username.length > 20 ||
body.password.length < 8 ||
body.password.length > 15
) {
@ -107,9 +107,18 @@ SignUpAPI.post("/", async (c) => {
const passwordHash = await generatePasswordHash(body.password, 10);
const [otherUser] = await pool.execute<RowDataPacket[]>(
"SELECT * FROM users",
);
let isAdmin = 0;
if (otherUser.length === 0) {
isAdmin = 1;
}
const [result] = await pool.execute<RowDataPacket[]>(
"INSERT INTO `users` (`id`, `password`, `email`, `mailverified`, `time`) VALUES (?, ?, ?, '0', current_timestamp(3))",
[body.username, passwordHash, body.email],
"INSERT INTO `users` (`id`, `name`, `password`, `email`, `mailverified`, `isAdmin`, `time`) VALUES (?, ?, ?, ?, '0', ?, current_timestamp(3))",
[body.username, body.username, passwordHash, body.email, String(isAdmin)],
);
if ((result as RowDataPacket).affectedRows === 1) {

View File

@ -0,0 +1,5 @@
import { Hono } from "hono";
const Community = new Hono();
export default Community;

View File

@ -0,0 +1,11 @@
import { Hono } from "hono";
const TimeLine = new Hono();
import Users from "./users.js";
TimeLine.route("/users", Users);
import Community from "./community.js";
TimeLine.route("/community", Community);
export default TimeLine;

View File

@ -0,0 +1,46 @@
import { Hono } from "hono";
import { Auth, getHeaderToken } from "../../../lib/token.js";
import pool from "../../../lib/database.js";
import type { RowDataPacket } from "mysql2";
const Users = new Hono();
Users.post("/", async (c) => {
const body = await c.req.json();
if (!Auth(getHeaderToken(c.req.header("Authorization") ?? ""), ["read:user"])) {
return c.json({
success: false,
error: "auth_failed",
});
}
let page = 1;
if (
typeof body.page === "string" &&
!isNaN(Number(body.page)) &&
Number(body.page) >= 1
) {
page = Number(body.page);
}
const [usersData] = await pool.execute<RowDataPacket[]>(
"SELECT * FROM users"
);
let result = [];
for (let i = usersData.length - 1; i < 0; i--) {
result.push({
username: usersData[i].id,
name: usersData[i].name,
isAdmin: usersData[i].isAdmin === 1 ? true: false,
createAt: usersData[i].time,
});
}
return c.json({
success: true,
users: result,
});
});
export default Users;

View File

@ -4,11 +4,14 @@ import type InfoAPI from "../../../types/api/info";
import Config from "../../../config/peas.config.js";
import { getCookie } from "hono/cookie";
import { Locale } from "../../lib/locale.js";
import { isSignin } from "../../lib/token.js";
const Home = new Hono();
Home.get("/", async (c) => {
if (getCookie(c, "token") === undefined) return c.redirect("/signin");
if (await isSignin(getCookie(c, "token") ?? "") === false) {
return c.redirect("/signin");
}
const InfoReq = await fetch(`${Config.server.origin}/api/info`, {
method: "POST",

View File

@ -6,14 +6,13 @@ import Icon from "../../components/iconify.js";
import { Locale } from "../../lib/locale.js";
import toComponent from "../../lib/toComponent.js";
import { getCookie } from "hono/cookie";
import { getScopeAPIToken } from "../../lib/token.js";
import { isSignin } from "../../lib/token.js";
const Index = new Hono();
Index.get("/", async (c) => {
if (getCookie(c, "token") !== undefined) {
const scope = await getScopeAPIToken(getCookie(c, "token") ?? "");
if (scope !== undefined) return c.redirect("/home");
if (await isSignin(getCookie(c, "token") ?? "")) {
return c.redirect("/home");
}
const InfoReq = await fetch(`${Config.server.origin}/api/info`, {

View File

@ -8,14 +8,13 @@ import { getKeys as getTurnstileKeys, isEnabled as TurnstileIsEnabled } from "..
import Turnstile from "../../components/turnstile.js";
import { html } from "hono/html";
import { getCookie } from "hono/cookie";
import { getScopeAPIToken } from "../../lib/token.js";
import { isSignin } from "../../lib/token.js";
const MailVerify = new Hono();
MailVerify.get("/", async (c) => {
if (getCookie(c, "token") !== undefined) {
const scope = await getScopeAPIToken(getCookie(c, "token") ?? "");
if (scope !== undefined) return c.redirect("/home");
if (await isSignin(getCookie(c, "token") ?? "")) {
return c.redirect("/home");
}
const InfoReq = await fetch(`${Config.server.origin}/api/info`, {

View File

@ -9,14 +9,13 @@ import Turnstile from "../../components/turnstile.js";
import { getKeys as getTurnstileKeys, isEnabled as TurnstileIsEnabled } from "../../lib/turnstile.js";
import { html } from "hono/html";
import { getCookie } from "hono/cookie";
import { getScopeAPIToken } from "../../lib/token.js";
import { isSignin } from "../../lib/token.js";
const SignIn = new Hono();
SignIn.get("/", async (c) => {
if (getCookie(c, "token") !== undefined) {
const scope = await getScopeAPIToken(getCookie(c, "token") ?? "");
if (scope !== undefined) return c.redirect("/home");
if (await isSignin(getCookie(c, "token") ?? "")) {
return c.redirect("/home");
}
const InfoReq = await fetch(`${Config.server.origin}/api/info`, {

View File

@ -10,14 +10,13 @@ import Turnstile from "../../components/turnstile.js";
import { getKeys as getTurnstileKeys, isEnabled as TurnstileIsEnabled } from "../../lib/turnstile.js";
import { html } from "hono/html";
import { getCookie } from "hono/cookie";
import { getScopeAPIToken } from "../../lib/token.js";
import { isSignin } from "../../lib/token.js";
const SignUp = new Hono();
SignUp.get("/", async (c) => {
if (getCookie(c, "token") !== undefined) {
const scope = await getScopeAPIToken(getCookie(c, "token") ?? "");
if (scope !== undefined) return c.redirect("/home");
if (await isSignin(getCookie(c, "token") ?? "")) {
return c.redirect("/home");
}
const InfoReq = await fetch(`${Config.server.origin}/api/info`, {

View File

@ -1,5 +1,6 @@
type scope =
"read:user" |
"client";
"admin:client" |
"user:client";
export default scope;

View File

@ -10,10 +10,10 @@ importers:
dependencies:
'@inquirer/prompts':
specifier: ^7.8.6
version: 7.8.6(@types/node@24.5.2)
version: 7.8.6(@types/node@24.6.2)
'@types/node':
specifier: ^24.5.2
version: 24.5.2
version: 24.6.2
fs:
specifier: 0.0.1-security
version: 0.0.1-security
@ -22,7 +22,7 @@ importers:
version: 3.15.1
typescript:
specifier: ^5.9.2
version: 5.9.2
version: 5.9.3
yaml:
specifier: ^2.8.1
version: 2.8.1
@ -163,8 +163,8 @@ packages:
'@types/node':
optional: true
'@types/node@24.5.2':
resolution: {integrity: sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==}
'@types/node@24.6.2':
resolution: {integrity: sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang==}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
@ -261,13 +261,13 @@ packages:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
typescript@5.9.2:
resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
undici-types@7.12.0:
resolution: {integrity: sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==}
undici-types@7.13.0:
resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==}
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
@ -286,132 +286,132 @@ snapshots:
'@inquirer/ansi@1.0.0': {}
'@inquirer/checkbox@4.2.4(@types/node@24.5.2)':
'@inquirer/checkbox@4.2.4(@types/node@24.6.2)':
dependencies:
'@inquirer/ansi': 1.0.0
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/figures': 1.0.13
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
yoctocolors-cjs: 2.1.3
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/confirm@5.1.18(@types/node@24.5.2)':
'@inquirer/confirm@5.1.18(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/core@10.2.2(@types/node@24.5.2)':
'@inquirer/core@10.2.2(@types/node@24.6.2)':
dependencies:
'@inquirer/ansi': 1.0.0
'@inquirer/figures': 1.0.13
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
cli-width: 4.1.0
mute-stream: 2.0.0
signal-exit: 4.1.0
wrap-ansi: 6.2.0
yoctocolors-cjs: 2.1.3
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/editor@4.2.20(@types/node@24.5.2)':
'@inquirer/editor@4.2.20(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/external-editor': 1.0.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/external-editor': 1.0.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/expand@4.0.20(@types/node@24.5.2)':
'@inquirer/expand@4.0.20(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
yoctocolors-cjs: 2.1.3
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/external-editor@1.0.2(@types/node@24.5.2)':
'@inquirer/external-editor@1.0.2(@types/node@24.6.2)':
dependencies:
chardet: 2.1.0
iconv-lite: 0.7.0
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/figures@1.0.13': {}
'@inquirer/input@4.2.4(@types/node@24.5.2)':
'@inquirer/input@4.2.4(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/number@3.0.20(@types/node@24.5.2)':
'@inquirer/number@3.0.20(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/password@4.0.20(@types/node@24.5.2)':
'@inquirer/password@4.0.20(@types/node@24.6.2)':
dependencies:
'@inquirer/ansi': 1.0.0
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/prompts@7.8.6(@types/node@24.5.2)':
'@inquirer/prompts@7.8.6(@types/node@24.6.2)':
dependencies:
'@inquirer/checkbox': 4.2.4(@types/node@24.5.2)
'@inquirer/confirm': 5.1.18(@types/node@24.5.2)
'@inquirer/editor': 4.2.20(@types/node@24.5.2)
'@inquirer/expand': 4.0.20(@types/node@24.5.2)
'@inquirer/input': 4.2.4(@types/node@24.5.2)
'@inquirer/number': 3.0.20(@types/node@24.5.2)
'@inquirer/password': 4.0.20(@types/node@24.5.2)
'@inquirer/rawlist': 4.1.8(@types/node@24.5.2)
'@inquirer/search': 3.1.3(@types/node@24.5.2)
'@inquirer/select': 4.3.4(@types/node@24.5.2)
'@inquirer/checkbox': 4.2.4(@types/node@24.6.2)
'@inquirer/confirm': 5.1.18(@types/node@24.6.2)
'@inquirer/editor': 4.2.20(@types/node@24.6.2)
'@inquirer/expand': 4.0.20(@types/node@24.6.2)
'@inquirer/input': 4.2.4(@types/node@24.6.2)
'@inquirer/number': 3.0.20(@types/node@24.6.2)
'@inquirer/password': 4.0.20(@types/node@24.6.2)
'@inquirer/rawlist': 4.1.8(@types/node@24.6.2)
'@inquirer/search': 3.1.3(@types/node@24.6.2)
'@inquirer/select': 4.3.4(@types/node@24.6.2)
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/rawlist@4.1.8(@types/node@24.5.2)':
'@inquirer/rawlist@4.1.8(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
yoctocolors-cjs: 2.1.3
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/search@3.1.3(@types/node@24.5.2)':
'@inquirer/search@3.1.3(@types/node@24.6.2)':
dependencies:
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/figures': 1.0.13
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
yoctocolors-cjs: 2.1.3
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/select@4.3.4(@types/node@24.5.2)':
'@inquirer/select@4.3.4(@types/node@24.6.2)':
dependencies:
'@inquirer/ansi': 1.0.0
'@inquirer/core': 10.2.2(@types/node@24.5.2)
'@inquirer/core': 10.2.2(@types/node@24.6.2)
'@inquirer/figures': 1.0.13
'@inquirer/type': 3.0.8(@types/node@24.5.2)
'@inquirer/type': 3.0.8(@types/node@24.6.2)
yoctocolors-cjs: 2.1.3
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@inquirer/type@3.0.8(@types/node@24.5.2)':
'@inquirer/type@3.0.8(@types/node@24.6.2)':
optionalDependencies:
'@types/node': 24.5.2
'@types/node': 24.6.2
'@types/node@24.5.2':
'@types/node@24.6.2':
dependencies:
undici-types: 7.12.0
undici-types: 7.13.0
ansi-regex@5.0.1: {}
@ -491,9 +491,9 @@ snapshots:
dependencies:
ansi-regex: 5.0.1
typescript@5.9.2: {}
typescript@5.9.3: {}
undici-types@7.12.0: {}
undici-types@7.13.0: {}
wrap-ansi@6.2.0:
dependencies:

View File

@ -88,10 +88,12 @@ DROP TABLE IF EXISTS `users`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `users` (
`id` text NOT NULL,
`id` VARCHAR(20) NOT NULL,
`name` VARCHAR(50) NOT NULL,
`password` text NOT NULL,
`email` text NOT NULL,
`mailverified` int(1) NOT NULL DEFAULT 0,
`isAdmin` int(1) NOT NULL DEFAULT 0,
`time` datetime(3) NOT NULL DEFAULT current_timestamp(3),
`num` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`num`),