cyberhybridhub/server/lib/handlers/profile_handler.dart
2026-05-20 10:22:58 -05:00

83 lines
2.4 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:shelf/shelf.dart';
import '../db.dart';
import '../firebase_auth.dart';
Handler profileHandler({
required ProfileDb db,
required FirebaseAuthVerifier auth,
}) {
return (Request request) async {
if (request.method == 'OPTIONS') {
return Response.ok('', headers: _corsHeaders);
}
final String? firebaseUid = await auth.verifyBearerToken(
request.headers['Authorization'] ?? request.headers['authorization'],
);
if (firebaseUid == null) {
return _jsonResponse(401, <String, dynamic>{'error': 'Unauthorized'});
}
if (request.requestedUri.path != '/v1/me/profile') {
return _jsonResponse(404, <String, dynamic>{'error': 'Not found'});
}
try {
if (request.method == 'GET') {
final Map<String, dynamic>? profile = await db.getProfile(firebaseUid);
if (profile == null) {
return _jsonResponse(404, <String, dynamic>{'error': 'Not found'});
}
return _jsonResponse(200, profile);
}
if (request.method == 'PUT') {
final String body = await request.readAsString();
final Map<String, dynamic> json =
jsonDecode(body) as Map<String, dynamic>;
final int revision = (json['revision'] as num?)?.toInt() ?? 1;
try {
final Map<String, dynamic> saved = await db.upsertProfile(
firebaseUid: firebaseUid,
body: json,
clientRevision: revision,
);
return _jsonResponse(200, saved);
} on StaleRevisionException catch (e) {
return _jsonResponse(409, <String, dynamic>{
'error': 'Conflict',
'profile': e.serverProfile,
});
}
}
return _jsonResponse(405, <String, dynamic>{'error': 'Method not allowed'});
} catch (e, st) {
stderr.writeln('Profile handler error: $e\n$st');
return _jsonResponse(500, <String, dynamic>{'error': 'Internal error'});
}
};
}
Map<String, String> get _corsHeaders => <String, String>{
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, PUT, OPTIONS',
'Access-Control-Allow-Headers': 'Authorization, Content-Type',
};
Response _jsonResponse(int status, Map<String, dynamic> body) {
return Response(
status,
body: jsonEncode(body),
headers: <String, String>{
..._corsHeaders,
'Content-Type': 'application/json',
},
);
}