remove excess comments

This commit is contained in:
Michael Freno
2025-12-23 10:30:51 -05:00
parent 236555e41e
commit 8ca8e6f712
29 changed files with 1 additions and 242 deletions

View File

@@ -432,9 +432,8 @@ export const authRouter = createTRPCRouter({
};
if (rememberMe) {
cookieOptions.maxAge = 60 * 60 * 24 * 14; // 14 days
cookieOptions.maxAge = 60 * 60 * 24 * 14;
}
// If rememberMe is false, cookie will be session-only (no maxAge)
setCookie(
ctx.event.nativeEvent,
@@ -591,7 +590,6 @@ export const authRouter = createTRPCRouter({
});
}
// If provider is unknown/null, update it to "email" since they're logging in with password
if (
!user.provider ||
!["email", "google", "github", "apple"].includes(user.provider)
@@ -669,7 +667,6 @@ export const authRouter = createTRPCRouter({
.setExpirationTime("15m")
.sign(secret);
// Send email
const domain = env.VITE_DOMAIN || "https://freno.me";
const htmlContent = `<html>
<head>
@@ -754,7 +751,6 @@ export const authRouter = createTRPCRouter({
const { email } = input;
try {
// Check rate limiting
const requested = getCookie(
ctx.event.nativeEvent,
"passwordResetRequested"
@@ -777,20 +773,16 @@ export const authRouter = createTRPCRouter({
});
if (res.rows.length === 0) {
// Don't reveal if user exists
return { success: true, message: "email sent" };
}
const user = res.rows[0] as unknown as User;
// Create JWT token with user ID (15min expiry)
const secret = new TextEncoder().encode(env.JWT_SECRET_KEY);
const token = await new SignJWT({ id: user.id })
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime("15m")
.sign(secret);
// Send email
const domain = env.VITE_DOMAIN || "https://freno.me";
const htmlContent = `<html>
<head>
@@ -832,7 +824,6 @@ export const authRouter = createTRPCRouter({
await sendEmail(email, "password reset", htmlContent);
// Set rate limit cookie (5 minutes)
const exp = new Date(Date.now() + 5 * 60 * 1000);
setCookie(
ctx.event.nativeEvent,
@@ -870,7 +861,6 @@ export const authRouter = createTRPCRouter({
}
}),
// Reset password with token
resetPassword: publicProcedure
.input(
z.object({
@@ -890,7 +880,6 @@ export const authRouter = createTRPCRouter({
}
try {
// Verify JWT token
const secret = new TextEncoder().encode(env.JWT_SECRET_KEY);
const { payload } = await jwtVerify(token, secret);
@@ -904,7 +893,6 @@ export const authRouter = createTRPCRouter({
const conn = ConnectionFactory();
const passwordHash = await hashPassword(newPassword);
// Get user to check current provider
const userRes = await conn.execute({
sql: "SELECT provider FROM User WHERE id = ?",
args: [payload.id]
@@ -919,7 +907,6 @@ export const authRouter = createTRPCRouter({
const currentProvider = (userRes.rows[0] as any).provider;
// Only update provider to "email" if it's null, undefined, or not a known OAuth provider
if (
!currentProvider ||
!["google", "github", "apple"].includes(currentProvider)
@@ -929,14 +916,12 @@ export const authRouter = createTRPCRouter({
args: [passwordHash, "email", payload.id]
});
} else {
// Keep existing OAuth provider, just update password
await conn.execute({
sql: "UPDATE User SET password_hash = ? WHERE id = ?",
args: [passwordHash, payload.id]
});
}
// Clear any session cookies
setCookie(ctx.event.nativeEvent, "emailToken", "", {
maxAge: 0,
path: "/"
@@ -959,14 +944,12 @@ export const authRouter = createTRPCRouter({
}
}),
// Resend email verification
resendEmailVerification: publicProcedure
.input(z.object({ email: z.string().email() }))
.mutation(async ({ input, ctx }) => {
const { email } = input;
try {
// Check rate limiting
const requested = getCookie(
ctx.event.nativeEvent,
"emailVerificationRequested"
@@ -998,14 +981,12 @@ export const authRouter = createTRPCRouter({
});
}
// Create JWT token (15min expiry)
const secret = new TextEncoder().encode(env.JWT_SECRET_KEY);
const token = await new SignJWT({ email })
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime("15m")
.sign(secret);
// Send email
const domain = env.VITE_DOMAIN || "https://freno.me";
const htmlContent = `<html>
<head>
@@ -1044,7 +1025,6 @@ export const authRouter = createTRPCRouter({
await sendEmail(email, "freno.me email verification", htmlContent);
// Set rate limit cookie
setCookie(
ctx.event.nativeEvent,
"emailVerificationRequested",
@@ -1081,7 +1061,6 @@ export const authRouter = createTRPCRouter({
}
}),
// Sign out
signOut: publicProcedure.mutation(async ({ ctx }) => {
setCookie(ctx.event.nativeEvent, "userIDToken", "", {
maxAge: 0,

View File

@@ -162,7 +162,6 @@ export const databaseRouter = createTRPCRouter({
requestingUser: ctx.userId
});
// User can only delete their own comments with "user" type
if (input.deletionType === "user" && !isOwner && !isAdmin) {
throw new TRPCError({
code: "FORBIDDEN",
@@ -170,7 +169,6 @@ export const databaseRouter = createTRPCRouter({
});
}
// Only admins can do admin or database deletion
if (
(input.deletionType === "admin" ||
input.deletionType === "database") &&
@@ -184,14 +182,11 @@ export const databaseRouter = createTRPCRouter({
if (input.deletionType === "database") {
console.log("[deleteComment] Performing database deletion");
// Full deletion - remove from database
// First delete reactions
await conn.execute({
sql: "DELETE FROM CommentReaction WHERE comment_id = ?",
args: [input.commentID]
});
// Then delete the comment
await conn.execute({
sql: "DELETE FROM Comment WHERE id = ?",
args: [input.commentID]
@@ -205,7 +200,6 @@ export const databaseRouter = createTRPCRouter({
};
} else if (input.deletionType === "admin") {
console.log("[deleteComment] Performing admin deletion");
// Admin delete - replace body with admin message
await conn.execute({
sql: "UPDATE Comment SET body = ?, commenter_id = ? WHERE id = ?",
args: ["[deleted by admin]", "", input.commentID]
@@ -219,7 +213,6 @@ export const databaseRouter = createTRPCRouter({
};
} else {
console.log("[deleteComment] Performing user deletion");
// User delete - replace body with user message
await conn.execute({
sql: "UPDATE Comment SET body = ?, commenter_id = ? WHERE id = ?",
args: ["[deleted]", "", input.commentID]
@@ -249,7 +242,6 @@ export const databaseRouter = createTRPCRouter({
.query(async ({ input }) => {
try {
const conn = ConnectionFactory();
// Join with Post table to get post titles along with comments
const query = `
SELECT c.*, p.title as post_title
FROM Comment c
@@ -270,10 +262,6 @@ export const databaseRouter = createTRPCRouter({
}
}),
// ============================================================
// Post Routes
// ============================================================
getPostById: publicProcedure
.input(
z.object({
@@ -288,7 +276,6 @@ export const databaseRouter = createTRPCRouter({
async () => {
try {
const conn = ConnectionFactory();
// Single query with JOIN to get post and tags in one go
const query = `
SELECT p.*, t.value as tag_value
FROM Post p
@@ -301,7 +288,6 @@ export const databaseRouter = createTRPCRouter({
});
if (results.rows[0]) {
// Group tags by post ID
const post = results.rows[0];
const tags = results.rows
.filter((row) => row.tag_value)
@@ -339,7 +325,6 @@ export const databaseRouter = createTRPCRouter({
try {
const conn = ConnectionFactory();
// Get post by title with JOINs to get all related data in one query
const postQuery = `
SELECT
p.*,
@@ -364,7 +349,6 @@ export const databaseRouter = createTRPCRouter({
const postRow = postResults.rows[0];
// Return structured data with proper formatting
return {
post: postRow,
comments: [], // Comments are not included in this optimized query - would need separate call if needed
@@ -426,7 +410,6 @@ export const databaseRouter = createTRPCRouter({
await conn.execute(tagQuery);
}
// Invalidate blog cache
cache.deleteByPrefix("blog-");
return { data: results.lastInsertRowid };
@@ -502,7 +485,6 @@ export const databaseRouter = createTRPCRouter({
const results = await conn.execute({ sql: query, args: params });
// Handle tags
const deleteTagsQuery = `DELETE FROM Tag WHERE post_id = ?`;
await conn.execute({
sql: deleteTagsQuery,
@@ -516,7 +498,6 @@ export const databaseRouter = createTRPCRouter({
await conn.execute(tagQuery);
}
// Invalidate blog cache
cache.deleteByPrefix("blog-");
return { data: results.lastInsertRowid };
@@ -535,31 +516,26 @@ export const databaseRouter = createTRPCRouter({
try {
const conn = ConnectionFactory();
// Delete associated tags first
await conn.execute({
sql: "DELETE FROM Tag WHERE post_id = ?",
args: [input.id.toString()]
});
// Delete associated likes
await conn.execute({
sql: "DELETE FROM PostLike WHERE post_id = ?",
args: [input.id.toString()]
});
// Delete associated comments
await conn.execute({
sql: "DELETE FROM Comment WHERE post_id = ?",
args: [input.id]
});
// Finally delete the post
await conn.execute({
sql: "DELETE FROM Post WHERE id = ?",
args: [input.id]
});
// Invalidate blog cache
cache.deleteByPrefix("blog-");
return { success: true };

View File

@@ -10,7 +10,6 @@ import {
APIError
} from "~/server/fetch-utils";
// Types for commits
interface GitCommit {
sha: string;
message: string;
@@ -26,7 +25,6 @@ interface ContributionDay {
}
export const gitActivityRouter = createTRPCRouter({
// Get recent commits from GitHub
getGitHubCommits: publicProcedure
.input(z.object({ limit: z.number().default(3) }))
.query(async ({ input }) => {
@@ -34,7 +32,6 @@ export const gitActivityRouter = createTRPCRouter({
`github-commits-${input.limit}`,
10 * 60 * 1000, // 10 minutes
async () => {
// Get user's repositories sorted by most recently pushed
const reposResponse = await fetchWithTimeout(
`https://api.github.com/users/MikeFreno/repos?sort=pushed&per_page=10`,
{
@@ -50,7 +47,6 @@ export const gitActivityRouter = createTRPCRouter({
const repos = await reposResponse.json();
const allCommits: GitCommit[] = [];
// Fetch recent commits from each repo
for (const repo of repos) {
if (allCommits.length >= input.limit * 3) break; // Get extra to sort later
@@ -69,7 +65,6 @@ export const gitActivityRouter = createTRPCRouter({
if (commitsResponse.ok) {
const commits = await commitsResponse.json();
for (const commit of commits) {
// Filter for commits by the authenticated user
if (
commit.author?.login === "MikeFreno" ||
commit.commit?.author?.email?.includes("mike")
@@ -91,7 +86,6 @@ export const gitActivityRouter = createTRPCRouter({
}
}
} catch (error) {
// Log individual repo failures but continue with others
if (
error instanceof NetworkError ||
error instanceof TimeoutError
@@ -108,7 +102,6 @@ export const gitActivityRouter = createTRPCRouter({
}
}
// Sort by date and return the most recent
allCommits.sort(
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
);
@@ -117,7 +110,6 @@ export const gitActivityRouter = createTRPCRouter({
},
{ maxStaleMs: 24 * 60 * 60 * 1000 } // Accept stale data up to 24 hours old
).catch((error) => {
// Final fallback - return empty array if everything fails
if (error instanceof NetworkError) {
console.error("GitHub API unavailable (network error)");
} else if (error instanceof TimeoutError) {
@@ -133,7 +125,6 @@ export const gitActivityRouter = createTRPCRouter({
});
}),
// Get recent commits from Gitea
getGiteaCommits: publicProcedure
.input(z.object({ limit: z.number().default(3) }))
.query(async ({ input }) => {
@@ -141,7 +132,6 @@ export const gitActivityRouter = createTRPCRouter({
`gitea-commits-${input.limit}`,
10 * 60 * 1000, // 10 minutes
async () => {
// First, get user's repositories
const reposResponse = await fetchWithTimeout(
`${env.GITEA_URL}/api/v1/users/Mike/repos?limit=100`,
{
@@ -157,7 +147,6 @@ export const gitActivityRouter = createTRPCRouter({
const repos = await reposResponse.json();
const allCommits: GitCommit[] = [];
// Fetch recent commits from each repo
for (const repo of repos) {
if (allCommits.length >= input.limit * 3) break; // Get extra to sort later
@@ -199,7 +188,6 @@ export const gitActivityRouter = createTRPCRouter({
}
}
} catch (error) {
// Log individual repo failures but continue with others
if (
error instanceof NetworkError ||
error instanceof TimeoutError
@@ -216,7 +204,6 @@ export const gitActivityRouter = createTRPCRouter({
}
}
// Sort by date and return the most recent
allCommits.sort(
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
);
@@ -225,7 +212,6 @@ export const gitActivityRouter = createTRPCRouter({
},
{ maxStaleMs: 24 * 60 * 60 * 1000 }
).catch((error) => {
// Final fallback - return empty array if everything fails
if (error instanceof NetworkError) {
console.error("Gitea API unavailable (network error)");
} else if (error instanceof TimeoutError) {
@@ -245,7 +231,6 @@ export const gitActivityRouter = createTRPCRouter({
"github-activity",
10 * 60 * 1000,
async () => {
// Use GitHub GraphQL API for contribution data
const query = `
query($userName: String!) {
user(login: $userName) {
@@ -287,7 +272,6 @@ export const gitActivityRouter = createTRPCRouter({
throw new APIError("GraphQL query failed", 500, "GraphQL Error");
}
// Extract contribution days from the response
const contributions: ContributionDay[] = [];
const weeks =
data.data?.user?.contributionsCollection?.contributionCalendar
@@ -327,7 +311,6 @@ export const gitActivityRouter = createTRPCRouter({
"gitea-activity",
10 * 60 * 1000,
async () => {
// Get user's repositories
const reposResponse = await fetchWithTimeout(
`${env.GITEA_URL}/api/v1/user/repos?limit=100`,
{
@@ -343,7 +326,6 @@ export const gitActivityRouter = createTRPCRouter({
const repos = await reposResponse.json();
const contributionsByDay = new Map<string, number>();
// Get commits from each repo (last 3 months to avoid too many API calls)
const threeMonthsAgo = new Date();
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
@@ -373,7 +355,6 @@ export const gitActivityRouter = createTRPCRouter({
}
}
} catch (error) {
// Log individual repo failures but continue with others
if (
error instanceof NetworkError ||
error instanceof TimeoutError
@@ -387,7 +368,6 @@ export const gitActivityRouter = createTRPCRouter({
}
}
// Convert to array format
const contributions: ContributionDay[] = Array.from(
contributionsByDay.entries()
).map(([date, count]) => ({ date, count }));

View File

@@ -47,7 +47,6 @@ import potions from "~/lineage-json/item-route/potions.json";
import poison from "~/lineage-json/item-route/poison.json";
import staves from "~/lineage-json/item-route/staves.json";
// Misc data imports
import activities from "~/lineage-json/misc-route/activities.json";
import investments from "~/lineage-json/misc-route/investments.json";
import jobs from "~/lineage-json/misc-route/jobs.json";

View File

@@ -96,7 +96,6 @@ export const miscRouter = createTRPCRouter({
credentials: credentials
});
// Sanitize the title and filename for S3 key (replace spaces with hyphens, remove special chars)
const sanitizeForS3 = (str: string) => {
return str
.replace(/\s+/g, "-") // Replace spaces with hyphens
@@ -262,7 +261,6 @@ export const miscRouter = createTRPCRouter({
})
)
.mutation(async ({ input }) => {
// Check if contact request was recently sent
const contactExp = getCookie("contactRequestSent");
let remaining = 0;
@@ -314,7 +312,6 @@ export const miscRouter = createTRPCRouter({
}
);
// Set cookie to prevent spam (60 second cooldown)
const exp = new Date(Date.now() + 1 * 60 * 1000);
setCookie("contactRequestSent", exp.toUTCString(), {
expires: exp,
@@ -365,7 +362,6 @@ export const miscRouter = createTRPCRouter({
sendDeletionRequestEmail: publicProcedure
.input(z.object({ email: z.string().email() }))
.mutation(async ({ input }) => {
// Check if deletion request was recently sent
const deletionExp = getCookie("deletionRequestSent");
let remaining = 0;
@@ -445,7 +441,6 @@ export const miscRouter = createTRPCRouter({
)
]);
// Set cookie to prevent spam (60 second cooldown)
const exp = new Date(Date.now() + 1 * 60 * 1000);
setCookie("deletionRequestSent", exp.toUTCString(), {
expires: exp,

View File

@@ -13,7 +13,6 @@ import type { User } from "~/types/user";
import { toUserProfile } from "~/types/user";
export const userRouter = createTRPCRouter({
// Get current user profile
getProfile: publicProcedure.query(async ({ ctx }) => {
const userId = await getUserID(ctx.event.nativeEvent);
@@ -41,7 +40,6 @@ export const userRouter = createTRPCRouter({
return toUserProfile(user);
}),
// Update email
updateEmail: publicProcedure
.input(z.object({ email: z.string().email() }))
.mutation(async ({ input, ctx }) => {
@@ -62,7 +60,6 @@ export const userRouter = createTRPCRouter({
args: [email, 0, userId]
});
// Fetch updated user
const res = await conn.execute({
sql: "SELECT * FROM User WHERE id = ?",
args: [userId]
@@ -70,7 +67,6 @@ export const userRouter = createTRPCRouter({
const user = res.rows[0] as unknown as User;
// Set email cookie for verification flow
setCookie(ctx.event.nativeEvent, "emailToken", email, {
path: "/"
});
@@ -78,7 +74,6 @@ export const userRouter = createTRPCRouter({
return toUserProfile(user);
}),
// Update display name
updateDisplayName: publicProcedure
.input(z.object({ displayName: z.string().min(1).max(50) }))
.mutation(async ({ input, ctx }) => {
@@ -99,7 +94,6 @@ export const userRouter = createTRPCRouter({
args: [displayName, userId]
});
// Fetch updated user
const res = await conn.execute({
sql: "SELECT * FROM User WHERE id = ?",
args: [userId]
@@ -109,7 +103,6 @@ export const userRouter = createTRPCRouter({
return toUserProfile(user);
}),
// Update profile image
updateProfileImage: publicProcedure
.input(z.object({ imageUrl: z.string() }))
.mutation(async ({ input, ctx }) => {
@@ -130,7 +123,6 @@ export const userRouter = createTRPCRouter({
args: [imageUrl, userId]
});
// Fetch updated user
const res = await conn.execute({
sql: "SELECT * FROM User WHERE id = ?",
args: [userId]
@@ -140,7 +132,6 @@ export const userRouter = createTRPCRouter({
return toUserProfile(user);
}),
// Change password (requires old password)
changePassword: publicProcedure
.input(
z.object({
@@ -202,14 +193,12 @@ export const userRouter = createTRPCRouter({
});
}
// Update password
const newPasswordHash = await hashPassword(newPassword);
await conn.execute({
sql: "UPDATE User SET password_hash = ? WHERE id = ?",
args: [newPasswordHash, userId]
});
// Clear session cookies (force re-login)
setCookie(ctx.event.nativeEvent, "emailToken", "", {
maxAge: 0,
path: "/"
@@ -222,7 +211,6 @@ export const userRouter = createTRPCRouter({
return { success: true, message: "success" };
}),
// Set password (for OAuth users who don't have password)
setPassword: publicProcedure
.input(
z.object({
@@ -271,14 +259,12 @@ export const userRouter = createTRPCRouter({
});
}
// Set password
const passwordHash = await hashPassword(newPassword);
await conn.execute({
sql: "UPDATE User SET password_hash = ? WHERE id = ?",
args: [passwordHash, userId]
});
// Clear session cookies (force re-login)
setCookie(ctx.event.nativeEvent, "emailToken", "", {
maxAge: 0,
path: "/"
@@ -291,7 +277,6 @@ export const userRouter = createTRPCRouter({
return { success: true, message: "success" };
}),
// Delete account (anonymize data)
deleteAccount: publicProcedure
.input(z.object({ password: z.string() }))
.mutation(async ({ input, ctx }) => {
@@ -337,7 +322,6 @@ export const userRouter = createTRPCRouter({
});
}
// Anonymize user data (don't hard delete)
await conn.execute({
sql: `UPDATE User SET
email = ?,
@@ -350,7 +334,6 @@ export const userRouter = createTRPCRouter({
args: [null, 0, null, "user deleted", null, null, userId]
});
// Clear session cookies
setCookie(ctx.event.nativeEvent, "emailToken", "", {
maxAge: 0,
path: "/"

View File

@@ -50,7 +50,6 @@ export const t = initTRPC.context<Context>().create();
export const createTRPCRouter = t.router;
export const publicProcedure = t.procedure;
// Middleware to enforce authentication
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.userId || ctx.privilegeLevel === "anonymous") {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Not authenticated" });
@@ -63,7 +62,6 @@ const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
});
});
// Middleware to enforce admin access
const enforceUserIsAdmin = t.middleware(({ ctx, next }) => {
if (ctx.privilegeLevel !== "admin") {
throw new TRPCError({