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.
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.
- 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
All implementations provide these operations:
create(entity)- Add a new entityread(id)- Retrieve an entity by IDupdate(id, data)- Modify an existing entitydelete(id)- Remove an entity by IDlist()- Return all entities
The IAM system provides comprehensive identity management and access control:
- User Management: Create, read, update, delete users
- Session Management: Create, refresh, and invalidate user sessions
- Credential Verification: Secure authentication with username/password
- Role-Based Access Control (RBAC): Assign permissions through roles
- Permission System: Granular permissions for actions on resources
- Policy Evaluation: Check access permissions for operations
All implementations provide these IAM operations:
create_user(principal, password)- Register a new userauthenticate(credentials)- Verify credentials and return principalcreate_session(principal)- Start an authenticated sessionget_session(token)- Retrieve session by tokeninvalidate_session(token)- End a session
check_permission(context)- Verify if action is allowed on resourcecreate_role(role)- Define a new role with permissionsassign_role(principal, role)- Grant role to a userrevoke_role(principal, role)- Remove role from a user
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")
}├── 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
The Go implementation uses:
- Interfaces for abstraction
sync.RWMutexfor 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")// 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)The Python implementation uses:
- Abstract Base Classes (ABC) for interfaces
threading.RLockfor 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")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)The Rust implementation uses:
- Traits for abstraction
std::sync::RwLockfor thread safetythiserrorfor 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")?;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)?;# CRUD example
cd go
go run examples/basic/main.go
# IAM example
go run examples/iam/main.go# CRUD example
cd python
python examples/main.py
# IAM example
python examples/iam_demo.py# CRUD example
cd rust
cargo run --example main
# IAM example
cargo run --example iam_democd go
go test ./crud -vcd python
pip install pytest
python -m pytest crud/test_crud.py -vcd rust
cargo testAll implementations provide consistent error types:
- NotFound: Entity with given ID doesn't exist
- AlreadyExists: Entity with given ID already exists
- InvalidId: Empty or invalid ID provided
- 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
All implementations are thread-safe:
- Go: Uses
sync.RWMutexfor concurrent access - Python: Uses
threading.RLockfor thread safety - Rust: Uses
std::sync::RwLockfor concurrent access
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
- Fork the repository
- Create a feature branch
- Set up pre-commit hooks (optional but recommended):
pip install pre-commit pre-commit install
- Make your changes
- Ensure all tests pass and code is properly formatted
- Submit a pull request
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-verifyMIT License - see LICENSE file for details.
This project demonstrates several important software engineering principles:
- Consistency: Same interface across all languages
- Testability: Comprehensive test coverage
- Documentation: Clear, consistent documentation
- Error Handling: Robust error handling patterns
- Concurrency: Thread-safe operations
- Maintainability: Clean, well-structured code
- Automation: Comprehensive CI/CD pipelines