private async Task <int> OnExecute(IConsole console, DatabaseContext database, ConfirmationMailService mailingService) { if (!MailUtilities.IsValidAddress(AccountName)) { console.Error.WriteLine("Please use a valid email address!"); return(1); } console.Out.WriteLine("WARNING: Argon2 hash is currently not supported!"); (var account, var confirmation, bool success) = await database.AddAccount(AccountName, Array.Empty <byte>()).ConfigureAwait(false); if (success) { console.Out.WriteLine($"Created account with ID {account.AccountId}"); console.Out.WriteLine($"Visit {mailingService.GetConfirmationUrl(confirmation.Token)} to confirm the mail address"); if (SendMail) { console.Out.WriteLine("Sending confirmation mail..."); await mailingService.SendMailAsync(AccountName, confirmation.Token).ConfigureAwait(false); } return(0); } else { console.Error.WriteLine($"The AccountName {AccountName} already exists!"); return(1); } }
public override async ValueTask Handle(P02CreateAccount packet) { var response = Packets.New <P03CreateAccountResponse>(); if (!MailUtilities.IsValidAddress(packet.AccountName)) { response.StatusCode = CreateAccountStatus.InvalidAccountName; } else { using var csp = SHA256.Create(); byte[] passwordHash = csp.ComputeHash(packet.KeyHash); // As of RFC 5321 the local-part of an email address should not be case-sensitive. (var newAccount, var confirmation, bool success) = await Database.AddAccount(packet.AccountName.ToLowerInvariant(), passwordHash).ConfigureAwait(false); if (!success) { response.StatusCode = CreateAccountStatus.AccountNameTaken; } else { Task mail = mailing.SendMailAsync(confirmation.MailAddress, confirmation.Token); Channel loopback = await Database.AddChannel( new Channel { ChannelType = ChannelType.Loopback, OwnerId = newAccount.AccountId }, new ChannelMember { AccountId = newAccount.AccountId }) .ConfigureAwait(false); Channel accountData = await Database.AddChannel( new Channel { ChannelType = ChannelType.AccountData, OwnerId = newAccount.AccountId }, new ChannelMember { AccountId = newAccount.AccountId }) .ConfigureAwait(false); // Create password update packet var passwordUpdate = Packets.New <P15PasswordUpdate>(); passwordUpdate.KeyHash = packet.KeyHash; passwordUpdate.MessageFlags = MessageFlags.Loopback | MessageFlags.Unencrypted; _ = await injector.CreateMessage(passwordUpdate, loopback.ChannelId, newAccount.AccountId).ConfigureAwait(false); // Create email address var mailAddress = Packets.New <P14MailAddress>(); mailAddress.MailAddress = await Database.MailConfirmations.AsQueryable() .Where(c => c.AccountId == newAccount.AccountId) .Select(c => c.MailAddress).SingleAsync().ConfigureAwait(false); mailAddress.MessageFlags = MessageFlags.Unencrypted; _ = await injector.CreateMessage(mailAddress, accountData.ChannelId, newAccount.AccountId).ConfigureAwait(false); // As newly created account do not have sessions or contacts there is no need to deliver these packets immediately await mail.ConfigureAwait(false); response.StatusCode = CreateAccountStatus.Success; } } await Client.Send(response).ConfigureAwait(false); }