Skip to content

A repo for playing around with CRUD and IAM implementations in go, rust and python. Python uses JWT to implement token based authentication.

License

Notifications You must be signed in to change notification settings

thephiltacular/crud-iam-playground

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CRUD and IAM Playground

A CRUD (Create, Read, Update, Delete) and IAM (Identity and Access Management) library implemented in Go, Python, and Rust with consistent interfaces, comprehensive test suites, and CI/CD.

CI - All Languages Go CI Python CI Rust CI

Overview

This project demonstrates how to build consistent APIs across different programming languages for both CRUD operations and Identity and Access Management (IAM). Each implementation provides the same CRUD interface with identical functionality, error handling, and behavior patterns, along with comprehensive IAM features including authentication, authorization, and session management.

Features

  • Consistent Interface: Same CRUD operations across all languages
  • Identity and Access Management: Authentication, authorization, and session management
  • Thread-Safe: All implementations use proper concurrency controls
  • Comprehensive Testing: Full test coverage with edge cases and concurrency tests
  • Error Handling: Robust error handling with clear error types
  • Documentation: Well-documented code with examples
  • CI/CD: Automated testing and validation for all implementations

CRUD Interface

All implementations provide these operations:

  • create(entity) - Add a new entity
  • read(id) - Retrieve an entity by ID
  • update(id, data) - Modify an existing entity
  • delete(id) - Remove an entity by ID
  • list() - Return all entities

Identity and Access Management (IAM)

The IAM system provides comprehensive identity management and access control:

Authentication

  • User Management: Create, read, update, delete users
  • Session Management: Create, refresh, and invalidate user sessions
  • Credential Verification: Secure authentication with username/password

Authorization

  • Role-Based Access Control (RBAC): Assign permissions through roles
  • Permission System: Granular permissions for actions on resources
  • Policy Evaluation: Check access permissions for operations

IAM Interfaces

All implementations provide these IAM operations:

Authentication

  • create_user(principal, password) - Register a new user
  • authenticate(credentials) - Verify credentials and return principal
  • create_session(principal) - Start an authenticated session
  • get_session(token) - Retrieve session by token
  • invalidate_session(token) - End a session

Authorization

  • check_permission(context) - Verify if action is allowed on resource
  • create_role(role) - Define a new role with permissions
  • assign_role(principal, role) - Grant role to a user
  • revoke_role(principal, role) - Remove role from a user

IAM Integration with CRUD

The IAM system integrates seamlessly with CRUD operations:

  • Access Control: Check permissions before allowing CRUD operations
  • Audit Logging: Track who performed what operations
  • Context-Aware: Use session context for authorization decisions

Example IAM usage:

// Authenticate user
principal, err := authProvider.Authenticate(Credentials{
    Username: "john_doe",
    Password: "password123",
})

// Check permission for CRUD operation
ctx := AuthorizationContext{
    Principal: principal,
    Resource:  NewResource("entity", "user-1"),
    Action:    ActionRead,
}
allowed, err := authzProvider.CheckPermission(ctx)
if allowed {
    // Perform CRUD operation
    entity, err := store.Read("user-1")
}

Project Structure

├── go/                     # Go implementation
│   ├── crud/              # Core CRUD and IAM library
│   │   ├── entity.go      # Entity definition
│   │   ├── interface.go   # CRUD interface
│   │   ├── memory_store.go # In-memory CRUD implementation
│   │   ├── auth.go        # Authentication interface and implementation
│   │   ├── authz.go       # Authorization interface and implementation
│   │   ├── iam_store.go   # IAM data storage
│   │   ├── crud_test.go   # CRUD tests
│   │   ├── iam_test.go    # IAM tests
│   ├── examples/          # Usage examples
│   └── go.mod            # Go module definition
├── python/                # Python implementation
│   ├── crud/             # Core CRUD and IAM library
│   │   ├── __init__.py   # Package exports
│   │   ├── entity.py     # Entity class
│   │   ├── interface.py  # Abstract base class
│   │   ├── memory_store.py # In-memory CRUD implementation
│   │   ├── auth.py       # Authentication classes
│   │   ├── authz.py      # Authorization classes
│   │   ├── iam_store.py  # IAM data storage
│   │   ├── errors.py     # Custom exceptions
│   │   ├── test_crud.py  # CRUD tests
│   │   ├── test_iam.py   # IAM tests
│   ├── examples/         # Usage examples
│   └── pyproject.toml    # Python package configuration
├── rust/                 # Rust implementation
│   ├── src/             # Source code
│   │   ├── lib.rs       # Library root
│   │   ├── entity.rs    # Entity struct
│   │   ├── store.rs     # Store trait
│   │   ├── memory_store.rs # In-memory CRUD implementation
│   │   ├── auth.rs      # Authentication traits and structs
│   │   ├── authz.rs     # Authorization traits and structs
│   │   ├── iam_store.rs # IAM data storage
│   │   ├── errors.rs    # Error types
│   │   ├── tests.rs     # CRUD tests
│   │   ├── iam_tests.rs # IAM tests
│   ├── examples/        # Usage examples
│   └── Cargo.toml       # Rust package configuration
└── .github/
    └── workflows/       # CI/CD configurations

