Skip to content

biyonik/conduit-go

Repository files navigation

πŸš€ Conduit-Go Framework

Go Version License Build Status

Modern, Laravel-inspired web framework for Go. Built with security, performance, and developer experience in mind.

✨ Features

πŸ”’ Phase 1: Security & Stability (βœ… COMPLETED)

  • SQL Injection Protection
  • CSRF Protection
  • Rate Limiting
  • Graceful Shutdown
  • Memory Leak Protection

πŸ” Phase 2: Authentication & Authorization (βœ… COMPLETED)

  • JWT Authentication

    • Access & refresh tokens
    • Token rotation
    • Secure token storage
  • User Management

    • Registration with validation
    • Login with bcrypt password hashing
    • Profile management
    • Password change
  • Password Reset

    • Forgot password flow
    • Secure reset tokens (1-hour expiry)
    • Email notifications (ready for Phase 3)
  • Role-Based Authorization

    • Admin, Editor, User roles
    • Protected routes
    • Policy-based access control

πŸ”„ Phase 3: Advanced Features (βœ… COMPLETED)

Queue System

  • Redis Queue

    • Push/Later (immediate/delayed dispatch)
    • Pop (blocking job fetch)
    • Failed job handling
    • Retry mechanism with exponential backoff
  • Job System

    • Job interface with Handle() and Failed()
    • Serialization/deserialization
    • Job metadata (ID, attempts, queue name)
    • Job registry for type mapping
  • Worker

    • Multiple queue support
    • Graceful shutdown
    • Concurrent processing
    • Failed job tracking

Event System

  • Event Dispatcher

    • Laravel-inspired event-driven architecture
    • Multiple listeners per event
    • Async/sync dispatch
    • Thread-safe operations
  • Event Features

    • Built-in events (user, email, payment, cache)
    • Custom event creation
    • Conditional listeners
    • Async listeners for slow operations
    • Event statistics and monitoring

Mail System

  • SMTP Driver

    • Send emails via any SMTP server
    • Support for Gmail, SendGrid, AWS SES, Mailhog
    • HTML & plain text emails
    • File attachments
    • Multiple recipients (To, Cc, Bcc)
  • Message Builder

    • Fluent API for email construction
    • Priority levels (High, Normal, Low)
    • Custom headers support
    • Reply-To support
  • Drivers

    • SMTP (production)
    • Log (development/testing)

Storage System

  • Local Storage

    • Local filesystem operations
    • Path traversal protection
    • Stream support for large files
    • Directory management
    • URL generation
  • Storage Features

    • Upload/download files
    • File existence checks
    • File size and metadata
    • Unique name generation
    • Image detection helpers

πŸ“‹ Usage Examples

Event System

// Create dispatcher
dispatcher := events.NewDispatcher(logger)

// Register listener
dispatcher.Listen("user.registered", events.ListenerFunc(func(e events.Event) error {
    user := e.Payload().(*models.User)
    log.Printf("New user: %s", user.Email)
    return nil
}))

// Dispatch event
event := events.NewUserRegisteredEvent(user)
dispatcher.Dispatch(event)

// Async dispatch (non-blocking)
dispatcher.DispatchAsync(event)

Mail System

// Configure SMTP (Mailhog for development)
config := &mail.SMTPConfig{
    Host: "localhost",
    Port: 1025,
    From: mail.Address{Email: "noreply@conduit.com", Name: "Conduit"},
}
mailer := mail.NewSMTPMailer(config, logger)

// Send email
message := mail.NewMessage().
    To("user@example.com", "John Doe").
    Subject("Welcome to Conduit!").
    Body("Thank you for joining.").
    Html("<h1>Welcome!</h1>")

err := mailer.Send(message)

Storage System

// Initialize local storage
storage, _ := storage.NewLocalStorage("/var/www/uploads", logger)
storage.SetBaseURL("https://cdn.myapp.com")

// Upload file
imageData := []byte{...}
storage.Put("avatars/user-1.jpg", imageData)

// Get URL
url := storage.Url("avatars/user-1.jpg")
// β†’ "https://cdn.myapp.com/avatars/user-1.jpg"

// Stream large file
file, _ := os.Open("large-video.mp4")
storage.PutFile("videos/video.mp4", file)

// Download
data, _ := storage.Get("avatars/user-1.jpg")

Queue System

// Create a job
emailJob := jobs.NewSendEmailJob(
    "user@example.com",
    "Welcome to Conduit-Go",
    "Hello! Welcome to our platform.",
)

// Push to queue (immediate)
queue.Push(emailJob, "emails")

// Push to queue (delayed)
queue.Later(5*time.Minute, emailJob, "emails")

Running Workers

# Start worker for default queue
make worker

# Start worker for specific queues
make worker-emails

# Start worker for all queues
make worker-all

# Or directly
go run cmd/worker/main.go emails notifications

Creating Custom Jobs

package jobs

import (
    "encoding/json"
    "github.com/biyonik/conduit-go/pkg/queue"
)

