invite method
Creates an invitation. The app links its own records, such as a contact, to it by the id in the returned link.
publicDetails travel in the preview, so anyone holding the link reads
them; anything private belongs in content, which is encrypted and
fixed here. With contentOutOfBand the encrypted content is returned
for the app to send alongside the link rather than published in the
preview. expiresIn must be at least a millisecond.
Implementation
Future<CreatedInvitation> invite({
Map<String, dynamic> publicDetails = const {},
Map<String, dynamic>? content,
bool contentOutOfBand = false,
Duration expiresIn = const Duration(days: 7),
}) async {
// NOTE: a preview ttl of 0 would never expire.
if (expiresIn.inMilliseconds < 1) {
throw ArgumentError.value(
expiresIn, 'expiresIn', 'must be at least a millisecond');
}
final id = _randomHex(16);
final code = _randomCode();
final expiresAt = DateTime.now().toUtc().add(expiresIn);
InvitationKey? contentKey;
SealedInvitationContent? sealed;
if (content != null) {
contentKey = InvitationKey.mint();
sealed = await contentKey.seal(jsonEncode(content),
inviter: me, invitationId: id);
}
await (await sentInvitations).create(
id: id,
obj: SentInvitation(
code: code,
expiresAt: expiresAt,
publicDetails: publicDetails,
contentKey: contentKey?.base64,
),
expiresAt: expiresAt.add(_afterExpiry),
);
final preview = InvitationPreview(
publicDetails: publicDetails,
expiresAt: expiresAt,
content: contentOutOfBand ? null : sealed,
);
final previewKey = _previewKey(me, id);
previewKey.metadata.ttl = expiresIn.inMilliseconds;
await atClient.put(
previewKey,
jsonEncode(preview.toJson()),
putRequestOptions: PutRequestOptions()..useRemoteAtServer = true,
);
return CreatedInvitation(
link: InvitationLink(inviter: me, id: id),
code: code,
outOfBandContent: contentOutOfBand ? sealed : null,
);
}