initial commit
@@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
.git
|
||||
tmp
|
||||
stderr.log
|
||||
*.sql
|
||||
.DS_Store
|
||||
.gitignore
|
||||
.htaccess
|
||||
.well-known
|
||||
@@ -0,0 +1,7 @@
|
||||
node_modules/
|
||||
.env
|
||||
stderr.log
|
||||
tmp/
|
||||
public/images/
|
||||
humicpro_intellisight.sql
|
||||
.htaccess
|
||||
@@ -0,0 +1,19 @@
|
||||
# DO NOT REMOVE. CLOUDLINUX PASSENGER CONFIGURATION BEGIN
|
||||
PassengerAppRoot "/home/humicpro/public_html/intellisight-api.humicprototyping.com"
|
||||
PassengerBaseURI "/"
|
||||
PassengerNodejs "/home/humicpro/nodevenv/public_html/intellisight-api.humicprototyping.com/20/bin/node"
|
||||
PassengerAppType node
|
||||
PassengerStartupFile index.js
|
||||
# DO NOT REMOVE. CLOUDLINUX PASSENGER CONFIGURATION END
|
||||
# DO NOT REMOVE OR MODIFY. CLOUDLINUX ENV VARS CONFIGURATION BEGIN
|
||||
<IfModule Litespeed>
|
||||
SetEnv DB_HOST localhost
|
||||
SetEnv DB_NAME humicpro_intellisight
|
||||
SetEnv DB_USER humicpro_intellisight
|
||||
SetEnv ACCESS_TOKEN_SECRET F22dm6BOm2p23XlmHbmS9Fc843U5V8s9mmsAFC83xQOQbKLcoPYF1sMDaM80ztaR8
|
||||
SetEnv REFRESH_TOKEN_SECRET Lm6t2mHQ1sYHTSKjx8lToTSvzoHpRQ3EcFxDAouWR387UzYV4BsT0C38QihptOhYi
|
||||
SetEnv ACCESS_TOKEN_EXP 60m
|
||||
SetEnv REFRESH_TOKEN_EXP 1d
|
||||
SetEnv DB_PASS humicpro_intellisight
|
||||
</IfModule>
|
||||
# DO NOT REMOVE OR MODIFY. CLOUDLINUX ENV VARS CONFIGURATION END
|
||||
@@ -0,0 +1,15 @@
|
||||
PORT=4000
|
||||
NODE_ENV=production
|
||||
|
||||
DB_HOST=db
|
||||
DB_NAME=intellisight
|
||||
DB_USER=intellisight
|
||||
DB_PASS=change-me
|
||||
DB_ROOT_PASS=change-me
|
||||
|
||||
ACCESS_TOKEN_SECRET=generate-a-random-secret
|
||||
REFRESH_TOKEN_SECRET=generate-a-random-secret
|
||||
ACCESS_TOKEN_EXP=60m
|
||||
REFRESH_TOKEN_EXP=1d
|
||||
|
||||
CORS_ORIGIN=https://your-frontend-domain.com
|
||||
@@ -0,0 +1,29 @@
|
||||
FROM node:20-alpine AS deps
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --omit=dev
|
||||
|
||||
FROM node:20-alpine AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 express
|
||||
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
RUN mkdir -p public/images && chown -R express:nodejs /app
|
||||
|
||||
COPY docker/seed/ /app/seed/
|
||||
COPY docker/entrypoint.sh /app/entrypoint.sh
|
||||
RUN chmod +x /app/entrypoint.sh
|
||||
|
||||
USER express
|
||||
EXPOSE 4000
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:4000/auth/me || exit 1
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
CMD ["node", "index.js"]
|
||||
@@ -0,0 +1,2 @@
|
||||
FROM mysql:8.0
|
||||
COPY init.sql /docker-entrypoint-initdb.d/
|
||||
@@ -0,0 +1,37 @@
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile
|
||||
container_name: intellisight-api
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
- uploads:/app/public/images
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
db:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.db
|
||||
container_name: intellisight-db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
|
||||
MYSQL_DATABASE: ${DB_NAME}
|
||||
MYSQL_USER: ${DB_USER}
|
||||
MYSQL_PASSWORD: ${DB_PASS}
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
uploads:
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
SEED_MARKER="/app/public/images/.seeded"
|
||||
SEED_SRC="/app/seed/images"
|
||||
DEST="/app/public/images"
|
||||
|
||||
if [ ! -f "$SEED_MARKER" ]; then
|
||||
echo "First run — seeding existing uploads..."
|
||||
if [ -d "$SEED_SRC" ]; then
|
||||
cp -r "$SEED_SRC"/* "$DEST/"
|
||||
echo "Seed complete."
|
||||
else
|
||||
echo "No seed directory found — skipping."
|
||||
fi
|
||||
touch "$SEED_MARKER"
|
||||
else
|
||||
echo "Uploads already seeded — skipping."
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 304 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 761 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 319 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 324 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 589 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 269 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 582 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 243 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 876 KiB |
|
After Width: | Height: | Size: 907 KiB |
|
After Width: | Height: | Size: 1000 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 325 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,49 @@
|
||||
require('dotenv').config();
|
||||
const PORT = process.env.PORT || 4000;
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const cors = require('cors');
|
||||
const db = require('./src/configs/database.js');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const verifyJWT = require('./src/middleware/verifyJWT.js');
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin: process.env.CORS_ORIGIN,
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization'],
|
||||
})
|
||||
);
|
||||
|
||||
app.options('*', cors({
|
||||
origin: process.env.CORS_ORIGIN,
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization'],
|
||||
}));
|
||||
|
||||
app.use(express.json());
|
||||
app.use(cookieParser());
|
||||
app.use(express.static('public'));
|
||||
|
||||
// Sync table pada database
|
||||
(async () => {
|
||||
try {
|
||||
await db.sync();
|
||||
console.log('Database synced');
|
||||
} catch (err) {
|
||||
console.error('DB Sync Error:', err);
|
||||
}
|
||||
})();
|
||||
|
||||
app.use('/auth', require('./src/routes/AuthRoutes.js'));
|
||||
app.use('/user', verifyJWT, require('./src/routes/UserRoutes.js'));
|
||||
app.use('/exam', verifyJWT, require('./src/routes/ExaminationRoutes.js'));
|
||||
app.use((req, res) => {
|
||||
res.status(404).json({ message: 'Endpoint tidak ditemukan' });
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
});
|
||||