userPanel Svelte Themes

Userpanel

A re-useable user panel for multiple applications based on go + svelte + docker

Auth Service API

A RESTful authentication service built with Go, PostgreSQL, JWT, and Docker. Designed for integration with a SvelteKit + Material 3 frontend.

๐Ÿš€ Features

  • โœ… User registration and authentication
  • โœ… JWT-based token authentication (24-hour expiry)
  • โœ… Secure password hashing with bcrypt
  • โœ… CORS enabled for frontend integration
  • โœ… RESTful API with consistent JSON responses
  • โœ… Request logging middleware
  • โœ… PostgreSQL with GORM ORM
  • โœ… Docker & Docker Compose ready
  • โœ… Auto database migrations

๐Ÿ“‹ Prerequisites

  • Docker & Docker Compose
  • Go 1.24+ (for local development)
  • PostgreSQL 16+ (if running without Docker)

๐Ÿ› ๏ธ Setup

1. Clone and Configure

cd /path/to/userPanel

2. Environment Variables

Create or update backend/.env:

PORT=8080
DATABASE_URL=postgres://postgres:password@db:5432/authdb?sslmode=disable
JWT_SECRET=your-super-secret-jwt-key-change-in-production
CORS_ORIGIN=http://localhost:5173

3. Start Services

# Start with Docker Compose
docker compose up --build

# Or in detached mode
docker compose up --build -d

# View logs
docker compose logs -f api

The API will be available at http://localhost:8080

๐Ÿ“ก API Endpoints

Health Check

GET /api/health

Check service status and uptime.

Response:

{
  "success": true,
  "data": {
    "status": "ok",
    "uptime": "5m 23s"
  }
}

Authentication

POST /api/register

Register a new user account.

Request Body:

{
  "name": "John Doe",
  "email": "[email protected]",
  "password": "password123"
}

Validation:

  • Email is required and must be unique
  • Name is required
  • Password must be at least 6 characters

Success Response (200):

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]",
      "created_at": "2025-11-01T17:51:14Z",
      "updated_at": "2025-11-01T17:51:14Z"
    }
  }
}

Error Response (409):

{
  "success": false,
  "message": "Email already registered"
}

POST /api/login

Authenticate and receive a JWT token.

Request Body:

{
  "email": "[email protected]",
  "password": "password123"
}

Success Response (200):

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]",
      "created_at": "2025-11-01T17:51:14Z",
      "updated_at": "2025-11-01T17:51:14Z"
    }
  }
}

Error Response (401):

{
  "success": false,
  "message": "Invalid email or password"
}

User Profile (Protected Routes)

All profile endpoints require authentication via JWT token in the Authorization header:

Authorization: Bearer <your-jwt-token>

GET /api/profile

Get authenticated user's profile.

Headers:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200):

{
  "success": true,
  "data": {
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]",
    "avatar": "https://example.com/avatar.jpg",
    "created_at": "2025-11-01T17:51:14Z",
    "updated_at": "2025-11-01T17:51:14Z"
  }
}

Error Response (401):

{
  "success": false,
  "message": "Invalid or expired token"
}

PUT /api/profile

Update authenticated user's profile.

Headers:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

Request Body:

{
  "name": "Jane Doe",
  "avatar": "https://example.com/new-avatar.jpg"
}

Success Response (200):

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Jane Doe",
    "email": "[email protected]",
    "avatar": "https://example.com/new-avatar.jpg",
    "created_at": "2025-11-01T17:51:14Z",
    "updated_at": "2025-11-01T17:52:05Z"
  }
}

DELETE /api/profile

Delete authenticated user's account (soft delete).

Headers:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200):

{
  "success": true,
  "message": "Account deleted successfully"
}

๐Ÿงช Testing with cURL

# Health check
curl http://localhost:8080/api/health

# Register
curl -X POST http://localhost:8080/api/register \
  -H "Content-Type: application/json" \
  -d '{"name":"John Doe","email":"[email protected]","password":"password123"}'

# Login
curl -X POST http://localhost:8080/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"password123"}'

# Get Profile (replace TOKEN with your JWT)
curl -X GET http://localhost:8080/api/profile \
  -H "Authorization: Bearer <TOKEN>"

# Update Profile
curl -X PUT http://localhost:8080/api/profile \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Jane Doe","avatar":"https://example.com/avatar.jpg"}'

# Delete Account
curl -X DELETE http://localhost:8080/api/profile \
  -H "Authorization: Bearer <TOKEN>"

๐Ÿ—๏ธ Project Structure

