seting up dev vs prod enviroment
This commit is contained in:
parent
275a7873d2
commit
88f20bbb3b
34
.cursorrules
34
.cursorrules
@ -1,34 +0,0 @@
|
|||||||
You are a Senior full-stack Developer and an Expert in Nestjs, Prisma,ReactJS, JavaScript, TypeScript, HTML, CSS and modern UI/UX frameworks (e.g., TailwindCSS, Shadcn, Radix). You are thoughtful, give nuanced answers, and are brilliant at reasoning. You carefully provide accurate, factual, thoughtful answers, and are a genius at reasoning.
|
|
||||||
|
|
||||||
- Follow the user’s requirements carefully & to the letter.
|
|
||||||
- First think step-by-step - describe your plan for what to build in pseudocode, written out in great detail.
|
|
||||||
- Confirm, then write code!
|
|
||||||
- Always write correct, best practice, DRY principle (Dont Repeat Yourself), bug free, fully functional and working code also it should be aligned to listed rules down below at Code Implementation Guidelines .
|
|
||||||
- Focus on easy and readability code, over being performant.
|
|
||||||
- Fully implement all requested functionality.
|
|
||||||
- Leave NO todo’s, placeholders or missing pieces.
|
|
||||||
- Ensure code is complete! Verify thoroughly finalised.
|
|
||||||
- Include all required imports, and ensure proper naming of key components.
|
|
||||||
- Be concise Minimize any other prose.
|
|
||||||
- If you think there might not be a correct answer, you say so.
|
|
||||||
- If you do not know the answer, say so, instead of guessing.
|
|
||||||
|
|
||||||
### Coding Environment
|
|
||||||
The user asks questions about the following coding languages:
|
|
||||||
- ReactJS
|
|
||||||
- Nestjs
|
|
||||||
- Prisma
|
|
||||||
- JavaScript
|
|
||||||
- TypeScript
|
|
||||||
- TailwindCSS
|
|
||||||
- HTML
|
|
||||||
- CSS
|
|
||||||
|
|
||||||
### Code Implementation Guidelines
|
|
||||||
Follow these rules when you write code:
|
|
||||||
- Use early returns whenever possible to make the code more readable.
|
|
||||||
- Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
|
|
||||||
- Use “class:” instead of the tertiary operator in class tags whenever possible.
|
|
||||||
- Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
|
|
||||||
- Implement accessibility features on elements. For example, a tag should have a tabindex=“0”, aria-label, on:click, and on:keydown, and similar attributes.
|
|
||||||
- Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,4 +9,4 @@ frontend/.vite
|
|||||||
node_modules
|
node_modules
|
||||||
pestgres_data/
|
pestgres_data/
|
||||||
redis_data/
|
redis_data/
|
||||||
|
aisugestions.md
|
||||||
|
|||||||
70
Dockerfile
Normal file
70
Dockerfile
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
# backend/Dockerfile
|
||||||
|
FROM node:18-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install necessary tools
|
||||||
|
RUN apk add --no-cache curl wget postgresql-client
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies including dev dependencies for building
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Install NestJS CLI globally
|
||||||
|
RUN npm install -g @nestjs/cli
|
||||||
|
|
||||||
|
# Copy prisma files
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
|
||||||
|
# Generate Prisma client
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:18-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install necessary tools
|
||||||
|
RUN apk add --no-cache curl wget postgresql-client
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install production dependencies only
|
||||||
|
RUN npm install --omit=dev
|
||||||
|
|
||||||
|
# Copy prisma files and generate client
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy built application from builder stage
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|
||||||
|
# Create the start script
|
||||||
|
RUN printf '#!/bin/sh\n\
|
||||||
|
until pg_isready -h postgres -p 5432 -U ${POSTGRES_USER} -d ${POSTGRES_DB}; do\n\
|
||||||
|
echo "Waiting for postgres..."\n\
|
||||||
|
sleep 2\n\
|
||||||
|
done\n\
|
||||||
|
\n\
|
||||||
|
echo "PostgreSQL is ready!"\n\
|
||||||
|
\n\
|
||||||
|
npx prisma migrate deploy\n\
|
||||||
|
node dist/main.js\n' > /app/start.sh
|
||||||
|
|
||||||
|
# Make the script executable
|
||||||
|
RUN chmod +x /app/start.sh
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Use shell form to ensure environment variables are expanded
|
||||||
|
CMD ["/bin/sh", "/app/start.sh"]
|
||||||
13
TODO.md
Normal file
13
TODO.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Todo
|
||||||
|
|
||||||
|
- [ ] on password reset page, link in the sent to user email is undefined;
|
||||||
|
- [ ] translate mail template in backend;
|
||||||
|
- [x] translate user dashboard;
|
||||||
|
- [ ] clean console logs;
|
||||||
|
- [ ] remove TUF logo;
|
||||||
|
- [ ] arrow down fix;
|
||||||
|
- [ ] use posthog for monitoring;
|
||||||
|
- [ ] comprehensive monitoring solution for the backend;
|
||||||
|
- [ ] add monitoring to the frontend;
|
||||||
|
- [ ] add monitoring to the database;
|
||||||
|
- [ ]
|
||||||
35
_.env
35
_.env
@ -1,35 +0,0 @@
|
|||||||
# Environment variables declared in this file are automatically made available to Prisma.
|
|
||||||
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
|
|
||||||
|
|
||||||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
|
||||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
|
||||||
|
|
||||||
DATABASE_URL="postgresql://root:irina76@localhost:5433/imk2?schema=public"
|
|
||||||
JWT_SECRET=some-secret
|
|
||||||
AWS_REGION=EU2
|
|
||||||
AWS_ACCESS_KEY_ID=4d2f5655369a02100375e3247d7e1fe6
|
|
||||||
AWS_SECRET_ACCESS_KEY=6d4723e14c0d799b89948c24dbe983e4
|
|
||||||
AWS_S3_BUCKET_NAME=imk-data
|
|
||||||
AWS_ENDPOINT_URL=https://eu2.contabostorage.com
|
|
||||||
|
|
||||||
#Email Configuration
|
|
||||||
# SMTP_HOST=smtp.gmail.com
|
|
||||||
# SMTP_PORT=587
|
|
||||||
# SMTP_USER=taratur@gmail.com
|
|
||||||
# SMTP_PASS=dziy nccc svgg bovb
|
|
||||||
# EMAIL_FROM=taratur@gmail.com
|
|
||||||
|
|
||||||
SMTP_HOST=imk.mk
|
|
||||||
SMTP_PORT=465
|
|
||||||
SMTP_USER=mailer@imk.mk
|
|
||||||
SMTP_PASS=76Avtostoperski76
|
|
||||||
SMTP_FROM=mailer@imk.mk
|
|
||||||
# FRONTEND_URL=https://imk.mk
|
|
||||||
EMAIL_FROM=mailer@yandex.com
|
|
||||||
|
|
||||||
ADMIN_EMAIL=taratur@gmail.com
|
|
||||||
|
|
||||||
# default app ADMIN
|
|
||||||
DEFAULT_ADMIN_EMAIL=taratur@gmail.com
|
|
||||||
DEFAULT_ADMIN_PASSWORD=irina7654321
|
|
||||||
DEFAULT_ADMIN_NAME=admin
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
|
||||||
backend:
|
|
||||||
logging:
|
|
||||||
driver: "json-file"
|
|
||||||
options:
|
|
||||||
max-size: "10m"
|
|
||||||
max-file: "3"
|
|
||||||
container_name: imk-backend
|
|
||||||
build:
|
|
||||||
context: ./backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=production
|
|
||||||
- PORT=3000
|
|
||||||
- DATABASE_URL=postgresql://postgres:postgres@imk-postgres:5432/postgres?schema=public
|
|
||||||
- FRONTEND_URL=https://www.placebo.mk
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 2G
|
|
||||||
reservations:
|
|
||||||
memory: 512M
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
networks:
|
|
||||||
- app_network
|
|
||||||
healthcheck:
|
|
||||||
test:
|
|
||||||
[
|
|
||||||
"CMD",
|
|
||||||
"wget",
|
|
||||||
"-q",
|
|
||||||
"--spider",
|
|
||||||
"http://localhost:3000/health || exit 1",
|
|
||||||
]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 15s
|
|
||||||
restart: always
|
|
||||||
postgres:
|
|
||||||
container_name: imk-postgres
|
|
||||||
image: postgres:14-alpine
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: postgres
|
|
||||||
PGDATA: /var/lib/postgresql/data/pgdata
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
networks:
|
|
||||||
- app_network
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
redis:
|
|
||||||
container_name: imk-redis
|
|
||||||
image: redis:alpine
|
|
||||||
command: redis-server --appendonly yes
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
networks:
|
|
||||||
- app_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
networks:
|
|
||||||
app_network:
|
|
||||||
driver: bridge
|
|
||||||
name: app_network
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
name: imk_postgres_data
|
|
||||||
redis_data:
|
|
||||||
name: imk_redis_data
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# backend/.dockerignore
|
# backend/.dockerignore
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
.env
|
#.env
|
||||||
.env.*
|
#.env.*
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
33
backend/Dockerfile.dev
Normal file
33
backend/Dockerfile.dev
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
FROM node:18-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install necessary tools
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
postgresql-client \
|
||||||
|
bash
|
||||||
|
|
||||||
|
# Install global packages
|
||||||
|
RUN npm install -g @nestjs/cli
|
||||||
|
|
||||||
|
|
||||||
|
# Copy scripts
|
||||||
|
COPY scripts/start-dev.sh /app/scripts/
|
||||||
|
RUN chmod +x /app/scripts/start-dev.sh
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy prisma files
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
|
||||||
|
# Generate Prisma client
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
EXPOSE 3000 9229
|
||||||
|
|
||||||
|
# Use the initialization script as the entry point
|
||||||
|
CMD ["/app/scripts/start-dev.sh"]
|
||||||
@ -1,76 +0,0 @@
|
|||||||
# backend/Dockerfile
|
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
# Add build arguments
|
|
||||||
ARG NODE_ENV
|
|
||||||
ARG API_URL
|
|
||||||
ARG CORS_ORIGIN
|
|
||||||
ARG DATABASE_URL
|
|
||||||
ARG POSTGRES_USER
|
|
||||||
ARG POSTGRES_PASSWORD
|
|
||||||
ARG POSTGRES_DB
|
|
||||||
ARG JWT_SECRET
|
|
||||||
ARG SMTP_HOST
|
|
||||||
ARG SMTP_PORT
|
|
||||||
ARG SMTP_USER
|
|
||||||
ARG SMTP_PASS
|
|
||||||
ARG EMAIL_FROM
|
|
||||||
ARG DEFAULT_ADMIN_EMAIL
|
|
||||||
ARG DEFAULT_ADMIN_PASSWORD
|
|
||||||
ARG DEFAULT_ADMIN_NAME
|
|
||||||
|
|
||||||
# Set environment variables from build args
|
|
||||||
ENV NODE_ENV=${NODE_ENV}
|
|
||||||
ENV API_URL=${API_URL}
|
|
||||||
ENV CORS_ORIGIN=${CORS_ORIGIN}
|
|
||||||
ENV DATABASE_URL=${DATABASE_URL}
|
|
||||||
ENV POSTGRES_USER=${POSTGRES_USER}
|
|
||||||
ENV POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
||||||
ENV POSTGRES_DB=${POSTGRES_DB}
|
|
||||||
ENV JWT_SECRET=${JWT_SECRET}
|
|
||||||
ENV SMTP_HOST=${SMTP_HOST}
|
|
||||||
ENV SMTP_PORT=${SMTP_PORT}
|
|
||||||
ENV SMTP_USER=${SMTP_USER}
|
|
||||||
ENV SMTP_PASS=${SMTP_PASS}
|
|
||||||
ENV EMAIL_FROM=${EMAIL_FROM}
|
|
||||||
ENV DEFAULT_ADMIN_EMAIL=${DEFAULT_ADMIN_EMAIL}
|
|
||||||
ENV DEFAULT_ADMIN_PASSWORD=${DEFAULT_ADMIN_PASSWORD}
|
|
||||||
ENV DEFAULT_ADMIN_NAME=${DEFAULT_ADMIN_NAME}
|
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
|
||||||
|
|
||||||
# Install necessary tools
|
|
||||||
RUN apk add --no-cache curl wget postgresql-client
|
|
||||||
|
|
||||||
# Copy package files
|
|
||||||
COPY package*.json ./
|
|
||||||
COPY prisma ./prisma/
|
|
||||||
# Install dependencies
|
|
||||||
RUN npm install --omit-dev
|
|
||||||
|
|
||||||
# Copy prisma schema
|
|
||||||
# COPY prisma ./prisma/
|
|
||||||
|
|
||||||
# Generate Prisma client
|
|
||||||
RUN npx prisma generate
|
|
||||||
# RUN npx prisma migrate deploy
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build the application
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Expose port
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# ADD https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /wait-for-it.sh
|
|
||||||
# RUN chmod +x /wait-for-it.sh
|
|
||||||
# Add healthcheck
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
||||||
CMD wget -q --spider http://localhost:3000/health || exit 1
|
|
||||||
|
|
||||||
# Start the application
|
|
||||||
# CMD ["npm", "run", "start:prod"]
|
|
||||||
|
|
||||||
CMD ["node", "dist/main.js"]
|
|
||||||
75
backend/docker-compose.dev.yml
Normal file
75
backend/docker-compose.dev.yml
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
container_name: imk-postgres-dev
|
||||||
|
image: postgres:14-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: imk_db
|
||||||
|
volumes:
|
||||||
|
- postgres_data_dev:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
networks:
|
||||||
|
- imk_network_dev
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
backend:
|
||||||
|
container_name: imk-backend-dev
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
|
volumes:
|
||||||
|
- ./src:/app/src:delegated
|
||||||
|
- ./prisma:/app/prisma:delegated
|
||||||
|
- ./package.json:/app/package.json:delegated
|
||||||
|
- ./package-lock.json:/app/package-lock.json:delegated
|
||||||
|
- ./tsconfig.json:/app/tsconfig.json:delegated
|
||||||
|
- ./nest-cli.json:/app/nest-cli.json:delegated
|
||||||
|
- node_modules:/app/node_modules
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DATABASE_URL=postgresql://postgres:postgres@postgres:5432/imk_db?schema=public
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_PASSWORD=postgres
|
||||||
|
- POSTGRES_DB=imk_db
|
||||||
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
|
- AWS_REGION=${AWS_REGION}
|
||||||
|
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
|
||||||
|
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
|
||||||
|
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME}
|
||||||
|
- AWS_ENDPOINT_URL=${AWS_ENDPOINT_URL}
|
||||||
|
- SMTP_HOST=${SMTP_HOST}
|
||||||
|
- SMTP_PORT=${SMTP_PORT}
|
||||||
|
- SMTP_USER=${SMTP_USER}
|
||||||
|
- SMTP_PASS=${SMTP_PASS}
|
||||||
|
- EMAIL_FROM=${EMAIL_FROM}
|
||||||
|
- FRONTEND_URL=${FRONTEND_URL}
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
- "9229:9229"
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- imk_network_dev
|
||||||
|
restart: unless-stopped
|
||||||
|
command: ["/app/scripts/start-dev.sh"]
|
||||||
|
tty: true
|
||||||
|
stdin_open: true
|
||||||
|
# command: sh -c "rm -rf /app/dist && npm run start:dev"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
imk_network_dev:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data_dev:
|
||||||
|
node_modules:
|
||||||
34
backend/env.development
Normal file
34
backend/env.development
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# imk_copy/backend/.env.development
|
||||||
|
# Database
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
|
POSTGRES_DB=imk_dev
|
||||||
|
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/imk_dev?schema=public
|
||||||
|
|
||||||
|
# JWT
|
||||||
|
JWT_SECRET=your_development_jwt_secret
|
||||||
|
|
||||||
|
# AWS/S3
|
||||||
|
AWS_REGION=your-region
|
||||||
|
AWS_ACCESS_KEY_ID=your-access-key
|
||||||
|
AWS_SECRET_ACCESS_KEY=your-secret-key
|
||||||
|
AWS_S3_BUCKET_NAME=your-bucket-name
|
||||||
|
AWS_ENDPOINT_URL=your-endpoint-url
|
||||||
|
|
||||||
|
# SMTP
|
||||||
|
SMTP_HOST=smtp.example.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USER=your-smtp-user
|
||||||
|
SMTP_PASS=your-smtp-password
|
||||||
|
EMAIL_FROM=noreply@example.com
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
FRONTEND_URL=http://localhost:5173
|
||||||
|
|
||||||
|
# Admin defaults
|
||||||
|
DEFAULT_ADMIN_EMAIL=admin@example.com
|
||||||
|
DEFAULT_ADMIN_PASSWORD=admin123
|
||||||
|
DEFAULT_ADMIN_NAME=System Admin
|
||||||
|
|
||||||
|
# Node
|
||||||
|
NODE_ENV=development
|
||||||
@ -23,7 +23,10 @@
|
|||||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||||
"prisma:generate": "prisma generate",
|
"prisma:generate": "prisma generate",
|
||||||
"prisma:migrate:dev": "prisma migrate dev",
|
"prisma:migrate:dev": "prisma migrate dev",
|
||||||
"prisma:migrate": "prisma migrate deploy"
|
"prisma:migrate": "prisma migrate deploy",
|
||||||
|
"docker:dev": "docker-compose -f docker-compose.dev.yml up",
|
||||||
|
"docker:dev:build": "docker-compose -f docker-compose.dev.yml up --build",
|
||||||
|
"docker:dev:down": "docker-compose -f docker-compose.dev.yml down -v"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.679.0",
|
"@aws-sdk/client-s3": "^3.679.0",
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "_SharedDocuments" ADD CONSTRAINT "_SharedDocuments_AB_pkey" PRIMARY KEY ("A", "B");
|
||||||
|
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "_SharedDocuments_AB_unique";
|
||||||
@ -1,3 +1,3 @@
|
|||||||
# Please do not edit this file manually
|
# Please do not edit this file manually
|
||||||
# It should be added in your version-control system (i.e. Git)
|
# It should be added in your version-control system (e.g., Git)
|
||||||
provider = "postgresql"
|
provider = "postgresql"
|
||||||
9
backend/scripts/_init-db.sh
Executable file
9
backend/scripts/_init-db.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# backend/scripts/init-db.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||||
|
CREATE DATABASE $POSTGRES_DB;
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $POSTGRES_USER;
|
||||||
|
EOSQL
|
||||||
29
backend/scripts/init-db.sh
Normal file → Executable file
29
backend/scripts/init-db.sh
Normal file → Executable file
@ -1,9 +1,24 @@
|
|||||||
#!/bin/bash
|
#!/bin/sh
|
||||||
# backend/scripts/init-db.sh
|
|
||||||
|
|
||||||
set -e
|
echo "Starting development initialization..."
|
||||||
|
|
||||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
# Wait for database to be ready
|
||||||
CREATE DATABASE $POSTGRES_DB;
|
echo "Waiting for database to be ready..."
|
||||||
GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $POSTGRES_USER;
|
until PGPASSWORD=$POSTGRES_PASSWORD psql -h postgres -U $POSTGRES_USER -d postgres -c '\q'; do
|
||||||
EOSQL
|
echo "Postgres is unavailable - sleeping"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Database is ready!"
|
||||||
|
|
||||||
|
# Run Prisma migrations
|
||||||
|
echo "Running Prisma migrations..."
|
||||||
|
npx prisma migrate dev
|
||||||
|
|
||||||
|
# Generate Prisma Client (just in case)
|
||||||
|
echo "Generating Prisma Client..."
|
||||||
|
npx prisma generate
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
echo "Starting application in development mode..."
|
||||||
|
npm run start:dev
|
||||||
|
|||||||
20
backend/scripts/init-dev.sh
Executable file
20
backend/scripts/init-dev.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Starting development server..."
|
||||||
|
|
||||||
|
# Wait for database to be ready
|
||||||
|
echo "Waiting for database to be ready..."
|
||||||
|
until PGPASSWORD=$POSTGRES_PASSWORD psql -h postgres -U $POSTGRES_USER -d postgres -c '\q'; do
|
||||||
|
echo "Postgres is unavailable - sleeping"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Database is ready!"
|
||||||
|
|
||||||
|
# Run Prisma migrations
|
||||||
|
echo "Running Prisma migrations..."
|
||||||
|
npx prisma migrate dev --name init
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
echo "Starting application..."
|
||||||
|
npm run start:dev
|
||||||
30
backend/scripts/start-dev.sh
Executable file
30
backend/scripts/start-dev.sh
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Starting development initialization..."
|
||||||
|
|
||||||
|
# Wait for database to be ready
|
||||||
|
echo "Waiting for database to be ready..."
|
||||||
|
until PGPASSWORD=$POSTGRES_PASSWORD psql -h postgres -U $POSTGRES_USER -d postgres -c '\q'; do
|
||||||
|
echo "Postgres is unavailable - sleeping"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Database is ready!"
|
||||||
|
|
||||||
|
# Run Prisma migrations
|
||||||
|
echo "Running Prisma migrations..."
|
||||||
|
npx prisma migrate dev --name init
|
||||||
|
|
||||||
|
# Generate Prisma Client (just in case)
|
||||||
|
echo "Generating Prisma Client..."
|
||||||
|
npx prisma generate
|
||||||
|
|
||||||
|
# Clean dist directory if it exists
|
||||||
|
if [ -d "dist" ]; then
|
||||||
|
echo "Cleaning dist directory..."
|
||||||
|
rm -rf dist
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start the application in development mode
|
||||||
|
echo "Starting application in development mode..."
|
||||||
|
exec npm run start:dev
|
||||||
0
backend/scripts/test-db.sh
Normal file → Executable file
0
backend/scripts/test-db.sh
Normal file → Executable file
0
backend/scripts/wait-for-db.sh
Normal file → Executable file
0
backend/scripts/wait-for-db.sh
Normal file → Executable file
@ -1,9 +1,9 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
import { AuthController } from './auth.controller';
|
import { AuthController } from "./auth.controller";
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from "./auth.service";
|
||||||
import { CreateUserDto } from '../dto/create-user.dto';
|
import { CreateUserDto } from "../dto/create-user.dto";
|
||||||
|
|
||||||
describe('AuthController', () => {
|
describe("AuthController", () => {
|
||||||
let controller: AuthController;
|
let controller: AuthController;
|
||||||
let authService: AuthService;
|
let authService: AuthService;
|
||||||
|
|
||||||
@ -24,12 +24,13 @@ describe('AuthController', () => {
|
|||||||
authService = module.get<AuthService>(AuthService);
|
authService = module.get<AuthService>(AuthService);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('register', () => {
|
describe("register", () => {
|
||||||
it('should call authService.createUser with CreateUserDto', async () => {
|
it("should call authService.createUser with CreateUserDto", async () => {
|
||||||
const createUserDto: CreateUserDto = {
|
const createUserDto: CreateUserDto = {
|
||||||
name: 'testuser',
|
name: "testuser",
|
||||||
password: 'password123',
|
password: "password123",
|
||||||
email: 'test@example.com',
|
email: "test@example.com",
|
||||||
|
isAdmin: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
await controller.register(createUserDto);
|
await controller.register(createUserDto);
|
||||||
|
|||||||
@ -4,9 +4,9 @@ export const corsConfig = {
|
|||||||
"https://www.placebo.mk",
|
"https://www.placebo.mk",
|
||||||
"https://placebo.mk",
|
"https://placebo.mk",
|
||||||
"https://imkapi.oblak.solutions",
|
"https://imkapi.oblak.solutions",
|
||||||
"https://eu-assets.i.posthog.com",
|
// "https://eu-assets.i.posthog.com",
|
||||||
"https://app.posthog.com",
|
// "https://app.posthog.com",
|
||||||
"https://eu.posthog.com",
|
// "https://eu.posthog.com",
|
||||||
],
|
],
|
||||||
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
||||||
credentials: true,
|
credentials: true,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { IsString, IsEmail, MinLength, IsBoolean } from 'class-validator';
|
import { IsString, IsEmail, MinLength, IsBoolean } from "class-validator";
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from "class-transformer";
|
||||||
|
|
||||||
export class CreateUserDto {
|
export class CreateUserDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
|
|||||||
@ -25,6 +25,12 @@ async function bootstrap() {
|
|||||||
whitelist: true,
|
whitelist: true,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
app.useGlobalPipes(
|
||||||
|
new ValidationPipe({
|
||||||
|
transform: true,
|
||||||
|
whitelist: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
helmet({
|
helmet({
|
||||||
@ -69,7 +75,7 @@ async function bootstrap() {
|
|||||||
logger.log(`Attempting to start server on port ${port}...`);
|
logger.log(`Attempting to start server on port ${port}...`);
|
||||||
await app.listen(port, "0.0.0.0");
|
await app.listen(port, "0.0.0.0");
|
||||||
|
|
||||||
logger.log(`Application is running on: ${await app.getUrl()}`);
|
logger.log(`Application is Running on: ${await app.getUrl()}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Failed to start application:", error);
|
logger.error("Failed to start application:", error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
11
backend/start-dev.sh
Executable file
11
backend/start-dev.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
until pg_isready -h postgres -p 5432 -U ${POSTGRES_USER} -d ${POSTGRES_DB}; do
|
||||||
|
echo "Waiting for postgres..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "PostgreSQL is ready!"
|
||||||
|
|
||||||
|
npx prisma migrate dev --name init
|
||||||
|
npm run start:dev
|
||||||
47
docker-compose.yaml
Normal file
47
docker-compose.yaml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
container_name: imk-backend
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
- POSTGRES_DB=${POSTGRES_DB}
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- imk_network
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
container_name: imk-postgres
|
||||||
|
image: postgres:14-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
- POSTGRES_DB=${POSTGRES_DB}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "5433:5432"
|
||||||
|
networks:
|
||||||
|
- imk_network
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres -d ${POSTGRES_DB}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
networks:
|
||||||
|
imk_network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
@ -12,3 +12,20 @@ docker rmi -f $(docker images -q)
|
|||||||
|
|
||||||
# Start fresh
|
# Start fresh
|
||||||
docker-compose up --build
|
docker-compose up --build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# reset development
|
||||||
|
# Stop containers and remove volumes
|
||||||
|
docker-compose -f docker-compose.dev.yml down -v
|
||||||
|
|
||||||
|
# Remove existing images
|
||||||
|
docker rmi $(docker images -q backend_backend)
|
||||||
|
|
||||||
|
# Rebuild and start
|
||||||
|
docker-compose -f docker-compose.dev.yml up --build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
docker-compose -f docker-compose.dev.yml up --build --force-recreate
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { Card } from "../UI/Card";
|
|||||||
function DocumentUpload() {
|
function DocumentUpload() {
|
||||||
const [file, setFile] = useState(null);
|
const [file, setFile] = useState(null);
|
||||||
const [title, setTitle] = useState("");
|
const [title, setTitle] = useState("");
|
||||||
const [selectedUserId, setSelectedUserId] = useState(""); // Changed from array to single value
|
const [selectedUserId, setSelectedUserId] = useState("");
|
||||||
const [availableUsers, setAvailableUsers] = useState([]);
|
const [availableUsers, setAvailableUsers] = useState([]);
|
||||||
const [status, setStatus] = useState("idle");
|
const [status, setStatus] = useState("idle");
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
const [errorMessage, setErrorMessage] = useState("");
|
||||||
|
|||||||
@ -1,13 +1,38 @@
|
|||||||
|
import react from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
getAllUsers,
|
||||||
|
getUserInfo,
|
||||||
|
createUser,
|
||||||
|
resetUserPassword,
|
||||||
|
} from "../../services/api";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { FiKey, FiUserPlus } from "react-icons/fi";
|
||||||
|
|
||||||
function Users() {
|
function Users() {
|
||||||
const [newUser, setNewUser] = useState({});
|
const navigate = useNavigate();
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const [isAdmin, setIsAdmin] = useState(false);
|
||||||
|
const [resetPasswordModal, setResetPasswordModal] = useState({
|
||||||
|
isOpen: false,
|
||||||
|
userId: null,
|
||||||
|
userName: "",
|
||||||
|
newPassword: "",
|
||||||
|
});
|
||||||
|
const [newUser, setNewUser] = useState({
|
||||||
|
name: "",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
isAdmin: false,
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 mb-6 shadow-xl">
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 mb-6 shadow-xl">
|
||||||
<h2 className="text-xl font-bold text-white mb-4">Креирај корисник</h2>
|
<h2 className="text-xl font-bold text-white mb-4">Креирај корисник</h2>
|
||||||
<form
|
<form
|
||||||
ref={createUserFormRef}
|
|
||||||
onSubmit={handleCreateUser}
|
onSubmit={handleCreateUser}
|
||||||
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"
|
||||||
>
|
>
|
||||||
@ -131,6 +156,7 @@ function Users() {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export default Users;
|
||||||
@ -1,8 +1,9 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const API_URL = "https://imkapi.oblak.solutions:3000";
|
// const API_URL = "https://imkapi.oblak.solutions:3000";
|
||||||
|
const API_URL = "https://localhost:3000";
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: "https://imkapi.oblak.solutions",
|
baseURL: API_URL,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
headers: {
|
headers: {
|
||||||
Accept: "application/json, text/plain, */*",
|
Accept: "application/json, text/plain, */*",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user