createThread method
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};
}