backend/
โ”œโ”€โ”€ cmd/
โ”‚   โ””โ”€โ”€ auth-service/
โ”‚       โ””โ”€โ”€ main.go              # Application entry point
โ”œโ”€โ”€ config/
โ”‚   โ””โ”€โ”€ config.go                # Configuration management
โ”œโ”€โ”€ internal/
โ”‚   โ”œโ”€โ”€ handlers/
โ”‚   โ”‚   โ”œโ”€โ”€ auth.go             # Auth endpoints (register, login)
โ”‚   โ”‚   โ”œโ”€โ”€ user.go             # User profile endpoints
โ”‚   โ”‚   โ””โ”€โ”€ health.go           # Health check endpoint
โ”‚   โ”œโ”€โ”€ middleware/
โ”‚   โ”‚   โ”œโ”€โ”€ auth.go             # JWT authentication middleware
โ”‚   โ”‚   โ””โ”€โ”€ logger.go           # Request logging middleware
โ”‚   โ”œโ”€โ”€ models/
โ”‚   โ”‚   โ””โ”€โ”€ user.go             # User database model
โ”‚   โ””โ”€โ”€ utils/
โ”‚       โ”œโ”€โ”€ jwt.go              # JWT utilities
โ”‚       โ”œโ”€โ”€ password.go         # Password hashing
โ”‚       โ””โ”€โ”€ response.go         # JSON response helpers
โ”œโ”€โ”€ routes/
โ”‚   โ””โ”€โ”€ routes.go               # Route definitions
โ”œโ”€โ”€ db/
โ”‚   โ”œโ”€โ”€ migrations/             # SQL migrations (optional)
โ”‚   โ””โ”€โ”€ queries/                # SQL queries (if using sqlc)
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ .env                        # Environment variables
โ””โ”€โ”€ .env.example                # Example environment file

๐Ÿ” Security Features

  • Password Hashing: bcrypt with default cost (10)
  • JWT Tokens: HS256 algorithm, 24-hour expiry
  • CORS: Configured for frontend origin (default: http://localhost:5173)
  • Soft Deletes: User accounts are soft-deleted (recoverable)
  • Email Normalization: Emails are lowercased and trimmed
  • No Password Logging: Passwords are never logged in plaintext

๐Ÿ”ง Development

Local Development (without Docker)

# Install dependencies
go mod download

# Run database migrations (ensure PostgreSQL is running)
# Update DATABASE_URL in .env to point to your local DB

# Run the server
go run ./backend/cmd/auth-service/main.go

Database Schema

The User model is auto-migrated on startup:

type User struct {
    ID           uint           // Primary key
    Name         string         // User's full name
    Email        string         // Unique email address
    PasswordHash string         // bcrypt hashed password
    Avatar       string         // Profile avatar URL (optional)
    CreatedAt    time.Time      // Account creation timestamp
    UpdatedAt    time.Time      // Last update timestamp
    DeletedAt    *time.Time     // Soft delete timestamp
}

๐Ÿณ Docker Commands

# Build and start
docker compose up --build

# Stop services
docker compose down

# View logs
docker compose logs -f api

# Restart API only
docker compose restart api

# Remove volumes (caution: deletes database data)
docker compose down -v

๐ŸŒ Frontend Integration

SvelteKit Example

// Login function
async function login(email, password) {
  const response = await fetch('http://localhost:8080/api/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });
  
  const data = await response.json();
  if (data.success) {
    localStorage.setItem('token', data.data.token);
    return data.data.user;
  }
  throw new Error(data.message);
}

// Authenticated request
async function getProfile() {
  const token = localStorage.getItem('token');
  const response = await fetch('http://localhost:8080/api/profile', {
    headers: { 'Authorization': `Bearer ${token}` }
  });
  
  const data = await response.json();
  if (data.success) return data.data;
  throw new Error(data.message);
}

๐Ÿ“ Environment Variables Reference

Variable Description Default Required
PORT Server port 8080 No
DATABASE_URL PostgreSQL connection string - Yes
JWT_SECRET Secret key for JWT signing - Yes
CORS_ORIGIN Allowed CORS origin http://localhost:5173 No

๐Ÿค Contributing

  1. Follow Go best practices and idiomatic code
  2. Use descriptive variable names
  3. Add comments for complex logic
  4. Test endpoints before committing
  5. Update this README for new features

๐Ÿ“„ License

This project is part of the userPanel application.

๐Ÿ†˜ Troubleshooting

Port Already in Use

# Check what's using port 8080
sudo lsof -i :8080

# Or change the port in .env
PORT=8081

Database Connection Issues

  • Ensure PostgreSQL container is running: docker compose ps
  • Check DATABASE_URL in .env matches docker-compose.yml settings
  • Verify network connectivity: docker network ls

JWT Token Invalid

  • Ensure JWT_SECRET matches between registration and login
  • Check token hasn't expired (24-hour lifetime)
  • Verify Authorization header format: Bearer <token>

Built with โค๏ธ using Go, PostgreSQL, GORM, Chi, and Docker

Top categories

Loading Svelte Themes