Skip to content

Commit 963a6ac

Browse files
committed
feat(api): add complete backend infrastructure with Go/Gin REST API
Implement comprehensive backend system including: - RESTful API with Gin framework and JWT authentication - PostgreSQL database models for shipments, assets, events, and digital passports - Docker containerization with multi-stage builds - Blockchain integration support for supply chain tracking - Real-time monitoring with geofencing capabilities - Organization-based multi-tenancy - Complete CRUD operations for all entities - Webhook endpoints for IoT data ingestion - Development tooling with Makefile and docker-compose The API provides endpoints for: - User authentication and authorization - Shipment tracking and management - Asset monitoring with IoT integration - Digital Product Passports (DPP) - Geofence zones and alerts - Dashboard analytics and metrics
1 parent b3791c1 commit 963a6ac

18 files changed

Lines changed: 2126 additions & 0 deletions

File tree

api/Dockerfile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Build stage
2+
FROM golang:1.21-alpine AS builder
3+
4+
# Install build dependencies
5+
RUN apk add --no-cache git
6+
7+
# Set working directory
8+
WORKDIR /app
9+
10+
# Copy go mod files
11+
COPY go.mod go.sum ./
12+
13+
# Download dependencies
14+
RUN go mod download
15+
16+
# Copy source code
17+
COPY . .
18+
19+
# Build the application
20+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
21+
22+
# Final stage
23+
FROM alpine:latest
24+
25+
# Install runtime dependencies
26+
RUN apk --no-cache add ca-certificates tzdata
27+
28+
# Set working directory
29+
WORKDIR /root/
30+
31+
# Copy the binary from builder
32+
COPY --from=builder /app/main .
33+
34+
# Copy environment file (optional)
35+
COPY --from=builder /app/.env.example .env.example
36+
37+
# Expose port
38+
EXPOSE 8080
39+
40+
# Run the application
41+
CMD ["./main"]

api/Makefile

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
.PHONY: help run build test clean docker-up docker-down docker-build migrate dev prod
2+
3+
# Colors for output
4+
GREEN := $(shell tput -Txterm setaf 2)
5+
YELLOW := $(shell tput -Txterm setaf 3)
6+
WHITE := $(shell tput -Txterm setaf 7)
7+
RESET := $(shell tput -Txterm sgr0)
8+
9+
# Default target
10+
help: ## Show this help message
11+
@echo ''
12+
@echo 'Usage:'
13+
@echo ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
14+
@echo ''
15+
@echo 'Targets:'
16+
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " ${YELLOW}%-15s${GREEN}%s${RESET}\n", $$1, $$2}' $(MAKEFILE_LIST)
17+
18+
run: ## Run the application locally
19+
go run main.go
20+
21+
build: ## Build the application
22+
go build -o bin/locsafe-api main.go
23+
24+
test: ## Run tests
25+
go test -v ./...
26+
27+
test-coverage: ## Run tests with coverage
28+
go test -v -cover ./...
29+
30+
clean: ## Clean build artifacts
31+
rm -rf bin/
32+
go clean
33+
34+
deps: ## Download dependencies
35+
go mod download
36+
go mod tidy
37+
38+
docker-up: ## Start Docker containers
39+
docker-compose up -d
40+
41+
docker-down: ## Stop Docker containers
42+
docker-compose down
43+
44+
docker-build: ## Build Docker image
45+
docker build -t locsafe-api:latest .
46+
47+
docker-logs: ## View Docker logs
48+
docker-compose logs -f
49+
50+
migrate: ## Run database migrations
51+
go run main.go migrate
52+
53+
seed: ## Seed database with sample data
54+
go run main.go seed
55+
56+
dev: ## Start development environment
57+
@echo "${GREEN}Starting development environment...${RESET}"
58+
docker-compose up -d postgres redis
59+
@sleep 3
60+
go run main.go
61+
62+
prod: docker-build ## Build and run production environment
63+
@echo "${GREEN}Starting production environment...${RESET}"
64+
docker-compose -f docker-compose.yml up -d
65+
66+
fmt: ## Format code
67+
go fmt ./...
68+
gofmt -s -w .
69+
70+
lint: ## Run linter
71+
golangci-lint run
72+
73+
vet: ## Run go vet
74+
go vet ./...
75+
76+
security: ## Run security checks
77+
gosec ./...
78+
79+
swagger: ## Generate Swagger documentation
80+
swag init -g main.go
81+
82+
db-reset: ## Reset database
83+
docker-compose down postgres
84+
docker volume rm locsafe_postgres_data
85+
docker-compose up -d postgres
86+
@sleep 5
87+
go run main.go migrate
88+
89+
install-tools: ## Install development tools
90+
go install github.com/swaggo/swag/cmd/swag@latest
91+
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
92+
go install github.com/securego/gosec/v2/cmd/gosec@latest
93+
94+
.DEFAULT_GOAL := help

api/config/database.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package config
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"gorm.io/driver/postgres"
8+
"gorm.io/gorm"
9+
"gorm.io/gorm/logger"
10+
)
11+
12+
// InitDB initializes and returns a database connection
13+
func InitDB() (*gorm.DB, error) {
14+
dsn := fmt.Sprintf(
15+
"host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=UTC",
16+
getEnv("DB_HOST", "localhost"),
17+
getEnv("DB_USER", "postgres"),
18+
getEnv("DB_PASSWORD", "postgres"),
19+
getEnv("DB_NAME", "locsafe"),
20+
getEnv("DB_PORT", "5432"),
21+
getEnv("DB_SSLMODE", "disable"),
22+
)
23+
24+
config := &gorm.Config{
25+
Logger: logger.Default.LogMode(logger.Info),
26+
}
27+
28+
// In production, reduce logging
29+
if os.Getenv("APP_ENV") == "production" {
30+
config.Logger = logger.Default.LogMode(logger.Error)
31+
}
32+
33+
db, err := gorm.Open(postgres.Open(dsn), config)
34+
if err != nil {
35+
return nil, fmt.Errorf("failed to connect to database: %w", err)
36+
}
37+
38+
// Configure connection pool
39+
sqlDB, err := db.DB()
40+
if err != nil {
41+
return nil, fmt.Errorf("failed to get database instance: %w", err)
42+
}
43+
44+
// Set connection pool settings
45+
sqlDB.SetMaxIdleConns(10)
46+
sqlDB.SetMaxOpenConns(100)
47+
48+
return db, nil
49+
}
50+
51+
// getEnv gets an environment variable with a fallback value
52+
func getEnv(key, fallback string) string {
53+
if value, exists := os.LookupEnv(key); exists {
54+
return value
55+
}
56+
return fallback
57+
}

api/docker-compose.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
version: '3.8'
2+
3+
services:
4+
postgres:
5+
image: postgres:15-alpine
6+
container_name: locsafe-postgres
7+
environment:
8+
POSTGRES_USER: postgres
9+
POSTGRES_PASSWORD: postgres
10+
POSTGRES_DB: locsafe
11+
ports:
12+
- "5432:5432"
13+
volumes:
14+
- postgres_data:/var/lib/postgresql/data
15+
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
16+
networks:
17+
- locsafe-network
18+
healthcheck:
19+
test: ["CMD-SHELL", "pg_isready -U postgres"]
20+
interval: 10s
21+
timeout: 5s
22+
retries: 5
23+
24+
redis:
25+
image: redis:7-alpine
26+
container_name: locsafe-redis
27+
ports:
28+
- "6379:6379"
29+
volumes:
30+
- redis_data:/data
31+
networks:
32+
- locsafe-network
33+
healthcheck:
34+
test: ["CMD", "redis-cli", "ping"]
35+
interval: 10s
36+
timeout: 5s
37+
retries: 5
38+
39+
api:
40+
build:
41+
context: .
42+
dockerfile: Dockerfile
43+
container_name: locsafe-api
44+
environment:
45+
APP_ENV: development
46+
PORT: 8080
47+
DB_HOST: postgres
48+
DB_PORT: 5432
49+
DB_USER: postgres
50+
DB_PASSWORD: postgres
51+
DB_NAME: locsafe
52+
DB_SSLMODE: disable
53+
REDIS_HOST: redis
54+
REDIS_PORT: 6379
55+
JWT_SECRET: jwt-key
56+
ports:
57+
- "8080:8080"
58+
depends_on:
59+
postgres:
60+
condition: service_healthy
61+
redis:
62+
condition: service_healthy
63+
volumes:
64+
- ./:/app
65+
networks:
66+
- locsafe-network
67+
restart: unless-stopped
68+
69+
volumes:
70+
postgres_data:
71+
redis_data:
72+
73+
networks:
74+
locsafe-network:
75+
driver: bridge

api/go.mod

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module github.com/tufstraka/Locsafe/api
2+
3+
go 1.21
4+
5+
require (
6+
github.com/gin-contrib/cors v1.5.0
7+
github.com/gin-gonic/gin v1.9.1
8+
github.com/golang-jwt/jwt/v5 v5.2.0
9+
github.com/google/uuid v1.5.0
10+
github.com/joho/godotenv v1.5.1
11+
github.com/lib/pq v1.10.9
12+
golang.org/x/crypto v0.19.0
13+
gorm.io/driver/postgres v1.5.4
14+
gorm.io/gorm v1.25.5
15+
)
16+
17+
require (
18+
github.com/bytedance/sonic v1.10.1 // indirect
19+
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
20+
github.com/chenzhuoyu/iasm v0.9.0 // indirect
21+
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
22+
github.com/gin-contrib/sse v0.1.0 // indirect
23+
github.com/go-playground/locales v0.14.1 // indirect
24+
github.com/go-playground/universal-translator v0.18.1 // indirect
25+
github.com/go-playground/validator/v10 v10.15.5 // indirect
26+
github.com/goccy/go-json v0.10.2 // indirect
27+
github.com/jackc/pgpassfile v1.0.0 // indirect
28+
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
29+
github.com/jackc/pgx/v5 v5.4.3 // indirect
30+
github.com/jinzhu/inflection v1.0.0 // indirect
31+
github.com/jinzhu/now v1.1.5 // indirect
32+
github.com/json-iterator/go v1.1.12 // indirect
33+
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
34+
github.com/kr/text v0.2.0 // indirect
35+
github.com/leodido/go-urn v1.2.4 // indirect
36+
github.com/mattn/go-isatty v0.0.19 // indirect
37+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
38+
github.com/modern-go/reflect2 v1.0.2 // indirect
39+
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
40+
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
41+
github.com/ugorji/go/codec v1.2.11 // indirect
42+
golang.org/x/arch v0.5.0 // indirect
43+
golang.org/x/net v0.16.0 // indirect
44+
golang.org/x/sys v0.17.0 // indirect
45+
golang.org/x/text v0.14.0 // indirect
46+
google.golang.org/protobuf v1.31.0 // indirect
47+
gopkg.in/yaml.v3 v3.0.1 // indirect
48+
)

0 commit comments

Comments
 (0)