type MyCustomJob struct {
    queue.BaseJob
    Data string `json:"data"`
}

func (j *MyCustomJob) Handle() error {
    // Your job logic here
    return nil
}

func (j *MyCustomJob) Failed(err error) error {
    // Failed job handling
    return nil
}

func (j *MyCustomJob) GetPayload() ([]byte, error) {
    return json.Marshal(j)
}

func (j *MyCustomJob) SetPayload(data []byte) error {
    return json.Unmarshal(data, j)
}

// Register the job type
func init() {
    queue.RegisterJob("*jobs.MyCustomJob", func() queue.Job {
        return &MyCustomJob{}
    })
}

πŸš€ Quick Start

Prerequisites

  • Go 1.25 or higher
  • MySQL 8.0 or higher
  • Docker (optional)

Installation

# Clone repository
git clone https://github.com/yourusername/conduit-go.git
cd conduit-go

# Environment setup
cp .env.example .env
nano .env  # Edit with your credentials

# Start Docker services
docker-compose up -d
sleep 10  # Wait for MySQL

# Run application
make run

Server runs on: http://localhost:8000

πŸ“– API Documentation

Authentication Endpoints

Register

POST /api/auth/register
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "Secret123!",
  "password_confirm": "Secret123!"
}

Response:

{
  "success": true,
  "data": {
    "user": {
      "id": 123,
      "name": "John Doe",
      "email": "john@example.com"
    },
    "access_token": "eyJhbGc...",
    "refresh_token": "eyJhbGc...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}

Login

POST /api/auth/login
Content-Type: application/json

{
  "email": "john@example.com",
  "password": "Secret123!"
}

Get Profile (Protected)

GET /api/auth/profile
Authorization: Bearer {access_token}

Refresh Token

POST /api/auth/refresh
Content-Type: application/json

{
  "refresh_token": "eyJhbGc..."
}

Forgot Password

POST /api/auth/forgot-password
Content-Type: application/json

{
  "email": "john@example.com"
}

Reset Password

POST /api/auth/reset-password
Content-Type: application/json

{
  "token": "abc123...",
  "email": "john@example.com",
  "password": "NewSecret123!",
  "password_confirm": "NewSecret123!"
}

Protected Routes

All /api/v1/* routes require authentication:

GET /api/v1/check
Authorization: Bearer {access_token}

Admin Routes

Admin-only routes require admin role:

GET /api/admin/users
Authorization: Bearer {admin_access_token}

πŸ’» Usage Examples

Frontend Integration (React/Vue/Angular)

// Register
const registerResponse = await fetch('http://localhost:8000/api/auth/register', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John Doe',
    email: 'john@example.com',
    password: 'Secret123!',
    password_confirm: 'Secret123!',
  }),
});

const { data } = await registerResponse.json();
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('refresh_token', data.refresh_token);

// Protected API call
const profileResponse = await fetch('http://localhost:8000/api/auth/profile', {
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
  },
});

// Handle token expiration
if (profileResponse.status === 401) {
  // Refresh token
  const refreshResponse = await fetch('http://localhost:8000/api/auth/refresh', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      refresh_token: localStorage.getItem('refresh_token'),
    }),
  });
  
  const { data } = await refreshResponse.json();
  localStorage.setItem('access_token', data.access_token);
  localStorage.setItem('refresh_token', data.refresh_token);
  
  // Retry original request
}

πŸ§ͺ Testing

# Run all tests
make test

# Run auth tests only
go test -v ./tests -run Auth

# Run with coverage
make test-coverage

# Security audit
make security

πŸ” Security Best Practices

Password Requirements

  • Minimum 8 characters
  • At least 1 uppercase letter
  • At least 1 lowercase letter
  • At least 1 number
  • At least 1 special character

Token Management

  • Access tokens expire in 1 hour
  • Refresh tokens expire in 7 days
  • Tokens use HS256 algorithm
  • Secret keys must be stored in environment variables

Rate Limiting

  • Public auth endpoints: 10 requests/minute
  • Protected API endpoints: 50 requests/minute
  • Admin endpoints: 30 requests/minute

πŸ“¦ Postman Collection

Import postman/Conduit-Go-API.postman_collection.json to test all endpoints.

Variables:

  • base_url: http://localhost:8000
  • access_token: Auto-populated after login
  • refresh_token: Auto-populated after login

πŸ› οΈ Development

# Format code
make fmt

# Run linter
make lint

# Build binary
make build

# Run with hot reload
make run

🎨 Phase 4: CLI Tool & Code Generation (βœ… COMPLETED)

Conduit comes with a powerful Laravel Artisan-inspired CLI tool for rapid development.

Build the CLI Tool

# Build conduit CLI tool
go build -o conduit cmd/conduit/main.go

# Or add to PATH
sudo mv conduit /usr/local/bin/

Make Commands

Generate controllers, models, middleware, jobs, events, and listeners with a single command:

# Create a controller
conduit make:controller UserController

# Create a resource controller with CRUD methods
conduit make:controller UserController --resource

# Create an API controller (no views)
conduit make:controller UserController --api

# Create a model
conduit make:model User

# Create a model with migration
conduit make:model Post --migration

# Create middleware
conduit make:middleware AuthMiddleware

# Create a job
conduit make:job ProcessVideoJob

# Create an event
conduit make:event UserRegistered

# Create a listener
conduit make:listener SendWelcomeEmail --event=UserRegistered

Migration Commands

Manage database schema changes with Laravel-style migrations:

# Run pending migrations
conduit migrate

# Rollback the last migration
conduit migrate:rollback

# Rollback multiple migrations
conduit migrate:rollback --step=3

# Drop all tables and re-run migrations
conduit migrate:fresh

# Show migration status
conduit migrate:status

Cache Commands

# Clear all cache
conduit cache:clear

# Forget a specific cache key
conduit cache:forget user:123

Queue Commands

# Start queue worker
conduit queue:work

# Start queue worker for specific queue
conduit queue:work --queue=emails

# Limit number of jobs
conduit queue:work --max-jobs=100

# Start queue listener (auto-restart on code changes)
conduit queue:listen

# Restart all queue workers
conduit queue:restart

Development Server

# Start development server (default: localhost:8080)
conduit serve

# Custom host and port
conduit serve --host=0.0.0.0 --port=3000

The dev server includes:

  • βœ… Auto-logging of all requests
  • βœ… Beautiful welcome page
  • βœ… Health check endpoint (/health)
  • βœ… Graceful shutdown
  • βœ… Hot reload ready

Help & Version

# Show all available commands
conduit help

# Show version
conduit version

πŸ§ͺ Testing Helpers

Conduit provides Laravel-inspired testing utilities:

package controllers_test

import (
    "testing"
    "github.com/biyonik/conduit-go/pkg/testing"
)

func TestUserCreation(t *testing.T) {
    // HTTP Testing
    resp := testing.NewTestRequest("POST", "/api/users").
        WithJSON(map[string]interface{}{
            "name": "John Doe",
            "email": "john@example.com",
        }).
        Send(router)

    // Assertions
    resp.AssertStatus(t, 201).
        AssertJSON(t).
        AssertJSONPath(t, "message", "User created")

    // Database Testing
    testing.RefreshDatabase(t)
    testing.DatabaseTransaction(t, func(tx *sql.Tx) {
        // Test code runs in transaction, auto-rolled back
    })

    // Factory Pattern
    user := testing.UserFactory().Make(map[string]interface{}{
        "email": "custom@example.com",
    })

    // Assertions
    testing.AssertEquals(t, "custom@example.com", user["email"])
    testing.AssertNotNil(t, user["name"])
    testing.AssertTrue(t, user["active"].(bool), "User should be active")
}

πŸ”’ Security Audit Results

βœ… Comprehensive security audit completed - See SECURITY_AUDIT_REPORT.md

  • βœ… Event System: Goroutine leak prevention with graceful shutdown
  • βœ… Storage System: Path traversal attacks prevented (100+ test cases)
  • βœ… Database: SQL injection protection verified (50+ test cases)
  • βœ… Race Conditions: No data races detected (go test -race)
  • βœ… Test Coverage: >80% on all critical security paths

Security Rating: 🟒 PRODUCTION READY

🚦 Roadmap

  • Phase 1: Security & Stability

  • Phase 2: Authentication & Authorization

  • Phase 3: Advanced Features

    • βœ… Queue system (Redis)
    • βœ… Event system
    • βœ… Cache facade
    • βœ… Mail system
    • βœ… File storage
    • βœ… Email verification
  • Phase 4: Developer Experience (βœ… COMPLETED)

    • βœ… CLI tool (Artisan-inspired)
    • βœ… Code generators (make commands)
    • βœ… Migration system
    • βœ… Testing helpers
    • βœ… Development server
    • βœ… Comprehensive security audit
  • Phase 5: Production Enhancements (Next)

    • SMTP connection pooling
    • Distributed tracing
    • Metrics & monitoring
    • Load balancing
    • Docker orchestration
    • Rate limiting improvements

πŸ“ Environment Variables

# Application
APP_NAME=Conduit-Go
APP_ENV=development
PORT=8000

# Database
DB_DSN=user:pass@tcp(localhost:3306)/conduit_go?parseTime=true

# JWT
JWT_SECRET=your-super-secret-key
JWT_EXPIRATION=3600

# Rate Limiting
RATE_LIMIT_MAX_REQUESTS=100
RATE_LIMIT_WINDOW_SECONDS=60

🀝 Contributing

We welcome contributions! Please read our Contributing Guide to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes.

Contributors

Thank you to all the people who have contributed to Conduit-Go! πŸŽ‰

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ‘¨β€πŸ’» Author

Ahmet Altun


Built with ❀️ and β˜• in Turkey

About

No description, website, or topics provided.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •