Update documentation to reflect new authentication architecture
Remove legacy references to global auth composable and document the new dependency injection pattern with single source of truth. Key Documentation Updates: • Update authentication.md with DI architecture details and usage patterns • Update chat integration docs to reference AuthService and remove legacy patterns • Add comprehensive authentication-architecture.md with full technical details • Document migration path from legacy global auth to current DI pattern Content Changes: • Replace useAuth.ts references with useAuthService.ts • Document AuthService as singleton with dependency injection • Add code examples for both component and service usage • Explain benefits of new architecture (single source of truth, no timing issues) • Update chat integration to reflect service-based architecture 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4feb5459cc
commit
6cb10a31db
3 changed files with 311 additions and 11 deletions
235
docs/01-architecture/authentication-architecture.md
Normal file
235
docs/01-architecture/authentication-architecture.md
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
# Authentication Architecture
|
||||
|
||||
This document describes the current authentication architecture using dependency injection and service-based patterns.
|
||||
|
||||
## Overview
|
||||
|
||||
The authentication system has been refactored from a legacy global composable approach to a modern dependency injection pattern. This eliminates timing issues, improves maintainability, and provides a single source of truth for authentication state.
|
||||
|
||||
## Architecture Components
|
||||
|
||||
### 1. AuthService (Core Service)
|
||||
**Location**: `src/modules/base/auth/auth-service.ts`
|
||||
|
||||
The `AuthService` is a singleton service that extends `BaseService` and provides:
|
||||
- Reactive authentication state management
|
||||
- LNBits API integration
|
||||
- Event-driven authentication lifecycle
|
||||
- Automatic token management
|
||||
|
||||
**Key Features**:
|
||||
```typescript
|
||||
export class AuthService extends BaseService {
|
||||
// Public reactive state
|
||||
public isAuthenticated = ref(false)
|
||||
public user = ref<User | null>(null)
|
||||
public isLoading = ref(false)
|
||||
public error = ref<Error | null>(null)
|
||||
|
||||
// Computed properties for compatibility
|
||||
public currentUser = computed(() => this.user.value)
|
||||
public userDisplay = computed(() => { /* user display logic */ })
|
||||
|
||||
// Methods
|
||||
async login(credentials: LoginCredentials): Promise<void>
|
||||
async register(data: RegisterData): Promise<void>
|
||||
async logout(): Promise<void>
|
||||
async checkAuth(): Promise<boolean>
|
||||
async updatePassword(current: string, newPass: string): Promise<void>
|
||||
async updateProfile(data: Partial<User>): Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
### 2. useAuthService Composable (API Layer)
|
||||
**Location**: `src/composables/useAuthService.ts`
|
||||
|
||||
The `useAuthService` composable provides a clean, unified API that bridges Vue components with the injected AuthService:
|
||||
|
||||
```typescript
|
||||
export function useAuth() {
|
||||
const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) as AuthService
|
||||
|
||||
return {
|
||||
// State (reactive refs from service)
|
||||
currentUser: authService.currentUser,
|
||||
isAuthenticated: authService.isAuthenticated,
|
||||
isLoading: authService.isLoading,
|
||||
error: authService.error,
|
||||
userDisplay: authService.userDisplay,
|
||||
|
||||
// Methods (delegated to service)
|
||||
initialize: () => authService.initialize(),
|
||||
login: (credentials: any) => authService.login(credentials),
|
||||
register: (data: any) => authService.register(data),
|
||||
logout: () => authService.logout(),
|
||||
checkAuth: () => authService.checkAuth()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Dependency Injection Container
|
||||
**Location**: `src/core/di-container.ts`
|
||||
|
||||
The DI container manages service registration and injection:
|
||||
|
||||
```typescript
|
||||
// Service registration (in base module)
|
||||
container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService)
|
||||
|
||||
// Service consumption (in components/other services)
|
||||
const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) as AuthService
|
||||
```
|
||||
|
||||
## Usage Patterns
|
||||
|
||||
### In Vue Components (Recommended)
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { useAuth } from '@/composables/useAuthService'
|
||||
|
||||
const auth = useAuth()
|
||||
|
||||
// Access reactive state
|
||||
const isAuthenticated = auth.isAuthenticated
|
||||
const currentUser = auth.currentUser
|
||||
|
||||
// Call methods
|
||||
const handleLogin = async (credentials) => {
|
||||
await auth.login(credentials)
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### In Services (Direct Injection)
|
||||
```typescript
|
||||
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
||||
import type { AuthService } from '@/modules/base/auth/auth-service'
|
||||
|
||||
export class SomeService extends BaseService {
|
||||
private get authService(): AuthService {
|
||||
return this.dependencies.get('AuthService') as AuthService
|
||||
}
|
||||
|
||||
async someMethod() {
|
||||
const user = this.authService.user.value
|
||||
if (user?.pubkey) {
|
||||
// Use authenticated user data
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Benefits of New Architecture
|
||||
|
||||
### 1. **Single Source of Truth**
|
||||
- All authentication state managed by AuthService singleton
|
||||
- No more timing issues between global and injected auth
|
||||
- Consistent state across all modules and components
|
||||
|
||||
### 2. **Dependency Injection Benefits**
|
||||
- Loose coupling between components and auth logic
|
||||
- Easy to test (can inject mock services)
|
||||
- Modular architecture with clear boundaries
|
||||
- Service lifecycle management
|
||||
|
||||
### 3. **Improved Maintainability**
|
||||
- Centralized authentication logic
|
||||
- Event-driven architecture for auth state changes
|
||||
- Clear separation of concerns
|
||||
- Eliminated complex dual-auth detection patterns
|
||||
|
||||
### 4. **Performance Improvements**
|
||||
- No duplicate service instances
|
||||
- Efficient reactive state management
|
||||
- Reduced complexity in components
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### Before (Legacy Pattern)
|
||||
```typescript
|
||||
// ❌ Old global composable pattern
|
||||
import { auth } from '@/composables/useAuth'
|
||||
|
||||
// Direct access to global singleton
|
||||
const isAuthenticated = auth.isAuthenticated.value
|
||||
```
|
||||
|
||||
### After (Current Pattern)
|
||||
```typescript
|
||||
// ✅ New dependency injection pattern
|
||||
import { useAuth } from '@/composables/useAuthService'
|
||||
|
||||
const auth = useAuth()
|
||||
const isAuthenticated = auth.isAuthenticated.value
|
||||
```
|
||||
|
||||
## Service Integration
|
||||
|
||||
### Module Registration
|
||||
Each module that needs authentication access should:
|
||||
|
||||
1. **Declare dependency** on AuthService in module metadata
|
||||
2. **Access via dependency injection** using the DI container
|
||||
3. **Use reactive state** from the service for UI updates
|
||||
|
||||
### Example Service Integration
|
||||
```typescript
|
||||
export class ChatService extends BaseService {
|
||||
protected readonly metadata = {
|
||||
name: 'ChatService',
|
||||
dependencies: ['AuthService'] // Declare dependency
|
||||
}
|
||||
|
||||
async sendMessage(content: string) {
|
||||
// Access auth through DI
|
||||
const user = this.authService.user.value
|
||||
if (!user?.pubkey || !user?.prvkey) {
|
||||
throw new Error('Authentication required for messaging')
|
||||
}
|
||||
|
||||
// Use authenticated user data
|
||||
const encrypted = await nip04.encrypt(user.prvkey, recipientPubkey, content)
|
||||
// ... rest of implementation
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The authentication system provides comprehensive error handling:
|
||||
|
||||
1. **Network Errors**: Handled in AuthService with proper error propagation
|
||||
2. **Invalid Credentials**: Clear error messages passed to components
|
||||
3. **Token Expiration**: Automatic logout with cleanup
|
||||
4. **Service Unavailable**: Graceful degradation with retry logic
|
||||
|
||||
## Testing
|
||||
|
||||
The dependency injection architecture makes testing straightforward:
|
||||
|
||||
```typescript
|
||||
// Mock the auth service for testing
|
||||
const mockAuthService = {
|
||||
isAuthenticated: ref(true),
|
||||
currentUser: ref({ id: 'test-user', username: 'test' }),
|
||||
login: vi.fn(),
|
||||
logout: vi.fn()
|
||||
}
|
||||
|
||||
// Inject mock in tests
|
||||
container.provide(SERVICE_TOKENS.AUTH_SERVICE, mockAuthService)
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Token Storage**: Secure storage in localStorage with automatic cleanup
|
||||
2. **API Integration**: All requests authenticated via LNBits tokens
|
||||
3. **State Management**: Reactive state prevents stale authentication data
|
||||
4. **Service Isolation**: Authentication logic isolated in dedicated service
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Token Refresh**: Automatic token refresh before expiration
|
||||
2. **Multi-Factor Authentication**: Support for additional auth factors
|
||||
3. **Session Management**: Enhanced session handling and persistence
|
||||
4. **Audit Logging**: Authentication event logging for security
|
||||
|
|
@ -24,14 +24,15 @@ A Vue component that provides the chat interface with:
|
|||
- Encrypted message exchange
|
||||
- Connection status indicators
|
||||
|
||||
### 2. useNostrChat.ts
|
||||
**Location**: `src/composables/useNostrChat.ts`
|
||||
### 2. ChatService
|
||||
**Location**: `src/modules/chat/services/chat-service.ts`
|
||||
|
||||
A composable that handles:
|
||||
- Nostr relay connections
|
||||
A service-based architecture that handles:
|
||||
- Nostr relay connections via dependency injection
|
||||
- Message encryption/decryption
|
||||
- User authentication with LNBits
|
||||
- User authentication through AuthService
|
||||
- Real-time message subscription
|
||||
- Integration with modular service architecture
|
||||
|
||||
### 3. ChatPage.vue
|
||||
**Location**: `src/pages/ChatPage.vue`
|
||||
|
|
@ -83,9 +84,10 @@ Response:
|
|||
## Features
|
||||
|
||||
### 1. User Integration
|
||||
- Automatically loads peers from LNBits user database
|
||||
- Uses existing `pubkey` and `prvkey` fields
|
||||
- Admin-only access to private keys for messaging
|
||||
- Automatically loads peers from LNBits user database via dependency injection
|
||||
- Uses existing `pubkey` and `prvkey` fields from AuthService
|
||||
- Authentication managed through centralized AuthService
|
||||
- No dual authentication issues - single source of truth
|
||||
|
||||
### 2. Nostr Relay Integration
|
||||
- Connects to multiple Nostr relays for redundancy
|
||||
|
|
|
|||
|
|
@ -78,11 +78,74 @@ The application uses the following LNBits API endpoints:
|
|||
- Route protection for authenticated pages
|
||||
- Secure logout with token cleanup
|
||||
|
||||
## Migration from Nostr
|
||||
## Architecture
|
||||
|
||||
The following components have been removed or replaced:
|
||||
The authentication system uses a **dependency injection pattern** for clean modular architecture:
|
||||
|
||||
- `useIdentity.ts` → `useAuth.ts`
|
||||
### Core Components
|
||||
|
||||
1. **AuthService** (`src/modules/base/auth/auth-service.ts`)
|
||||
- Singleton service that manages authentication state
|
||||
- Handles API calls to LNBits
|
||||
- Provides reactive state management
|
||||
|
||||
2. **useAuthService** (`src/composables/useAuthService.ts`)
|
||||
- Wrapper composable that provides unified access to AuthService
|
||||
- Uses dependency injection to access the service
|
||||
- Provides consistent API for all components
|
||||
|
||||
3. **Dependency Injection Container** (`src/core/di-container.ts`)
|
||||
- Manages service registration and injection
|
||||
- Ensures single source of truth across modules
|
||||
|
||||
### Usage Pattern
|
||||
|
||||
Components access authentication through the `useAuth()` composable:
|
||||
|
||||
```typescript
|
||||
import { useAuth } from '@/composables/useAuthService'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const auth = useAuth()
|
||||
|
||||
// Access authentication state
|
||||
const isAuthenticated = auth.isAuthenticated
|
||||
const currentUser = auth.currentUser
|
||||
|
||||
// Call authentication methods
|
||||
const login = (credentials) => auth.login(credentials)
|
||||
const logout = () => auth.logout()
|
||||
|
||||
return {
|
||||
isAuthenticated,
|
||||
currentUser,
|
||||
login,
|
||||
logout
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Service Registration
|
||||
|
||||
The AuthService is registered in the base module and made available through dependency injection:
|
||||
|
||||
```typescript
|
||||
// In base module
|
||||
container.provide(SERVICE_TOKENS.AUTH_SERVICE, authService)
|
||||
|
||||
// In components
|
||||
const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE)
|
||||
```
|
||||
|
||||
## Migration from Legacy Architecture
|
||||
|
||||
The following components have been updated:
|
||||
|
||||
- **Legacy**: Global `useAuth.ts` composable → **Current**: `useAuthService.ts` with dependency injection
|
||||
- **Legacy**: Direct service imports → **Current**: Dependency injection pattern
|
||||
- **Legacy**: Dual authentication detection → **Current**: Single source of truth via AuthService
|
||||
- `IdentityDialog.vue` → `LoginDialog.vue`
|
||||
- `PasswordDialog.vue` → Integrated into `LoginDialog.vue`
|
||||
- Nostr connection status → User authentication status
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue