- User model with Ed25519 keypair identity - Register/login on home server (creates keypair) - Join guest servers with signature verification - Public endpoints for cross-server identity - Channel and message CRUD - JWT authentication middleware Architecture: Home server model, no federation, client-driven sync
87 lines
2.8 KiB
Dart
87 lines
2.8 KiB
Dart
import 'package:chat_server/models.dart';
|
|
import 'package:chat_server/objectbox.g.dart';
|
|
import 'package:hotreloader/hotreloader.dart';
|
|
import 'package:relic/relic.dart';
|
|
|
|
import 'config/config.dart';
|
|
import 'src/auth/auth_middleware.dart';
|
|
import 'src/handlers/auth_handlers.dart';
|
|
import 'src/handlers/channel_handlers.dart';
|
|
import 'src/handlers/message_handlers.dart';
|
|
import 'src/handlers/public_handlers.dart';
|
|
import 'src/utils/extensions.dart';
|
|
|
|
// Global ObjectBox store and boxes
|
|
late final Store store;
|
|
late final Box<User> userBox;
|
|
late final Box<Channel> channelBox;
|
|
late final Box<Message> messageBox;
|
|
|
|
RelicApp? _currentApp;
|
|
|
|
Future<void> startServer() async {
|
|
await _currentApp?.close();
|
|
|
|
_currentApp = RelicApp()
|
|
// ============ PUBLIC ENDPOINTS (no auth) ============
|
|
|
|
// Auth
|
|
..post('/auth/register', registerHandler)
|
|
..post('/auth/login', loginHandler)
|
|
..post('/auth/join', joinServerHandler)
|
|
|
|
// Public identity verification (for cross-server)
|
|
..get('/.well-known/users/<username>', publicUserHandler)
|
|
..get('/.well-known/verify/<userId>', publicVerifyHandler)
|
|
..get('/.well-known/server', publicServerInfoHandler)
|
|
|
|
// ============ PROTECTED ENDPOINTS (requires auth) ============
|
|
..use('/api', jwtMiddleware)
|
|
|
|
// Current user
|
|
..get('/api/me', getMeHandler)
|
|
|
|
// Channels
|
|
..get('/api/channels', getChannelsHandler)
|
|
..post('/api/channels', createChannelHandler)
|
|
..get('/api/channels/<channelId>', getChannelHandler)
|
|
|
|
// Messages
|
|
..get('/api/messages', getMessagesHandler)
|
|
..post('/api/messages', sendMessageHandler)
|
|
..put('/api/messages/<messageId>', editMessageHandler)
|
|
..delete('/api/messages/<messageId>', deleteMessageHandler)
|
|
|
|
// ============ LOGGING & FALLBACK ============
|
|
..use('/', logRequests())
|
|
..fallback = respondWith((_) => Response.notFound());
|
|
|
|
print('');
|
|
print('╔════════════════════════════════════════════╗');
|
|
print('║ 🚀 Server starting... ║');
|
|
print('║ Host: ${Config.serverHost.padRight(34)}║');
|
|
print('║ URL: http://localhost:${Config.port.toString().padRight(26)}║');
|
|
print('╚════════════════════════════════════════════╝');
|
|
print('');
|
|
|
|
await _currentApp!.serve(port: Config.port);
|
|
}
|
|
|
|
void main() async {
|
|
// Initialize ObjectBox
|
|
store = openStore();
|
|
userBox = store.box<User>();
|
|
channelBox = store.box<Channel>();
|
|
messageBox = store.box<Message>();
|
|
|
|
// Enable hot reload in development
|
|
await HotReloader.create(
|
|
onAfterReload: (ctx) async {
|
|
print('🔄 Changes detected! Restarting server...');
|
|
await startServer();
|
|
},
|
|
);
|
|
|
|
await startServer();
|
|
}
|