Files
chat-server/lib/server.dart
T

106 lines
3.5 KiB
Dart

import 'dart:io';
import 'package:relic/relic.dart';
import 'config/config.dart';
import 'src/auth/auth_middleware.dart';
import 'src/gateway/gateway_handlers.dart';
import 'src/handlers/auth_handlers.dart';
import 'src/handlers/channel_handlers.dart';
import 'src/handlers/dev_db_handlers.dart';
import 'src/handlers/message_handlers.dart';
import 'src/handlers/public_handlers.dart';
import 'src/handlers/settings_handlers.dart';
import 'src/handlers/upload_handlers.dart';
import 'src/state/app_state.dart';
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)
..get('/uploads/:fileName', getUploadFileHandler)
..get('/attachments/:attachmentId', getAttachmentHandler)
..get('/avatars/:userId', getAvatarAliasHandler)
..get('/icons/:serverId', getServerIconAliasHandler)
..get('/banners/:serverId', getServerBannerAliasHandler)
..get('/gateway', gatewayHandler)
// ============ PROTECTED ENDPOINTS (requires auth) ============
..use('/api', jwtMiddleware)
// Current user
..get('/api/me', getMeHandler)
..patch('/api/me', updateProfileHandler)
..put('/api/me/avatar', setAvatarHandler)
// Server settings
..get('/api/server/settings', getServerSettingsHandler)
..patch('/api/server/settings', patchServerSettingsHandler)
..put('/api/server/icon', setServerIconHandler)
..put('/api/server/banner', setServerBannerHandler)
// Dev DB tools (testing only, admin only, requires config flag)
..get('/api/dev/db/snapshot', getDevDbSnapshotHandler)
..post('/api/dev/db/reset', resetDevDbHandler)
..post('/api/dev/users/promote-admin', promoteUserToAdminHandler)
..post('/api/dev/users/demote-admin', demoteUserFromAdminHandler)
// Channels
..get('/api/channels', getChannelsHandler)
..post('/api/channels', createChannelHandler)
..get('/api/channels/:channelId', getChannelHandler)
// Messages
..get('/api/messages', getMessagesHandler)
..get('/api/channels/:channelId/media', getChannelMediaHandler)
..post('/api/uploads/init', initUploadHandler)
..put('/api/uploads/:uploadId', completeUploadHandler)
..post('/api/uploads', uploadFileHandler)
..post('/api/messages', sendMessageHandler)
..put('/api/messages/:messageId', editMessageHandler)
..delete('/api/messages/:messageId', deleteMessageHandler)
// ============ LOGGING & FALLBACK ============
..use('/', logRequests())
..fallback = respondWith((_) => Response.notFound());
print('');
print('🚀 Server starting...');
print('Bind: ${'${Config.bindHost}:${Config.bindPort}'.padRight(34)}');
print('Public URL: ${Config.publicBaseUrl.padRight(26)}');
print('');
final bindAddress = InternetAddress.tryParse(Config.bindHost) ?? (await InternetAddress.lookup(Config.bindHost)).first;
await _currentApp!.serve(
address: bindAddress,
port: Config.bindPort,
);
}
Future<void> stopServer() async {
await _currentApp?.close();
_currentApp = null;
}
void main() async {
Config.initialize();
initializeStore();
await startServer();
}