Skip to content

Commit

Permalink
potential DoS fix for notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
videah committed Jan 16, 2024
1 parent 6e5476a commit ebfa480
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
4 changes: 3 additions & 1 deletion lib/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ String stringifyModifiedUri(Uri uri, String originalUri) {
return host + uri.toString().substring(host.length);
}

/// Generates pagination headers for a Mastodon feed like a timeline or
/// notifications.
Map<String, String> generatePaginationHeaders<T>({
required List<T> items,
required Uri requestUri,
Expand All @@ -272,5 +274,5 @@ Map<String, String> generatePaginationHeaders<T>({
final prevURI = requestUri.replace(queryParameters: {'min_id': highestID.toString()});
final nextURI = requestUri.replace(queryParameters: {'cursor': nextCursor});

return {'Link': '<$prevURI>; rel="prev", <$nextURI>; rel="next"'};
return {'Link': '<$nextURI>; rel="next", <$prevURI>; rel="prev"'};
}
6 changes: 6 additions & 0 deletions routes/api/v1/notifications/index.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ Future<Response> onRequest<T>(RequestContext context) async {
bluesky,
);

// If we have a min_id, filter out any notifications that are older than it.
if (encodedParams.minId != null) {
final minId = BigInt.parse(encodedParams.minId!);
notifs.removeWhere((notif) => BigInt.parse(notif.id) <= minId);
}

var headers = <String, String>{};
if (notifs.isNotEmpty) {
headers = generatePaginationHeaders(
Expand Down
9 changes: 0 additions & 9 deletions routes/api/v1/timelines/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,6 @@ Future<Response> onRequest(RequestContext context) async {
nextCursor: nextCursor ?? '',
getId: (post) => BigInt.parse(post.id),
);

// final ids = processedPosts.map((post) => BigInt.parse(post.id)).toList();
// final highestID = ids.reduce((a, b) => a > b ? a : b);
//
// final prevParams = {'min_id': highestID.toString()};
// final nextParams = {'cursor': nextCursor};
// final prevURI = uri.replace(queryParameters: prevParams);
// final nextURI = uri.replace(queryParameters: nextParams);
// headers['Link'] = '<$prevURI>; rel="prev", <$nextURI>; rel="next"';
}

// If the user prefers not to see replies, we need to filter them out.
Expand Down
18 changes: 17 additions & 1 deletion routes/api/v1/timelines/list/[id].dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:dart_frog/dart_frog.dart';
import 'package:sky_bridge/auth.dart';
import 'package:sky_bridge/database.dart';
import 'package:sky_bridge/models/mastodon/mastodon_post.dart';
import 'package:sky_bridge/models/params/timeline_params.dart';
import 'package:sky_bridge/src/generated/prisma/prisma_client.dart';
import 'package:sky_bridge/util.dart';

Expand All @@ -22,6 +23,11 @@ Future<Response> onRequest<T>(RequestContext context, String id) async {
return Response(statusCode: HttpStatus.notFound);
}

// Get the next cursor from the request parameters.
final params = context.request.uri.queryParameters;
final encodedParams = TimelineParams.fromJson(params);
final nextCursor = encodedParams.cursor;

// Construct bluesky connection.
// Get a bluesky connection/session from the a provided bearer token.
// If the token is invalid, bail out and return an error.
Expand Down Expand Up @@ -49,8 +55,18 @@ Future<Response> onRequest<T>(RequestContext context, String id) async {
// Get the parent posts for each post.
final processedPosts = await processParentPosts(bluesky, posts);

// Return the post that we just liked.
var headers = <String, String>{};
if (processedPosts.isNotEmpty) {
headers = generatePaginationHeaders(
items: processedPosts,
requestUri: context.request.uri,
nextCursor: nextCursor ?? '',
getId: (post) => BigInt.parse(post.id),
);
}

return threadedJsonResponse(
body: processedPosts,
headers: headers,
);
}

0 comments on commit ebfa480

Please sign in to comment.