Language Implementations

Go

The Go implementation uses:

  • Interfaces for abstraction
  • sync.RWMutex for thread safety
  • Proper error handling with custom error types
  • Standard Go testing framework
// Create a store
store := crud.NewMemoryStore()

// Create an entity
entity := crud.NewEntity("user-1", map[string]interface{}{
    "name": "John Doe",
    "age":  30,
})
err := store.Create(entity)

// Read an entity
user, err := store.Read("user-1")

IAM Example (Go)

// Create auth provider
authProvider := crud.NewMemoryAuthProvider()

// Create a user
principal := crud.Principal{
    ID:       "user-1",
    Username: "john_doe",
    Email:    "john@example.com",
    Roles:    []string{"user"},
}
err := authProvider.CreateUser(principal, "password123")

// Authenticate
credentials := crud.Credentials{Username: "john_doe", Password: "password123"}
authenticatedPrincipal, err := authProvider.Authenticate(credentials)

// Create session
sessionManager := crud.NewMemorySessionManager()
session, err := sessionManager.CreateSession(authenticatedPrincipal, time.Hour)

// Check permission
authzProvider := crud.NewMemoryAuthorizationProvider()
ctx := crud.AuthorizationContext{
    Principal: authenticatedPrincipal,
    Resource:  crud.NewResource("entity", "user-1"),
    Action:    crud.ActionRead,
}
allowed, err := authzProvider.CheckPermission(ctx)

Python

The Python implementation uses:

  • Abstract Base Classes (ABC) for interfaces
  • threading.RLock for thread safety
  • Custom exception hierarchy
  • Type hints and pytest for testing
from crud import Entity, MemoryStore

# Create a store
store = MemoryStore()

# Create an entity
entity = Entity("user-1", {
    "name": "John Doe",
    "age": 30
})
store.create(entity)

# Read an entity
user = store.read("user-1")

IAM Example (Python)

from crud import Principal, Credentials, MemoryAuthProvider, MemorySessionManager, AuthorizationContext, MemoryAuthorizationProvider, Resource, Action
import datetime

# Create auth provider
auth_provider = MemoryAuthProvider()

# Create a user
principal = Principal(
    id="user-1",
    username="john_doe",
    email="john@example.com",
    roles=["user"]
)
auth_provider.create_user(principal, "password123")

# Authenticate
credentials = Credentials(username="john_doe", password="password123")
authenticated_principal = auth_provider.authenticate(credentials)

# Create session
session_manager = MemorySessionManager()
session = session_manager.create_session(authenticated_principal, datetime.timedelta(hours=1))

# Check permission
authz_provider = MemoryAuthorizationProvider()
ctx = AuthorizationContext(
    principal=authenticated_principal,
    resource=Resource(type="entity", id="user-1"),
    action=Action.READ
)
allowed = authz_provider.check_permission(ctx)

Rust

The Rust implementation uses:

  • Traits for abstraction
  • std::sync::RwLock for thread safety
  • thiserror for error handling
  • Rust's built-in testing framework
use crud_playground::{Entity, MemoryStore, Store};

// Create a store
let store = MemoryStore::new();

// Create an entity
let mut data = HashMap::new();
data.insert("name".to_string(), json!("John Doe"));
data.insert("age".to_string(), json!(30));
let entity = Entity::new("user-1".to_string(), data);
store.create(entity)?;

