4.9 KiB
Task 2.1 Implementation: User Data Model and DynamoDB Users Table
Overview
This task implements the User data model and DynamoDB Users table with full CRUD operations.
Files Created
1. User Model (internal/models/user.go)
- Defines the
Userstruct with all required fields:ID(user_id): Unique identifier (UUID)Email: User's email addressOAuthProvider: OAuth provider name (e.g., "google", "github")OAuthID: OAuth provider's user IDCreatedAt: Timestamp when user was createdUpdatedAt: Timestamp when user was last updated
2. DynamoDB Client (internal/storage/dynamodb.go)
NewDynamoDBClient: Creates a new DynamoDB client with optional endpoint overrideCreateUsersTable: Creates the Users table with proper schema- Partition Key:
user_id(String) - Billing Mode: Pay-per-request (on-demand)
- Waits for table to be active before returning
- Partition Key:
3. User Storage Layer (internal/storage/user_storage.go)
Implements all CRUD operations:
CreateUser: Creates a new user with auto-generated UUIDGetUserByID: Retrieves a user by their IDGetUserByOAuth: Retrieves a user by OAuth provider and IDUpdateUser: Updates an existing user (auto-updates UpdatedAt)DeleteUser: Deletes a user by their ID
4. Unit Tests (internal/storage/user_storage_test.go)
Comprehensive test coverage:
TestCreateUser: Verifies user creation with all fieldsTestGetUserByID: Tests user retrieval by IDTestGetUserByID_NotFound: Tests error handling for non-existent usersTestGetUserByOAuth: Tests user retrieval by OAuth credentialsTestGetUserByOAuth_NotFound: Tests error handling for OAuth lookupTestUpdateUser: Verifies user updates and timestamp changesTestDeleteUser: Tests user deletionTestCreateUser_MultipleUsers: Verifies multiple users can be created with unique IDs
5. Database Initialization (cmd/init-db/main.go)
Standalone CLI tool to initialize DynamoDB tables:
go run cmd/init-db/main.go -endpoint http://localhost:8000
6. Table Initialization Helper (cmd/server/init_tables.go)
Helper function for the main server to initialize tables on startup.
DynamoDB Schema
Users Table
Table Name: Users
Partition Key: user_id (String)
Billing Mode: Pay-per-request
Attributes:
- user_id: String (UUID)
- email: String
- oauth_provider: String
- oauth_id: String
- created_at: Number (Unix timestamp in nanoseconds)
- updated_at: Number (Unix timestamp in nanoseconds)
Dependencies Added
github.com/aws/aws-sdk-go-v2: AWS SDK for Go v2github.com/aws/aws-sdk-go-v2/config: AWS configurationgithub.com/aws/aws-sdk-go-v2/service/dynamodb: DynamoDB service clientgithub.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue: DynamoDB attribute marshalinggithub.com/google/uuid: UUID generation
Running Tests
Prerequisites
-
Start DynamoDB Local:
make db-startOr manually:
docker-compose up -d dynamodb-local -
Set environment variable (optional):
export DYNAMODB_ENDPOINT=http://localhost:8000
Run Tests
make test
# or
go test -v ./internal/storage/...
Usage Example
package main
import (
"context"
"log"
"custom-start-page/internal/storage"
)
func main() {
ctx := context.Background()
// Create DynamoDB client
db, err := storage.NewDynamoDBClient(ctx, "http://localhost:8000")
if err != nil {
log.Fatal(err)
}
// Create Users table
if err := db.CreateUsersTable(ctx); err != nil {
log.Fatal(err)
}
// Create user storage
userStorage := storage.NewUserStorage(db)
// Create a new user
user, err := userStorage.CreateUser(ctx, "user@example.com", "google", "google123")
if err != nil {
log.Fatal(err)
}
log.Printf("Created user: %+v", user)
// Retrieve user by ID
retrievedUser, err := userStorage.GetUserByID(ctx, user.ID)
if err != nil {
log.Fatal(err)
}
log.Printf("Retrieved user: %+v", retrievedUser)
}
Notes
OAuth Lookup Performance
The GetUserByOAuth method currently uses a Scan operation since there's no GSI for oauth_provider + oauth_id. For production use with many users, consider adding a GSI:
- Partition Key:
oauth_provider - Sort Key:
oauth_id
This would change the query from O(n) scan to O(1) lookup.
Timestamp Storage
Timestamps are stored as Go time.Time which DynamoDB marshals as Unix timestamps in nanoseconds. This provides high precision for audit trails.
Requirements Validated
- ✓ Requirement 1.1: User authentication foundation
- ✓ Requirement 1.3: OAuth user creation and retrieval
- ✓ Requirement 8.7: User data association
Next Steps
Task 2.2 will implement the OAuth service using this User model to handle Google OAuth authentication.