From 583170efd15d2b4031de44462e7b2bcb18d72f39 Mon Sep 17 00:00:00 2001 From: Carlos Date: Fri, 10 Jul 2026 21:56:45 +0200 Subject: [PATCH] fix: move prisma generate to builder stage, add migration and entrypoint, replace custom login with NextAuth credentials provider --- Dockerfile | 6 +- entrypoint.sh | 6 ++ package.json | 3 +- pages/api/auth/signin.js | 54 ---------------- pages/api/auth/signup.js | 53 ---------------- pages/signin.jsx | 63 +++++++++---------- .../20240926000000_init/metadata.json | 1 + .../20240926000000_init/migration.sql | 39 ++++++++++++ 8 files changed, 80 insertions(+), 145 deletions(-) create mode 100755 entrypoint.sh delete mode 100644 pages/api/auth/signin.js delete mode 100644 pages/api/auth/signup.js create mode 100644 prisma/migrations/20240926000000_init/metadata.json create mode 100644 prisma/migrations/20240926000000_init/migration.sql diff --git a/Dockerfile b/Dockerfile index da75319..d96980a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,8 @@ RUN npm install --frozen-lockfile FROM base AS builder WORKDIR /app ENV DATABASE_URL="postgresql://user:***@localhost:5432/1000apps" +# Install openssl for Prisma binary target detection +RUN apk add --no-cache openssl COPY --from=deps /app/node_modules ./node_modules COPY . . ENV NEXT_TELEMETRY_DISABLED=1 @@ -40,6 +42,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/pages ./pages COPY --from=builder --chown=nextjs:nodejs /app/lib ./lib COPY --from=builder --chown=nextjs:nodejs /app/components ./components COPY --from=builder --chown=nextjs:nodejs /app/styles ./styles +COPY entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/entrypoint.sh EXPOSE 3000 -CMD ["npm", "run", "start"] \ No newline at end of file +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..4485f54 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e +echo "Running Prisma migrations..." +npx prisma migrate deploy +echo "Starting Next.js..." +npm run start \ No newline at end of file diff --git a/package.json b/package.json index 019790e..3426061 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,7 @@ "next-auth": "^4.24.0", "@next-auth/prisma-adapter": "^1.0.7", "@prisma/client": "^5.0.0", - "bcryptjs": "^2.4.3", - "jsonwebtoken": "^9.0.0" + "bcryptjs": "^2.4.3" }, "devDependencies": { "prisma": "^5.0.0", diff --git a/pages/api/auth/signin.js b/pages/api/auth/signin.js deleted file mode 100644 index 3088618..0000000 --- a/pages/api/auth/signin.js +++ /dev/null @@ -1,54 +0,0 @@ -import { PrismaClient } from "@prisma/client" -import bcrypt from "bcryptjs" - -const prisma = new PrismaClient() - -export default async function handler(req, res) { - if (req.method !== "POST") { - return res.status(405).json({ error: "Método não permitido" }) - } - - const { username, password } = req.body - - if (!username || !password) { - return res.status(400).json({ error: "Username e senha são obrigatórios" }) - } - - try { - const user = await prisma.user.findUnique({ - where: { username } - }) - - if (!user) { - return res.status(401).json({ error: "Usuário não encontrado" }) - } - - if (!user.password) { - return res.status(401).json({ error: "Senha não configurada" }) - } - - const isValid = await bcrypt.compare(password, user.password) - - if (!isValid) { - return res.status(401).json({ error: "Senha incorreta" }) - } - - // Create a JWT token manually for the session - const token = require("jsonwebtoken").sign( - { sub: user.id, email: user.email, name: user.name || user.username }, - process.env.NEXTAUTH_SECRET || "test-secret-2x4=", - { expiresIn: "30d" } - ) - - return res.status(200).json({ - ok: true, - user: { id: user.id, email: user.email, name: user.name || user.username }, - token - }) - } catch (error) { - console.error("Signin error:", error) - return res.status(500).json({ error: "Erro interno do servidor" }) - } finally { - await prisma.$disconnect() - } -} \ No newline at end of file diff --git a/pages/api/auth/signup.js b/pages/api/auth/signup.js deleted file mode 100644 index c24eafb..0000000 --- a/pages/api/auth/signup.js +++ /dev/null @@ -1,53 +0,0 @@ -import { PrismaClient } from "@prisma/client" -import bcrypt from "bcryptjs" - -const prisma = new PrismaClient() - -export default async function handler(req, res) { - if (req.method !== "POST") { - return res.status(405).json({ error: "Método não permitido" }) - } - - const { username, password } = req.body - - if (!username || !password) { - return res.status(400).json({ error: "Username e senha são obrigatórios" }) - } - - if (password.length < 6) { - return res.status(400).json({ error: "Senha deve ter pelo menos 6 caracteres" }) - } - - try { - // Check if username exists - const existingUser = await prisma.user.findUnique({ - where: { username } - }) - - if (existingUser) { - return res.status(400).json({ error: "Nome de usuário já existe" }) - } - - // Hash password - const hashedPassword = await bcrypt.hash(password, 12) - - // Create user - const user = await prisma.user.create({ - data: { - username, - password: hashedPassword, - email: `${username}@1000apps.local` - } - }) - - return res.status(201).json({ - message: "Usuário criado com sucesso", - user: { id: user.id, username: user.username } - }) - } catch (error) { - console.error("Signup error:", error) - return res.status(500).json({ error: "Erro interno do servidor" }) - } finally { - await prisma.$disconnect() - } -} \ No newline at end of file diff --git a/pages/signin.jsx b/pages/signin.jsx index d609d77..6e60df6 100644 --- a/pages/signin.jsx +++ b/pages/signin.jsx @@ -1,36 +1,32 @@ -import { useState } from "react" -import { useRouter } from "next/router" +import { useState } from 'react' +import { useRouter } from 'next/router' +import { signIn } from 'next-auth/react' export default function SignIn() { - const [username, setUsername] = useState("") - const [password, setPassword] = useState("") - const [error, setError] = useState("") + const [username, setUsername] = useState('') + const [password, setPassword] = useState('') + const [error, setError] = useState('') const [loading, setLoading] = useState(false) const router = useRouter() const handleSubmit = async (e) => { e.preventDefault() - setError("") + setError('') setLoading(true) - try { - const res = await fetch("/api/auth/signin", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ username, password }) + const result = await signIn('credentials', { + redirect: false, + callbackUrl: '/dashboard', + username, + password, }) - - const data = await res.json() - - if (res.ok && data.ok) { - // Set session cookie - document.cookie = `next-auth.session-token=${data.token}; path=/; SameSite=Lax` - router.push("/dashboard") - } else { - setError(data.error || "Erro ao entrar") + if (result.error) { + setError(result.error) + } else if (result.status === 'ok') { + router.push('/dashboard') } } catch (err) { - setError("Erro de conexão") + setError('Authentication error') } finally { setLoading(false) } @@ -40,45 +36,42 @@ export default function SignIn() {

