finish commit for dashboard and table for view

This commit is contained in:
Esteban Paz 2026-08-16 14:22:53 -05:00
parent 4279357779
commit e5fb968629
6 changed files with 66 additions and 21 deletions

View File

@ -37,7 +37,7 @@ jobs:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
source: "dist/*,package.json,pnpm-lock.yaml,pnpm-workspace.yaml,ecosystem.config.cjs"
source: "dist/*,package.json,pnpm-lock.yaml,pnpm-workspace.yaml,ecosystem.config.cjs,prisma/schema.prisma,prisma/migrations,prisma.config.ts"
target: "${{ env.TARGET_DIR }}"
- name: Restart PM2
@ -52,9 +52,9 @@ jobs:
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
npm install -g pnpm@11 2>&1
cd ${{ env.TARGET_DIR }}
pnpm install --prod 2>&1
cat > .env <<'ENVEOF'
DATABASE_URL="${{ secrets.DATABASE_URL }}"
DIRECT_URL="${{ secrets.DIRECT_URL }}"
GOOGLE_SERVICE_ACCOUNT_EMAIL="${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }}"
GOOGLE_PRIVATE_KEY="${{ secrets.GOOGLE_PRIVATE_KEY }}"
GOOGLE_SHEET_ID="${{ secrets.GOOGLE_SHEET_ID }}"
@ -65,5 +65,8 @@ jobs:
CLOUDFLARE_ACCOUNT_ID="${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"
ADMIN_API_KEY="${{ secrets.ADMIN_API_KEY }}"
ENVEOF
pnpm install --prod 2>&1
pnpm exec prisma generate 2>&1
pnpm exec prisma migrate deploy 2>&1
pm2 reload ecosystem.config.cjs --only ${{ env.APP_NAME }} --update-env || \
pm2 start ecosystem.config.cjs --only ${{ env.APP_NAME }} --update-env

View File

@ -45,6 +45,7 @@
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.19",
"daisyui": "^5.5.18"
"daisyui": "^5.5.18",
"dotenv": "^17.4.2"
}
}

View File

@ -102,6 +102,9 @@ importers:
daisyui:
specifier: ^5.5.18
version: 5.5.20
dotenv:
specifier: ^17.4.2
version: 17.4.2
packages:

View File

@ -1,11 +1,23 @@
import type { APIRoute } from "astro";
import { prisma } from "../../lib/prisma";
import { createSession, sessionCookieFor, verifyPassword } from "../../lib/auth";
import {
createSession,
isSameOrigin,
sessionCookieFor,
verifyPassword,
} from "../../lib/auth";
export const prerender = false;
export const POST: APIRoute = async ({ request }) => {
try {
if (!isSameOrigin(request)) {
return Response.json(
{ success: false, message: "Origen no válido" },
{ status: 403 }
);
}
const body = await request.json();
const identifier = String(body?.username || body?.email || "")
.trim()

View File

@ -1,9 +1,13 @@
import type { APIRoute } from "astro";
import { clearSessionCookie, revokeSession } from "../../lib/auth";
import { clearSessionCookie, isSameOrigin, revokeSession } from "../../lib/auth";
export const prerender = false;
export const POST: APIRoute = async ({ request }) => {
if (!isSameOrigin(request)) {
return new Response(null, { status: 403 });
}
await revokeSession(request);
return new Response(null, {

View File

@ -69,6 +69,9 @@ function readSessionToken(request: Request): string | null {
export async function createSession(adminId: string): Promise<string> {
const token = randomBytes(32).toString("base64url");
await prisma.session.deleteMany({
where: { expires_at: { lte: new Date() } },
});
await prisma.session.create({
data: {
token_hash: sha256(token),
@ -83,25 +86,30 @@ export async function getSession(request: Request): Promise<AuthSession | null>
const token = readSessionToken(request);
if (!token) return null;
const session = await prisma.session.findUnique({
where: { token_hash: sha256(token) },
include: { admin: true },
});
try {
const session = await prisma.session.findUnique({
where: { token_hash: sha256(token) },
include: { admin: true },
});
if (
!session ||
session.expires_at.getTime() <= Date.now() ||
!session.admin.activo
) {
if (
!session ||
session.expires_at.getTime() <= Date.now() ||
!session.admin.activo
) {
return null;
}
return {
adminId: session.admin.id,
email: session.admin.email,
nombre: session.admin.nombre,
rol: session.admin.rol,
};
} catch (error) {
console.error("Error al leer la sesión:", error);
return null;
}
return {
adminId: session.admin.id,
email: session.admin.email,
nombre: session.admin.nombre,
rol: session.admin.rol,
};
}
export async function revokeSession(request: Request): Promise<void> {
@ -127,3 +135,17 @@ export async function isApiAuthorized(request: Request): Promise<boolean> {
return timingSafeEqualStr(key, apiKey);
}
export function isSameOrigin(request: Request): boolean {
const origin = request.headers.get("origin");
const referer = request.headers.get("referer");
const host = request.headers.get("host");
if (!host) return true;
try {
if (origin) return new URL(origin).host === host;
if (referer) return new URL(referer).host === host;
} catch {
return false;
}
return true;
}