mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
refactor(api): 🎨 Don't use node:crypto for random strings
This commit is contained in:
parent
d8cb1d475b
commit
d301d4da09
|
|
@ -59,6 +59,6 @@
|
||||||
"ignore": ["node_modules", "dist", "glitch", "glitch-dev"]
|
"ignore": ["node_modules", "dist", "glitch", "glitch-dev"]
|
||||||
},
|
},
|
||||||
"javascript": {
|
"javascript": {
|
||||||
"globals": ["Bun", "HTMLRewriter"]
|
"globals": ["Bun", "HTMLRewriter", "BufferEncoding"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { idValidator } from "@/api";
|
import { idValidator } from "@/api";
|
||||||
import { getBestContentType, urlToContentFormat } from "@/content_types";
|
import { getBestContentType, urlToContentFormat } from "@/content_types";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { addUserToMeilisearch } from "@/meilisearch";
|
import { addUserToMeilisearch } from "@/meilisearch";
|
||||||
import { proxyUrl } from "@/response";
|
import { proxyUrl } from "@/response";
|
||||||
import { EntityValidator } from "@lysand-org/federation";
|
import { EntityValidator } from "@lysand-org/federation";
|
||||||
|
|
@ -190,7 +190,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async resetPassword() {
|
async resetPassword() {
|
||||||
const resetToken = await randomBytes(32).toString("hex");
|
const resetToken = randomString(32, "hex");
|
||||||
|
|
||||||
await this.update({
|
await this.update({
|
||||||
passwordResetToken: resetToken,
|
passwordResetToken: resetToken,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import { randomBytes } from "node:crypto";
|
import { randomString } from "@/math";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "~/drizzle/db";
|
import { db } from "~/drizzle/db";
|
||||||
import { Applications } from "~/drizzle/schema";
|
import { Applications } from "~/drizzle/schema";
|
||||||
|
|
@ -15,7 +15,7 @@ const application = (
|
||||||
.insert(Applications)
|
.insert(Applications)
|
||||||
.values({
|
.values({
|
||||||
name: "Test Application",
|
name: "Test Application",
|
||||||
clientId: randomBytes(32).toString("hex"),
|
clientId: randomString(32, "hex"),
|
||||||
secret: "test",
|
secret: "test",
|
||||||
redirectUri: "https://example.com",
|
redirectUri: "https://example.com",
|
||||||
scopes: "read write",
|
scopes: "read write",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { applyConfig, handleZodError } from "@/api";
|
import { applyConfig, handleZodError } from "@/api";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { response } from "@/response";
|
import { response } from "@/response";
|
||||||
import { zValidator } from "@hono/zod-validator";
|
import { zValidator } from "@hono/zod-validator";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
|
|
@ -81,8 +81,8 @@ export default (app: Hono) =>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = randomBytes(32).toString("hex");
|
const code = randomString(32, "hex");
|
||||||
const accessToken = randomBytes(64).toString("base64url");
|
const accessToken = randomString(64, "base64url");
|
||||||
|
|
||||||
await db.insert(Tokens).values({
|
await db.insert(Tokens).values({
|
||||||
accessToken,
|
accessToken,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { afterAll, describe, expect, test } from "bun:test";
|
import { afterAll, describe, expect, test } from "bun:test";
|
||||||
import { randomBytes } from "node:crypto";
|
import { randomString } from "@/math";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "~/drizzle/db";
|
import { db } from "~/drizzle/db";
|
||||||
import { Applications } from "~/drizzle/schema";
|
import { Applications } from "~/drizzle/schema";
|
||||||
|
|
@ -8,8 +8,8 @@ import { getTestUsers, sendTestRequest } from "~/tests/utils";
|
||||||
import { meta } from "./index";
|
import { meta } from "./index";
|
||||||
|
|
||||||
const { users, deleteUsers, passwords } = await getTestUsers(1);
|
const { users, deleteUsers, passwords } = await getTestUsers(1);
|
||||||
const token = randomBytes(32).toString("hex");
|
const token = randomString(32, "hex");
|
||||||
const newPassword = randomBytes(16).toString("hex");
|
const newPassword = randomString(16, "hex");
|
||||||
|
|
||||||
// Create application
|
// Create application
|
||||||
const application = (
|
const application = (
|
||||||
|
|
@ -17,7 +17,7 @@ const application = (
|
||||||
.insert(Applications)
|
.insert(Applications)
|
||||||
.values({
|
.values({
|
||||||
name: "Test Application",
|
name: "Test Application",
|
||||||
clientId: randomBytes(32).toString("hex"),
|
clientId: randomString(32, "hex"),
|
||||||
secret: "test",
|
secret: "test",
|
||||||
redirectUri: "https://example.com",
|
redirectUri: "https://example.com",
|
||||||
scopes: "read write",
|
scopes: "read write",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { afterEach, describe, expect, test } from "bun:test";
|
import { afterEach, describe, expect, test } from "bun:test";
|
||||||
import { randomBytes } from "node:crypto";
|
import { randomString } from "@/math";
|
||||||
import { config } from "config-manager";
|
import { config } from "config-manager";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "~/drizzle/db";
|
import { db } from "~/drizzle/db";
|
||||||
|
|
@ -7,8 +7,8 @@ import { Users } from "~/drizzle/schema";
|
||||||
import { sendTestRequest } from "~/tests/utils";
|
import { sendTestRequest } from "~/tests/utils";
|
||||||
import { meta } from "./index";
|
import { meta } from "./index";
|
||||||
|
|
||||||
const username = randomBytes(10).toString("hex");
|
const username = randomString(10, "hex");
|
||||||
const username2 = randomBytes(10).toString("hex");
|
const username2 = randomString(10, "hex");
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await db.delete(Users).where(eq(Users.username, username));
|
await db.delete(Users).where(eq(Users.username, username));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { applyConfig, handleZodError, jsonOrForm } from "@/api";
|
import { applyConfig, handleZodError, jsonOrForm } from "@/api";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { jsonResponse } from "@/response";
|
import { jsonResponse } from "@/response";
|
||||||
import { zValidator } from "@hono/zod-validator";
|
import { zValidator } from "@hono/zod-validator";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
|
|
@ -54,8 +54,8 @@ export default (app: Hono) =>
|
||||||
redirectUri: decodeURIComponent(redirect_uris) || "",
|
redirectUri: decodeURIComponent(redirect_uris) || "",
|
||||||
scopes: scopes || "read",
|
scopes: scopes || "read",
|
||||||
website: website || null,
|
website: website || null,
|
||||||
clientId: randomBytes(32).toString("base64url"),
|
clientId: randomString(32, "base64url"),
|
||||||
secret: randomBytes(64).toString("base64url"),
|
secret: randomString(64, "base64url"),
|
||||||
})
|
})
|
||||||
.returning()
|
.returning()
|
||||||
)[0];
|
)[0];
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { applyConfig, auth, handleZodError, jsonOrForm } from "@/api";
|
import { applyConfig, auth, handleZodError, jsonOrForm } from "@/api";
|
||||||
import { oauthRedirectUri } from "@/constants";
|
import { oauthRedirectUri } from "@/constants";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { errorResponse, jsonResponse } from "@/response";
|
import { errorResponse, jsonResponse } from "@/response";
|
||||||
import { zValidator } from "@hono/zod-validator";
|
import { zValidator } from "@hono/zod-validator";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
|
|
@ -134,9 +134,7 @@ export default (app: Hono) =>
|
||||||
await db
|
await db
|
||||||
.insert(Applications)
|
.insert(Applications)
|
||||||
.values({
|
.values({
|
||||||
clientId:
|
clientId: user.id + randomString(32, "base64"),
|
||||||
user.id +
|
|
||||||
randomBytes(32).toString("base64url"),
|
|
||||||
name: "Lysand",
|
name: "Lysand",
|
||||||
redirectUri: `${oauthRedirectUri(issuerId)}`,
|
redirectUri: `${oauthRedirectUri(issuerId)}`,
|
||||||
scopes: "openid profile email",
|
scopes: "openid profile email",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { applyConfig, handleZodError, jsonOrForm } from "@/api";
|
import { applyConfig, handleZodError, jsonOrForm } from "@/api";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { response } from "@/response";
|
import { response } from "@/response";
|
||||||
import { zValidator } from "@hono/zod-validator";
|
import { zValidator } from "@hono/zod-validator";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
|
|
@ -240,7 +240,7 @@ export default (app: Hono) =>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate tokens
|
// Generate tokens
|
||||||
const code = randomBytes(256).toString("base64url");
|
const code = randomString(256, "base64url");
|
||||||
|
|
||||||
// Handle the requested scopes
|
// Handle the requested scopes
|
||||||
let idTokenPayload = {};
|
let idTokenPayload = {};
|
||||||
|
|
@ -287,7 +287,7 @@ export default (app: Hono) =>
|
||||||
.sign(privateKey);
|
.sign(privateKey);
|
||||||
|
|
||||||
await db.insert(Tokens).values({
|
await db.insert(Tokens).values({
|
||||||
accessToken: randomBytes(64).toString("base64url"),
|
accessToken: randomString(64, "base64url"),
|
||||||
code: code,
|
code: code,
|
||||||
scope: scope ?? application.scopes,
|
scope: scope ?? application.scopes,
|
||||||
tokenType: TokenType.Bearer,
|
tokenType: TokenType.Bearer,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { applyConfig, handleZodError } from "@/api";
|
import { applyConfig, handleZodError } from "@/api";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { errorResponse, response } from "@/response";
|
import { errorResponse, response } from "@/response";
|
||||||
import { zValidator } from "@hono/zod-validator";
|
import { zValidator } from "@hono/zod-validator";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
|
|
@ -174,10 +174,10 @@ export default (app: Hono) =>
|
||||||
return errorResponse("Application not found", 500);
|
return errorResponse("Application not found", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = randomBytes(32).toString("hex");
|
const code = randomString(32, "hex");
|
||||||
|
|
||||||
await db.insert(Tokens).values({
|
await db.insert(Tokens).values({
|
||||||
accessToken: randomBytes(64).toString("base64url"),
|
accessToken: randomString(64, "base64url"),
|
||||||
code: code,
|
code: code,
|
||||||
scope: flow.application.scopes,
|
scope: flow.application.scopes,
|
||||||
tokenType: TokenType.Bearer,
|
tokenType: TokenType.Bearer,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { randomBytes } from "node:crypto";
|
|
||||||
import { consoleLogger } from "@/loggers";
|
import { consoleLogger } from "@/loggers";
|
||||||
|
import { randomString } from "@/math";
|
||||||
import { asc, inArray, like } from "drizzle-orm";
|
import { asc, inArray, like } from "drizzle-orm";
|
||||||
import type { Status } from "~/database/entities/status";
|
import type { Status } from "~/database/entities/status";
|
||||||
import { db } from "~/drizzle/db";
|
import { db } from "~/drizzle/db";
|
||||||
|
|
@ -35,11 +35,11 @@ export const getTestUsers = async (count: number) => {
|
||||||
const passwords: string[] = [];
|
const passwords: string[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const password = randomBytes(32).toString("hex");
|
const password = randomString(32, "hex");
|
||||||
|
|
||||||
const user = await User.fromDataLocal({
|
const user = await User.fromDataLocal({
|
||||||
username: `test-${randomBytes(32).toString("hex")}`,
|
username: `test-${randomString(32, "hex")}`,
|
||||||
email: `${randomBytes(32).toString("hex")}@test.com`,
|
email: `${randomString(32, "hex")}@test.com`,
|
||||||
password,
|
password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -55,11 +55,11 @@ export const getTestUsers = async (count: number) => {
|
||||||
.insert(Tokens)
|
.insert(Tokens)
|
||||||
.values(
|
.values(
|
||||||
users.map((u) => ({
|
users.map((u) => ({
|
||||||
accessToken: randomBytes(32).toString("hex"),
|
accessToken: randomString(32, "hex"),
|
||||||
tokenType: "bearer",
|
tokenType: "bearer",
|
||||||
userId: u.id,
|
userId: u.id,
|
||||||
applicationId: null,
|
applicationId: null,
|
||||||
code: randomBytes(32).toString("hex"),
|
code: randomString(32, "hex"),
|
||||||
scope: "read write follow push",
|
scope: "read write follow push",
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
|
|
@ -89,7 +89,7 @@ export const getTestStatuses = async (
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const newStatus = await Note.insert({
|
const newStatus = await Note.insert({
|
||||||
content: `${i} ${randomBytes(32).toString("hex")}`,
|
content: `${i} ${randomString(32, "hex")}`,
|
||||||
authorId: user.id,
|
authorId: user.id,
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
|
|
|
||||||
4
utils/math.ts
Normal file
4
utils/math.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const randomString = (length: number, encoding?: BufferEncoding) =>
|
||||||
|
Buffer.from(crypto.getRandomValues(new Uint8Array(length))).toString(
|
||||||
|
encoding,
|
||||||
|
);
|
||||||
Loading…
Reference in a new issue