Skip to content

A Go-based API service with SQLite storage and user authentication

Notifications You must be signed in to change notification settings

eckertalex/improved-fiesta

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Improved Fiesta 🎉

A Go-based API service with SQLite storage and user authentication.

Getting Started

Prerequisites

  • Go 1.23.2
  • SQLite3
  • Make

Quick Start

  1. Clone the repository
  2. Run make tidy to install dependencies
  3. Copy .env.example to .env:
cp .env.example .env
  1. Run database migrations to set up the database schema:
make db/migrations/up
  1. Seed the database:
make db/seed
  1. Start the development server with hot reload:
make watch/api

The API will be available at the port specified in your .env file (default: 45067).

Available Make Commands

Run make help to see all available commands. Here are the most commonly used ones:

Development

  • make run/api - Build and run the API
  • make watch/api - Run the API with hot reload using Air
  • make tidy - Format code and tidy up Go modules

Testing

  • make test - Run all tests
  • make itest - Run integration tests
  • make audit - Run quality control checks (tests, format verification, vulnerability scanning)

Database Operations

  • make db/migrations/new name=migration_name - Create a new migration
  • make db/migrations/up - Apply all pending migrations
  • make db/migrations/down - Revert all migrations
  • make db/seed - Seed the database with initial data
  • make db/connect - Connect to the SQLite database

API Documentation

This document provides comprehensive documentation for all API endpoints, including required permissions, request/response formats, and examples.

Table of Contents

Method Endpoint Permission Description
GET /v1/healthcheck Public Application health status
GET /v1/users Admin List users
POST /v1/users Public Create new user
GET /v1/users/:id Admin or Owner Get user details
PATCH /v1/users/:id Admin or Owner Update user details
DELETE /v1/users/:id Admin or Owner Delete user account
PATCH /v1/users/:id/role Admin Update user role
POST /v1/users/activate Public Activate user account
POST /v1/users/reset-password Public Reset user password
POST /v1/tokens/session Public Generate auth token
DELETE /v1/tokens/session Public Delete auth token
POST /v1/tokens/activation Public Request activation token
POST /v1/tokens/password-reset Public Request password reset
GET /debug/vars Admin Debug metrics

Authentication

For endpoints requiring authentication, include the authentication token in the Authorization header:

Authorization: Bearer <token>

Tokens can be obtained using the /v1/auth/authentication endpoint.

Endpoint Details

GET /v1/healthcheck

Permission: Public
Description: Check application health status and version information

Example Request:

curl http://localhost:45067/v1/healthcheck

Response Body:

  • status (string): Current application status
  • system_info (object):
    • environment (string): Current environment
    • version (string): Application version

Example Response:

{
  "status": "available",
  "system_info": {
    "environment": "development",
    "version": "2024-01-15T10:30:00Z-c3418de38b57f0a8bf49d9f7759469eac37cb410"
  }
}

GET /v1/users

Permission: Public
Description: List users

Query Parameters:

  • username (string): Username
  • email (string): User's email address
  • page (number): Page
  • page_size (number): Page size
  • sort (number): Sort order (must be 'id', 'username', 'email', 'role', '-id', '-username', '-email', '-role')

Request Headers:

  • Authorization: Bearer token

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:45067/v1/users?email=example&page=2&page_size=10&sort=-username

Response Body:

  • data (array): User details
  • metadata (object): Metadata details

Example Response:

{
  "data": [
    {
      "id": 123,
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T11:45:00Z",
      "username": "alice",
      "email": "[email protected]",
      "activated": true,
      "role": "user"
    }
    {
      "id": 124,
      "created_at": "2024-01-15T14:00:00Z",
      "updated_at": "2024-01-15T14:00:00Z",
      "username": "bob",
      "email": "[email protected]",
      "activated": false,
      "role": "user"
    },
  ],
  "metadata": {
    "current_page": 1,
    "page_size": 20,
    "first_page": 1,
    "last_page": 1,
    "total_records": 2
  }
}

