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>
This commit is contained in:
103
lib/src/modules/auth/auth_routes.dart
Normal file
103
lib/src/modules/auth/auth_routes.dart
Normal file
@@ -0,0 +1,103 @@
|
||||
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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user