Entrar - 1000Apps

- - {error && ( -
- {error} -
- )} -
setUsername(e.target.value)} - className="w-full p-2 border rounded" required /> setPassword(e.target.value)} - className="w-full p-2 border rounded" required /> -
-

- Não tem conta?{" "} + Não tem conta?{' '} Cadastrar

+ {error && ( +
+ {error} +
+ )}
) diff --git a/prisma/migrations/20240926000000_init/metadata.json b/prisma/migrations/20240926000000_init/metadata.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/prisma/migrations/20240926000000_init/metadata.json @@ -0,0 +1 @@ +{} diff --git a/prisma/migrations/20240926000000_init/migration.sql b/prisma/migrations/20240926000000_init/migration.sql new file mode 100644 index 0000000..291421c --- /dev/null +++ b/prisma/migrations/20240926000000_init/migration.sql @@ -0,0 +1,39 @@ +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "email" TEXT NOT NULL, + "username" TEXT, + "name" TEXT, + "image" TEXT, + "password" TEXT, + "role" TEXT NOT NULL DEFAULT 'user', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "App" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "version" TEXT NOT NULL DEFAULT '1.0.0', + "entryUrl" TEXT NOT NULL, + "ownerId" TEXT NOT NULL, + "isPublic" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "App_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_username_key" ON "User"("username"); + +-- AddForeignKey +ALTER TABLE "App" ADD CONSTRAINT "App_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; +