POST /v1/users

Permission: Public
Description: Create a new user account

Request Body:

  • username (string): Username
  • email (string): User's email address
  • password (string): User's password

Example Request:

curl -X POST \
     -d '{"username": "bob", "email": "[email protected]", "password": "SecurePass123!"}' \
     http://localhost:45067/v1/users

Response Body:

  • data (object): User details

Example Response:

{
  "data": {
    "id": 124,
    "created_at": "2024-01-15T14:00:00Z",
    "updated_at": "2024-01-15T14:00:00Z",
    "username": "bob",
    "email": "[email protected]",
    "activated": false,
    "role": "user"
  }
}

GET /v1/users/:id

Permission: Admin or Owner
Description: Retrieve user details by ID

Path Parameters:

  • id (number): User ID

Request Headers:

  • Authorization: Bearer token

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:45067/v1/users/124

Response Body:

  • data (object): User details object

Example Response:

{
  "data": {
    "id": 124,
    "created_at": "2024-01-15T14:00:00Z",
    "updated_at": "2024-01-15T14:00:00Z",
    "username": "bob",
    "email": "[email protected]",
    "activated": false,
    "role": "user"
  }
}

PATCH /v1/users/:id

Permission: Admin or Owner
Description: Update user details

Path Parameters:

  • id (number): User ID

Request Headers:

  • Authorization: Bearer token

Request Body: (all fields optional)

  • username (string): New username
  • email (string): New email
  • password (string): New password

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     -X PATCH \
     -d '{"username": "robert"}' \
     http://localhost:45067/v1/users/124

Response Body:

  • data (object): Updated user details

Example Response:

{
  "data": {
    "id": 124,
    "created_at": "2024-01-15T14:00:00Z",
    "updated_at": "2024-01-15T15:30:00Z",
    "username": "robert",
    "email": "[email protected]",
    "activated": false,
    "role": "user"
  }
}

DELETE /v1/users/:id

Permission: Admin or Owner
Description: Delete user account

Path Parameters:

  • id (number): User ID

Request Headers:

  • Authorization: Bearer token

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     -X DELETE \
     http://localhost:45067/v1/users/124

Response: 204 No Content

PATCH /v1/users/:id/role

Permission: Admin
Description: Update user's role

Path Parameters:

  • id (number): User ID

Request Headers:

  • Authorization: Bearer token

Request Body:

  • role (string): New role (must be 'admin' or 'user')

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     -X PATCH \
     -d '{"role": "admin"}' \
     http://localhost:45067/v1/users/124/role

Response Body:

  • data (object): Updated user details

Example Response:

{
  "data": {
    "id": 124,
    "created_at": "2024-01-15T14:00:00Z",
    "updated_at": "2024-01-15T16:00:00Z",
    "username": "robert",
    "email": "[email protected]",
    "activated": false,
    "role": "admin"
  }
}

POST /v1/users/activate

Permission: Public
Description: Activate user account

Request Body:

  • token (string): Activation token

Example Request:

curl -X POST \
     -d '{"token": "URQXUFRJDA4KCIZ3CLZTHS3K3U"}' \
     http://localhost:45067/v1/users/activate

Response Body:

  • data (object): Updated user details

Example Response:

{
  "data": {
    "id": 123,
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "username": "alice",
    "email": "[email protected]",
    "activated": true,
    "role": "user"
  }
}

POST /v1/users/reset-password

Permission: Public
Description: Reset user password

Request Body:

  • password (string): New password
  • token (string): Password reset token

Example Request:

curl -X POST \
     -d '{"password": "SecurePass123!", "token": "K5YB7CA3KTZL4B6YXO5JLNLWWU"}' \
     http://localhost:45067/v1/users/reset-password

Response Body:

  • data (object): Updated user details

Example Response:

