finish commit for dashboard and table for view
This commit is contained in:
parent
4279357779
commit
e5fb968629
|
|
@ -37,7 +37,7 @@ jobs:
|
||||||
host: ${{ secrets.VPS_HOST }}
|
host: ${{ secrets.VPS_HOST }}
|
||||||
username: ${{ secrets.VPS_USER }}
|
username: ${{ secrets.VPS_USER }}
|
||||||
key: ${{ secrets.VPS_SSH_KEY }}
|
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 }}"
|
target: "${{ env.TARGET_DIR }}"
|
||||||
|
|
||||||
- name: Restart PM2
|
- name: Restart PM2
|
||||||
|
|
@ -52,9 +52,9 @@ jobs:
|
||||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||||
npm install -g pnpm@11 2>&1
|
npm install -g pnpm@11 2>&1
|
||||||
cd ${{ env.TARGET_DIR }}
|
cd ${{ env.TARGET_DIR }}
|
||||||
pnpm install --prod 2>&1
|
|
||||||
cat > .env <<'ENVEOF'
|
cat > .env <<'ENVEOF'
|
||||||
DATABASE_URL="${{ secrets.DATABASE_URL }}"
|
DATABASE_URL="${{ secrets.DATABASE_URL }}"
|
||||||
|
DIRECT_URL="${{ secrets.DIRECT_URL }}"
|
||||||
GOOGLE_SERVICE_ACCOUNT_EMAIL="${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }}"
|
GOOGLE_SERVICE_ACCOUNT_EMAIL="${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }}"
|
||||||
GOOGLE_PRIVATE_KEY="${{ secrets.GOOGLE_PRIVATE_KEY }}"
|
GOOGLE_PRIVATE_KEY="${{ secrets.GOOGLE_PRIVATE_KEY }}"
|
||||||
GOOGLE_SHEET_ID="${{ secrets.GOOGLE_SHEET_ID }}"
|
GOOGLE_SHEET_ID="${{ secrets.GOOGLE_SHEET_ID }}"
|
||||||
|
|
@ -65,5 +65,8 @@ jobs:
|
||||||
CLOUDFLARE_ACCOUNT_ID="${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"
|
CLOUDFLARE_ACCOUNT_ID="${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"
|
||||||
ADMIN_API_KEY="${{ secrets.ADMIN_API_KEY }}"
|
ADMIN_API_KEY="${{ secrets.ADMIN_API_KEY }}"
|
||||||
ENVEOF
|
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 reload ecosystem.config.cjs --only ${{ env.APP_NAME }} --update-env || \
|
||||||
pm2 start ecosystem.config.cjs --only ${{ env.APP_NAME }} --update-env
|
pm2 start ecosystem.config.cjs --only ${{ env.APP_NAME }} --update-env
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"daisyui": "^5.5.18"
|
"daisyui": "^5.5.18",
|
||||||
|
"dotenv": "^17.4.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,9 @@ importers:
|
||||||
daisyui:
|
daisyui:
|
||||||
specifier: ^5.5.18
|
specifier: ^5.5.18
|
||||||
version: 5.5.20
|
version: 5.5.20
|
||||||
|
dotenv:
|
||||||
|
specifier: ^17.4.2
|
||||||
|
version: 17.4.2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,23 @@
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import { prisma } from "../../lib/prisma";
|
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 prerender = false;
|
||||||
|
|
||||||
export const POST: APIRoute = async ({ request }) => {
|
export const POST: APIRoute = async ({ request }) => {
|
||||||
try {
|
try {
|
||||||
|
if (!isSameOrigin(request)) {
|
||||||
|
return Response.json(
|
||||||
|
{ success: false, message: "Origen no válido" },
|
||||||
|
{ status: 403 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
const identifier = String(body?.username || body?.email || "")
|
const identifier = String(body?.username || body?.email || "")
|
||||||
.trim()
|
.trim()
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import { clearSessionCookie, revokeSession } from "../../lib/auth";
|
import { clearSessionCookie, isSameOrigin, revokeSession } from "../../lib/auth";
|
||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
export const POST: APIRoute = async ({ request }) => {
|
export const POST: APIRoute = async ({ request }) => {
|
||||||
|
if (!isSameOrigin(request)) {
|
||||||
|
return new Response(null, { status: 403 });
|
||||||
|
}
|
||||||
|
|
||||||
await revokeSession(request);
|
await revokeSession(request);
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ function readSessionToken(request: Request): string | null {
|
||||||
|
|
||||||
export async function createSession(adminId: string): Promise<string> {
|
export async function createSession(adminId: string): Promise<string> {
|
||||||
const token = randomBytes(32).toString("base64url");
|
const token = randomBytes(32).toString("base64url");
|
||||||
|
await prisma.session.deleteMany({
|
||||||
|
where: { expires_at: { lte: new Date() } },
|
||||||
|
});
|
||||||
await prisma.session.create({
|
await prisma.session.create({
|
||||||
data: {
|
data: {
|
||||||
token_hash: sha256(token),
|
token_hash: sha256(token),
|
||||||
|
|
@ -83,25 +86,30 @@ export async function getSession(request: Request): Promise<AuthSession | null>
|
||||||
const token = readSessionToken(request);
|
const token = readSessionToken(request);
|
||||||
if (!token) return null;
|
if (!token) return null;
|
||||||
|
|
||||||
const session = await prisma.session.findUnique({
|
try {
|
||||||
where: { token_hash: sha256(token) },
|
const session = await prisma.session.findUnique({
|
||||||
include: { admin: true },
|
where: { token_hash: sha256(token) },
|
||||||
});
|
include: { admin: true },
|
||||||
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!session ||
|
!session ||
|
||||||
session.expires_at.getTime() <= Date.now() ||
|
session.expires_at.getTime() <= Date.now() ||
|
||||||
!session.admin.activo
|
!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 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> {
|
export async function revokeSession(request: Request): Promise<void> {
|
||||||
|
|
@ -127,3 +135,17 @@ export async function isApiAuthorized(request: Request): Promise<boolean> {
|
||||||
|
|
||||||
return timingSafeEqualStr(key, apiKey);
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue