Added Encryptions to All stored token and passwords

This commit is contained in:
Arunavo Ray
2025-07-16 16:02:34 +05:30
parent 7cc4aa87f2
commit beedbaf9a4
14 changed files with 475 additions and 24 deletions

View File

@@ -5,6 +5,7 @@ import { eq } from "drizzle-orm";
import { calculateCleanupInterval } from "@/lib/cleanup-service";
import { createSecureErrorResponse } from "@/lib/utils";
import { mapUiToDbConfig, mapDbToUiConfig } from "@/lib/utils/config-mapper";
import { encrypt, decrypt, migrateToken } from "@/lib/utils/encryption";
export const POST: APIRoute = async ({ request }) => {
try {
@@ -55,17 +56,27 @@ export const POST: APIRoute = async ({ request }) => {
? JSON.parse(existingConfig.giteaConfig)
: existingConfig.giteaConfig;
// Decrypt existing tokens before preserving
if (!mappedGithubConfig.token && existingGithub.token) {
mappedGithubConfig.token = existingGithub.token;
mappedGithubConfig.token = decrypt(existingGithub.token);
}
if (!mappedGiteaConfig.token && existingGitea.token) {
mappedGiteaConfig.token = existingGitea.token;
mappedGiteaConfig.token = decrypt(existingGitea.token);
}
} catch (tokenError) {
console.error("Failed to preserve tokens:", tokenError);
}
}
// Encrypt tokens before saving
if (mappedGithubConfig.token) {
mappedGithubConfig.token = encrypt(mappedGithubConfig.token);
}
if (mappedGiteaConfig.token) {
mappedGiteaConfig.token = encrypt(mappedGiteaConfig.token);
}
// Process schedule config - set/update nextRun if enabled, clear if disabled
const processedScheduleConfig = { ...scheduleConfig };
@@ -279,15 +290,54 @@ export const GET: APIRoute = async ({ request }) => {
// Map database structure to UI structure
const dbConfig = config[0];
const uiConfig = mapDbToUiConfig(dbConfig);
return new Response(JSON.stringify({
...dbConfig,
...uiConfig,
}), {
status: 200,
headers: { "Content-Type": "application/json" },
});
// Decrypt tokens before sending to UI
try {
const githubConfig = typeof dbConfig.githubConfig === "string"
? JSON.parse(dbConfig.githubConfig)
: dbConfig.githubConfig;
const giteaConfig = typeof dbConfig.giteaConfig === "string"
? JSON.parse(dbConfig.giteaConfig)
: dbConfig.giteaConfig;
// Decrypt tokens
if (githubConfig.token) {
githubConfig.token = decrypt(githubConfig.token);
}
if (giteaConfig.token) {
giteaConfig.token = decrypt(giteaConfig.token);
}
// Create modified config with decrypted tokens
const decryptedConfig = {
...dbConfig,
githubConfig,
giteaConfig
};
const uiConfig = mapDbToUiConfig(decryptedConfig);
return new Response(JSON.stringify({
...dbConfig,
...uiConfig,
}), {
status: 200,
headers: { "Content-Type": "application/json" },
});
} catch (error) {
console.error("Failed to decrypt tokens:", error);
// Return config without decrypting tokens if there's an error
const uiConfig = mapDbToUiConfig(dbConfig);
return new Response(JSON.stringify({
...dbConfig,
...uiConfig,
}), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
} catch (error) {
return createSecureErrorResponse(error, "config fetch", 500);
}

View File

@@ -9,6 +9,7 @@ import { type MembershipRole } from "@/types/organizations";
import { createSecureErrorResponse } from "@/lib/utils";
import { processWithResilience } from "@/lib/utils/concurrency";
import { v4 as uuidv4 } from "uuid";
import { getDecryptedGitHubToken } from "@/lib/utils/config-encryption";
export const POST: APIRoute = async ({ request }) => {
try {
@@ -71,7 +72,8 @@ export const POST: APIRoute = async ({ request }) => {
}
// Create a single Octokit instance to be reused
const octokit = createGitHubClient(config.githubConfig.token);
const decryptedToken = getDecryptedGitHubToken(config);
const octokit = createGitHubClient(decryptedToken);
// Define the concurrency limit - adjust based on API rate limits
// Using a lower concurrency for organizations since each org might contain many repos

View File

@@ -9,6 +9,7 @@ import {
getGiteaRepoOwnerAsync,
} from "@/lib/gitea";
import { createGitHubClient } from "@/lib/github";
import { getDecryptedGitHubToken } from "@/lib/utils/config-encryption";
import { processWithResilience } from "@/lib/utils/concurrency";
import { createSecureErrorResponse } from "@/lib/utils";
@@ -73,7 +74,8 @@ export const POST: APIRoute = async ({ request }) => {
}
// Create a single Octokit instance to be reused
const octokit = createGitHubClient(config.githubConfig.token);
const decryptedToken = getDecryptedGitHubToken(config);
const octokit = createGitHubClient(decryptedToken);
// Define the concurrency limit - adjust based on API rate limits
const CONCURRENCY_LIMIT = 3;

View File

@@ -13,6 +13,7 @@ import type { RetryRepoRequest, RetryRepoResponse } from "@/types/retry";
import { processWithRetry } from "@/lib/utils/concurrency";
import { createMirrorJob } from "@/lib/helpers";
import { createSecureErrorResponse } from "@/lib/utils";
import { getDecryptedGitHubToken } from "@/lib/utils/config-encryption";
export const POST: APIRoute = async ({ request }) => {
try {
@@ -71,8 +72,11 @@ export const POST: APIRoute = async ({ request }) => {
// Start background retry with parallel processing
setTimeout(async () => {
// Create a single Octokit instance to be reused if needed
const octokit = config.githubConfig.token
? createGitHubClient(config.githubConfig.token)
const decryptedToken = config.githubConfig.token
? getDecryptedGitHubToken(config)
: null;
const octokit = decryptedToken
? createGitHubClient(decryptedToken)
: null;
// Define the concurrency limit - adjust based on API rate limits

View File

@@ -10,6 +10,7 @@ import {
getGithubStarredRepositories,
} from "@/lib/github";
import { jsonResponse, createSecureErrorResponse } from "@/lib/utils";
import { getDecryptedGitHubToken } from "@/lib/utils/config-encryption";
export const POST: APIRoute = async ({ request }) => {
const url = new URL(request.url);
@@ -33,16 +34,16 @@ export const POST: APIRoute = async ({ request }) => {
});
}
const token = config.githubConfig?.token;
if (!token) {
if (!config.githubConfig?.token) {
return jsonResponse({
data: { error: "GitHub token is missing in config" },
status: 400,
});
}
const octokit = createGitHubClient(token);
// Decrypt the GitHub token before using it
const decryptedToken = getDecryptedGitHubToken(config);
const octokit = createGitHubClient(decryptedToken);
// Fetch GitHub data in parallel
const [basicAndForkedRepos, starredRepos, gitOrgs] = await Promise.all([