{
  "data": {
    "id": 123,
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T11:45:00Z",
    "username": "alice",
    "email": "[email protected]",
    "activated": true,
    "role": "user"
  }
}

POST /v1/tokens/session

Permission: Public
Description: Generate authentication token

Request Body:

  • email (string): User's email
  • password (string): User's password

Example Request:

curl -X POST \
     -d '{"email": "[email protected]", "password": "AdminPass123!"}' \
     http://localhost:45067/v1/tokens/session

Response Body:

  • authentication_token (object):
    • token (string): Authentication token
    • expiry (string): Token expiration timestamp

Example Response:

{
  "authentication_token": {
    "token": "QNSMBHTILTB4RDRTMRYACTGCTE",
    "expiry": "2024-01-15T13:30:00Z"
  }
}

DELETE /v1/tokens/session

Permission: Authenticated
Description: Delete auth token

Request Headers:

  • Authorization: Bearer token

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     -X DELETE \
     http://localhost:45067/v1/tokens/session

Response: 204 No Content

POST /v1/tokens/activation

Permission: Public
Description: Request new activation token

Request Body:

  • email (string): User's email

Example Request:

curl -X POST \
     -d '{"email": "[email protected]"}' \
     http://localhost:45067/v1/tokens/activation

Response Body:

  • message (string): Confirmation message

Example Response:

{
  "message": "an email will be sent to you containing activation instructions"
}

POST /v1/tokens/password-reset

Permission: Public
Description: Request password reset token

Request Body:

  • email (string): User's email

Example Request:

curl -X POST \
     -d '{"email": "[email protected]"}' \
     http://localhost:45067/v1/tokens/password-reset

Response Body:

  • message (string): Confirmation message

Example Response:

{
  "message": "an email will be sent to you containing password reset instructions"
}

GET /debug/vars

Permission: Admin
Description: Displays application metrics for debugging purposes

Request Headers:

  • Authorization: Bearer token

Example Request:

curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:45067/debug/vars

Response Body:

  • Various debugging metrics and application variables

Database Schema

The application uses SQLite as its database engine with the following schema:

Users Table

Stores user account information and credentials.

CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    username TEXT UNIQUE NOT NULL,
    email TEXT UNIQUE NOT NULL,
    password_hash BLOB NOT NULL,
    activated BOOLEAN NOT NULL DEFAULT false,
    role TEXT NOT NULL DEFAULT 'user' CHECK (role IN ('user', 'admin')),
    version INTEGER NOT NULL DEFAULT 1
);

Columns:

  • id: Unique identifier for each user
  • created_at: Timestamp of account creation
  • updated_at: Timestamp of last account update
  • username: Unique username
  • email: Unique email address
  • password_hash: Hashed user password (stored as BLOB)
  • activated: Account activation status
  • role: User role (either 'user' or 'admin')
  • version: Record version for optimistic locking

An updated_at trigger automatically updates the timestamp when the record changes:

CREATE TRIGGER set_updated_at
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
    UPDATE users SET updated_at = CURRENT_TIMESTAMP WHERE id = OLD.id;
END;

Tokens Table

Stores authentication, activation, and password reset tokens.

CREATE TABLE IF NOT EXISTS tokens (
    hash BLOB PRIMARY KEY,
    user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    expiry DATETIME NOT NULL,
    scope TEXT NOT NULL
);

Columns:

  • hash: Hashed token value (primary key)
  • user_id: Associated user ID (foreign key to users table)
  • expiry: Token expiration timestamp
  • scope: Token purpose/scope (e.g., 'authentication', 'activation', 'password-reset')

Relationships:

  • user_id references the id column in the users table
  • ON DELETE CASCADE ensures tokens are automatically deleted when the associated user is deleted

Todo

  • Write End-to-End tests

About

A Go-based API service with SQLite storage and user authentication

Topics

Resources

Stars

Watchers

Forks