feat:drone, cookies login dummy
This commit is contained in:
parent
76f9af6b8d
commit
fdb8fdb4a7
|
|
@ -0,0 +1,42 @@
|
||||||
|
kind: pipeline
|
||||||
|
type: ssh
|
||||||
|
name: silancar-build-deploy
|
||||||
|
|
||||||
|
server:
|
||||||
|
host:
|
||||||
|
from_secret: ssh_host
|
||||||
|
user:
|
||||||
|
from_secret: ssh_user
|
||||||
|
ssh_key:
|
||||||
|
from_secret: ssh_key
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: prepare repo
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
commands:
|
||||||
|
- rm -rf /opt/build/silancar
|
||||||
|
- mkdir -p /opt/build
|
||||||
|
- cd /opt/build
|
||||||
|
- git clone http://38.47.180.165:3000/humas/silancar.git
|
||||||
|
|
||||||
|
- name: build image
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
commands:
|
||||||
|
- docker login 38.47.180.165:3000 -u administrator -p HarborDockerImageRep0
|
||||||
|
- cd /opt/build/silancar
|
||||||
|
- docker build -t 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH .
|
||||||
|
- docker push 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
commands:
|
||||||
|
- docker pull 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH
|
||||||
|
- docker stop web-silancar|| true
|
||||||
|
- docker rm web-silancar || true
|
||||||
|
- docker run -dt -p 4700:4000 --restart always --name web-silancar 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
FROM node:23.5.0-alpine
|
||||||
|
|
||||||
|
ENV PORT=4000
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
sqlite-dev
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copy dependency files
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install --legacy-peer-deps
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Init DB (aman karena pakai || true)
|
||||||
|
RUN mkdir -p ./lib/db
|
||||||
|
RUN node scripts/init-db.js || true
|
||||||
|
|
||||||
|
# Build Next.js
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
EXPOSE 4000
|
||||||
|
|
||||||
|
CMD ["npm", "run", "start"]
|
||||||
|
|
@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
|
import { setCookiesEncrypt } from "@/utils/globals"
|
||||||
|
|
||||||
type FormValues = {
|
type FormValues = {
|
||||||
nrp: string
|
nrp: string
|
||||||
|
|
@ -26,13 +27,16 @@ export default function SignInPage() {
|
||||||
})
|
})
|
||||||
|
|
||||||
const onSubmit = async (data: FormValues) => {
|
const onSubmit = async (data: FormValues) => {
|
||||||
console.log("DATA LOGIN:", data)
|
|
||||||
|
|
||||||
await new Promise((res) => setTimeout(res, 1000))
|
await new Promise((res) => setTimeout(res, 1000))
|
||||||
|
if(data.nrp=="12345678"&&data.password=="P@ssw0rd.1") {
|
||||||
|
setCookiesEncrypt("status", "Login", { expires: 1 });
|
||||||
router.push("/dashboard")
|
router.push("/dashboard")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
|
'use client'
|
||||||
import DashboardSideMenu from "@/components/layout/dashboard-side-menu"
|
import DashboardSideMenu from "@/components/layout/dashboard-side-menu"
|
||||||
import Footer from "@/components/layout/footer"
|
import Footer from "@/components/layout/footer"
|
||||||
import { PinIcon } from "lucide-react"
|
import { getCookiesDecrypt } from "@/utils/globals"
|
||||||
import Image from "next/image"
|
import Image from "next/image"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
import { useRouter } from "next/navigation"
|
||||||
|
import { useEffect } from "react"
|
||||||
|
|
||||||
const dummy = { name: "Andri2 Ferinata", plat: "B 14 QU" }
|
const dummy = { name: "Andri2 Ferinata", plat: "B 14 QU" }
|
||||||
|
|
||||||
|
|
@ -19,6 +22,15 @@ const menu = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
|
const login=getCookiesDecrypt("status")
|
||||||
|
const router=useRouter()
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(!login){
|
||||||
|
router.push("/auth/sign-in")
|
||||||
|
}
|
||||||
|
},[login,router])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-3 px-12 py-16">
|
<div className="grid grid-cols-3 px-12 py-16">
|
||||||
<div className="col-span-2 flex flex-col pr-8">
|
<div className="col-span-2 flex flex-col pr-8">
|
||||||
|
|
|
||||||
BIN
app/favicon.ico
BIN
app/favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 4.2 KiB |
|
|
@ -3,6 +3,15 @@ import { Geist_Mono, Inter, Roboto } from "next/font/google"
|
||||||
import "./globals.css"
|
import "./globals.css"
|
||||||
import { ThemeProvider } from "@/components/theme-provider"
|
import { ThemeProvider } from "@/components/theme-provider"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import type { Metadata } from "next"
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Silancar",
|
||||||
|
description: "Silancar Korlantas",
|
||||||
|
icons: {
|
||||||
|
icon: "/favicon.ico", // atau png
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" })
|
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" })
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -8,9 +8,13 @@
|
||||||
"name": "silancar",
|
"name": "silancar",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
|
"@types/js-cookie": "^3.0.6",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"js-cookie": "^3.0.5",
|
||||||
"lucide-react": "^0.577.0",
|
"lucide-react": "^0.577.0",
|
||||||
"next": "16.1.7",
|
"next": "16.1.7",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
|
|
@ -3545,12 +3549,22 @@
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/crypto-js": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/js-cookie": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
|
|
@ -4939,6 +4953,11 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crypto-js": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
||||||
|
},
|
||||||
"node_modules/cssesc": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
|
|
@ -7305,6 +7324,14 @@
|
||||||
"url": "https://github.com/sponsors/panva"
|
"url": "https://github.com/sponsors/panva"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/js-cookie": {
|
||||||
|
"version": "3.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
|
||||||
|
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,13 @@
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
|
"@types/js-cookie": "^3.0.6",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"js-cookie": "^3.0.5",
|
||||||
"lucide-react": "^0.577.0",
|
"lucide-react": "^0.577.0",
|
||||||
"next": "16.1.7",
|
"next": "16.1.7",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -0,0 +1,37 @@
|
||||||
|
import Cookies from "js-cookie"
|
||||||
|
import CryptoJS from "crypto-js"
|
||||||
|
|
||||||
|
export function setCookiesEncrypt<T>(
|
||||||
|
param: string,
|
||||||
|
data: T,
|
||||||
|
options?: Cookies.CookieAttributes
|
||||||
|
) {
|
||||||
|
const cookiesEncrypt = CryptoJS.AES.encrypt(
|
||||||
|
JSON.stringify(data),
|
||||||
|
`${param}_EncryptKey@silancar`
|
||||||
|
).toString()
|
||||||
|
|
||||||
|
Cookies.set(param, cookiesEncrypt, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCookiesDecrypt<T>(param: string): T | null {
|
||||||
|
const cookiesEncrypt = Cookies.get(param)
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (cookiesEncrypt) {
|
||||||
|
const bytes = CryptoJS.AES.decrypt(
|
||||||
|
cookiesEncrypt,
|
||||||
|
`${param}_EncryptKey@silancar`
|
||||||
|
)
|
||||||
|
|
||||||
|
const decrypted = bytes.toString(CryptoJS.enc.Utf8)
|
||||||
|
|
||||||
|
return JSON.parse(decrypted) as T
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Decrypt error:", e)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue