Files
focusflow_api/lib/src/modules/auth/auth_routes.dart
Oracle Public Cloud User 8958455a12 Initial scaffold: FocusFlow ADHD Task Manager backend
Dart Shelf API with modules: auth (JWT + PBKDF2), tasks (CRUD + dopamine scorer),
streaks (forgiveness + freeze), rewards (variable reward engine), time perception,
sync (offline-first push/pull), rooms (body doubling placeholder).
Includes DB migration (001_initial_schema.sql) and Docker Compose.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 15:53:40 +00:00

104 lines
3.2 KiB
Dart

import 'dart:convert';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';
import '../../middleware/error_handler.dart';
import '../../shared/api_response.dart';
import 'auth_service.dart';
/// Auth module routes: register, login, refresh, logout, delete account.
class AuthRoutes {
final AuthService _authService;
AuthRoutes(this._authService);
Router get router {
final router = Router();
router.post('/register', _register);
router.post('/login', _login);
router.post('/refresh', _refresh);
router.post('/logout', _logout);
router.delete('/account', _deleteAccount);
return router;
}
// ── Handlers ────────────────────────────────────────────────────────
Future<Response> _register(Request request) async {
final body = jsonDecode(await request.readAsString()) as Map<String, dynamic>;
final email = body['email'] as String?;
final password = body['password'] as String?;
final displayName = body['display_name'] as String?;
if (email == null || password == null || displayName == null) {
throw ApiException.badRequest(
'Missing required fields: email, password, display_name',
);
}
if (password.length < 8) {
throw ApiException.badRequest('Password must be at least 8 characters');
}
final tokens = await _authService.register(
email: email,
password: password,
displayName: displayName,
);
return ApiResponse.created(tokens, message: 'Account created');
}
Future<Response> _login(Request request) async {
final body = jsonDecode(await request.readAsString()) as Map<String, dynamic>;
final email = body['email'] as String?;
final password = body['password'] as String?;
if (email == null || password == null) {
throw ApiException.badRequest('Missing required fields: email, password');
}
final tokens = await _authService.login(
email: email,
password: password,
);
return ApiResponse.success(tokens, message: 'Login successful');
}
Future<Response> _refresh(Request request) async {
final body = jsonDecode(await request.readAsString()) as Map<String, dynamic>;
final refreshToken = body['refresh_token'] as String?;
if (refreshToken == null) {
throw ApiException.badRequest('Missing required field: refresh_token');
}
final tokens = await _authService.refresh(refreshToken);
return ApiResponse.success(tokens);
}
Future<Response> _logout(Request request) async {
final body = jsonDecode(await request.readAsString()) as Map<String, dynamic>;
final refreshToken = body['refresh_token'] as String?;
if (refreshToken == null) {
throw ApiException.badRequest('Missing required field: refresh_token');
}
await _authService.logout(refreshToken);
return ApiResponse.success(null, message: 'Logged out successfully');
}
Future<Response> _deleteAccount(Request request) async {
final userId = request.context['userId'] as String;
await _authService.deleteAccount(userId);
return ApiResponse.success(null, message: 'Account deleted');
}
}