// Read an entity
let user = store.read("user-1")?;

IAM Example (Rust)

use crud_playground::{Principal, Credentials, MemoryAuthProvider, MemorySessionManager, AuthorizationContext, MemoryAuthorizationProvider, Resource, Action};
use std::time::Duration;

// Create auth provider
let auth_provider = MemoryAuthProvider::new();

// Create a user
let principal = Principal {
    id: "user-1".to_string(),
    username: "john_doe".to_string(),
    email: "john@example.com".to_string(),
    roles: vec!["user".to_string()],
    metadata: HashMap::new(),
};
auth_provider.create_user(principal, "password123".to_string())?;

// Authenticate
let credentials = Credentials {
    username: "john_doe".to_string(),
    password: "password123".to_string(),
};
let authenticated_principal = auth_provider.authenticate(credentials)?;

// Create session
let session_manager = MemorySessionManager::new();
let session = session_manager.create_session(authenticated_principal, Duration::from_secs(3600))?;

// Check permission
let authz_provider = MemoryAuthorizationProvider::new();
let ctx = AuthorizationContext {
    principal: authenticated_principal,
    resource: Resource::new("entity".to_string(), "user-1".to_string()),
    action: Action::Read,
    metadata: HashMap::new(),
};
let allowed = authz_provider.check_permission(ctx)?;

Running the Examples

Go

# CRUD example
cd go
go run examples/basic/main.go

# IAM example
go run examples/iam/main.go

Python

# CRUD example
cd python
python examples/main.py

# IAM example
python examples/iam_demo.py

Rust

# CRUD example
cd rust
cargo run --example main

# IAM example
cargo run --example iam_demo

Running Tests

Go

cd go
go test ./crud -v

Python

cd python
pip install pytest
python -m pytest crud/test_crud.py -v

Rust

cd rust
cargo test

Error Handling

All implementations provide consistent error types:

CRUD Errors

  • NotFound: Entity with given ID doesn't exist
  • AlreadyExists: Entity with given ID already exists
  • InvalidId: Empty or invalid ID provided

IAM Errors

  • InvalidCredentials: Authentication failed due to wrong credentials
  • UserNotFound: User does not exist in the system
  • UserAlreadyExists: User with given username already exists
  • SessionNotFound: Session token is invalid or expired
  • SessionExpired: Session has expired and needs refresh
  • AccessDenied: User does not have permission for the requested action

Thread Safety

All implementations are thread-safe:

  • Go: Uses sync.RWMutex for concurrent access
  • Python: Uses threading.RLock for thread safety
  • Rust: Uses std::sync::RwLock for concurrent access

CI/CD

The project includes comprehensive CI/CD pipelines:

  • Multiple Language Versions: Tests against multiple versions of each language
  • Code Quality: Formatting, linting, and static analysis
  • Security: Dependency auditing (Rust)
  • Coverage: Code coverage reporting
  • Change Detection: Only runs relevant tests when files change

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Set up pre-commit hooks (optional but recommended):
    pip install pre-commit
    pre-commit install
  4. Make your changes
  5. Ensure all tests pass and code is properly formatted
  6. Submit a pull request

Pre-commit Hooks

This project uses pre-commit hooks to ensure code quality and consistency across all languages:

  • Go: gofmt, go vet, go mod tidy, and tests
  • Python: black, flake8, isort, mypy, and tests
  • Rust: rustfmt, clippy, and tests
  • General: trailing whitespace, end-of-file fixes, merge conflict detection

The hooks will automatically run before each commit to catch issues early. You can also run them manually:

# Run on all files
pre-commit run --all-files

# Run on specific files
pre-commit run --files path/to/file.py

# Skip hooks for a specific commit (not recommended)
git commit --no-verify

License

MIT License - see LICENSE file for details.

Design Principles

This project demonstrates several important software engineering principles:

  1. Consistency: Same interface across all languages
  2. Testability: Comprehensive test coverage
  3. Documentation: Clear, consistent documentation
  4. Error Handling: Robust error handling patterns
  5. Concurrency: Thread-safe operations
  6. Maintainability: Clean, well-structured code
  7. Automation: Comprehensive CI/CD pipelines

About

A repo for playing around with CRUD and IAM implementations in go, rust and python. Python uses JWT to implement token based authentication.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published