createThread method

JsonMap createThread(
  1. String principalId,
  2. String channelId,
  3. JsonMap body
)

Creates a forum post of principalId in channelId from a ThreadCreate body: the thread, thread.created, then its first message through createMessage; returns the API ThreadCreated.

Throws FakeProblem: 404 for a channel the principal does not see, 403 forbidden below write, 400 validation_failed for a forum post without first_message (required_for_forum_post, as the server of M1-56), without a title, with a tag that is not a tag of the forum, and for a thread from a message (parent_message_id), which the fake does not model.

Implementation

JsonMap createThread(String principalId, String channelId, JsonMap body) {
  final channel = channels[channelId];
  if (channel == null || !seesChannel(principalId, channelId)) {
    throw const FakeProblem(404, 'not_found');
  }
  if (channel.access[principalId] == 'read') {
    throw const FakeProblem(403, 'forbidden');
  }
  FakeProblem invalid(String pointer, String code) => FakeProblem(
    400,
    'validation_failed',
    errors: [
      {'pointer': pointer, 'code': code},
    ],
  );
  if (channel.json['kind'] != 'forum' || body['parent_message_id'] != null) {
    throw invalid('/parent_message_id', 'not_supported_by_fake');
  }
  final first = body['first_message'] as JsonMap?;
  if (first == null) {
    throw invalid('/first_message', 'required_for_forum_post');
  }
  final title = (body['title'] as String?)?.trim() ?? '';
  if (title.isEmpty) throw invalid('/title', 'required');
  final tagIds = [...?(body['tag_ids'] as List<Object?>?)?.cast<String>()];
  for (final tag in tagIds) {
    if (forumTags[tag]?['channel_id'] != channelId) {
      throw invalid('/tag_ids', 'unknown_tag');
    }
  }
  final id = addThread(channelId, title, createdBy: principalId);
  final thread = threads[id]!..['tag_ids'] = tagIds;
  append(
    'thread.created',
    resource: {'kind': 'thread', 'id': id, 'version': thread['version']},
    scope: _scopeOf(id),
    payload: {'thread': thread},
    actor: principalId,
  );
  final message = createMessage(principalId, id, first).message;
  return {'thread': thread, 'first_message': message};
}