Beispiel #1
0
        /// <summary>
        /// Resends an activation link for a user; expects a user_created email template and a valid user identifier
        /// </summary>
        /// <param name="context"></param>
        /// <param name="userId"></param>
        /// <param name="ea"></param>
        /// <param name="emailTpl"></param>
        /// <returns></returns>
        public static async Task ResendActivationLink(DbContext context, Guid userId, IEmailAccount ea = null, IEmailTemplate emailTpl = null)
        {
            //Note: MBR seems to not like resending an activation link with a new password... It simply does not generate a new one but rather regenerates the verification key
            //because of that need to fake an account creation with some random email and then grab some auto generated data out of it
            //
            //basically a new account is created in order to get a new token and a new pass and verification key with its creation date
            //such user account is then destroyed but the necessary details are set on the account that we try to resend a link for.



            if (userId == default(Guid))
            {
                throw new InvalidOperationException("You cannot resend an activation link - this user has not yet been created...");
            }


            var mbrCtx = new CustomDbContext("MapHiveMbr");

            //get the mbr user object
            var mbrUser = await mbrCtx.Users.FirstOrDefaultAsync(u => u.ID == userId);

            if (mbrUser == null)
            {
                throw new InvalidOperationException("User does not exist in MBR.");
            }


            //need user account service to properly create a MBR user
            var userAccountService = CustomUserAccountService.GetInstance("MapHiveMbr");

            //wire up an evt listener - this is the way mbr talks
            AccountCreatedEvent <CustomUserAccount> e = null;

            userAccountService.Configuration.AddEventHandler(
                new MembershipRebootEventHandlers.AccountCreatedEventHandler <CustomUserAccount>(evt => e = evt));

            //rrnd email - after all need to avoid scenarios when two folks try the same resend activation procedure at once
            var rndEmail = $"{DateTime.Now.Ticks}@somedomain.com";

            //finally a new rnd user, so we can get a properly recreated verification key and a new pass...
            var newMbrAccount = userAccountService.CreateAccount(rndEmail, Cartomatic.Utils.Crypto.Generator.GenerateRandomString(10), rndEmail);

            //update the account in question with
            //mbrUser.VerificationKey = newMbrAccount.VerificationKey;
            //mbrUser.VerificationPurpose = newMbrAccount.VerificationPurpose;
            //mbrUser.HashedPassword = newMbrAccount.HashedPassword;
            //mbrUser.VerificationKeySent = newMbrAccount.VerificationKeySent
            //because the properties are read only, we need to do some crazy hocus-pocus again

            //note: looks like the type returned via mbrCtx.Users.FirstOrDefaultAsync is somewhat more dynamic and does not
            //map properly. therefore need to use a 'barebone' object instance
            var obj = new CustomUserAccount();


            //Warning - this sql is postgresql specific!
            var updateSql = $@"UPDATE
    {mbrCtx.GetTableSchema(obj)}.""{mbrCtx.GetTableName(obj)}""
SET
    ""{mbrCtx.GetTableColumnName(obj, nameof(mbrUser.VerificationKey))}"" = '{newMbrAccount.VerificationKey}',
    ""{mbrCtx.GetTableColumnName(obj, nameof(mbrUser.VerificationPurpose))}"" = {(int)newMbrAccount.VerificationPurpose},
    ""{mbrCtx.GetTableColumnName(obj, nameof(mbrUser.HashedPassword))}"" = '{newMbrAccount.HashedPassword}',
    ""{mbrCtx.GetTableColumnName(obj, nameof(mbrUser.VerificationKeySent))}"" = '{newMbrAccount.VerificationKeySent}'
WHERE
    ""{mbrCtx.GetTableColumnName(obj, nameof(mbrUser.ID))}"" = '{mbrUser.ID}';";

            //get rid of the new account
            mbrCtx.Users.Remove(await mbrCtx.Users.FirstAsync(u => u.ID == newMbrAccount.ID));

            //and save da mess
            await mbrCtx.SaveChangesAsync();

            await mbrCtx.Database.ExecuteSqlCommandAsync(updateSql);

            //send out the email
            if (emailTpl != null && ea != null)
            {
                MapHive.Server.Core.Email.EmailSender.Send(
                    ea,
                    emailTpl.Prepare(new Dictionary <string, object>
                {
                    { nameof(e.VerificationKey), e.VerificationKey },
                    { nameof(e.InitialPassword), e.InitialPassword }
                }),
                    mbrUser.Email
                    );
            }
        }