protected void btnLookup_Click(object sender, EventArgs e)
        {
            if (!Page.IsValid)
            {
                return;
            }

            var ipLimit         = GetAttributeValue(AttributeKey.IpThrottleLimit).AsInteger();
            var messageTemplate = GetAttributeValue(AttributeKey.TextMessageTemplate);
            var fromNumber      = GetAttributeValue(AttributeKey.SmsNumber);
            var phoneNumber     = pbPhoneNumberLookup.Number;

            try
            {
                using (var rockContext = new RockContext())
                {
                    var identityVerificationService = new IdentityVerificationService(rockContext);

                    var identityVerification = identityVerificationService.CreateIdentityVerificationRecord(Request.UserHostAddress, ipLimit, phoneNumber);

                    var smsMessage = new RockSMSMessage
                    {
                        FromNumber = DefinedValueCache.Get(fromNumber),
                        Message    = messageTemplate,
                    };
                    var mergeObjects = LavaHelper.GetCommonMergeFields(this.RockPage);
                    mergeObjects.Add("ConfirmationCode", identityVerification.IdentityVerificationCode.Code);

                    smsMessage.SetRecipients(new List <RockSMSMessageRecipient> {
                        RockSMSMessageRecipient.CreateAnonymous(phoneNumber, mergeObjects)
                    });

                    var errorList = new List <string>();
                    if (smsMessage.Send(out errorList))
                    {
                        IdentityVerificationId = identityVerification.Id;
                        ShowVerificationPage();
                    }
                    else
                    {
                        ShowWarningMessage("Verification text message failed to send.");
                    }
                }
            }
            catch (Exception ex)
            {
                ShowWarningMessage(ex.Message);
                RockLogger.Log.Error(RockLogDomains.Core, ex);
                ExceptionLogService.LogException(ex);
            }
        }
Exemple #2
0
        /// <summary>
        /// Sends an RSVP reminder email to an individual attendee.
        /// </summary>
        /// <param name="person">The <see cref="Person"/>.</param>
        /// <param name="reminder">The <see cref="SystemCommunication"/> to be sent as a reminder.</param>
        /// <param name="lavaMergeFields">A dictionary containing Lava merge fields.</param>
        /// <param name="smsNumber">The correctly formatted SMS Number for SMS communications.</param>
        /// <returns>1 if the communication was successfully sent, otherwise 0.</returns>
        private int SendReminderSMS(Person person, SystemCommunication reminder, Dictionary <string, object> lavaMergeFields, string smsNumber)
        {
            var recipient = new RockSMSMessageRecipient(person, smsNumber, lavaMergeFields);
            var message   = new RockSMSMessage(reminder);

            message.SetRecipients(new List <RockSMSMessageRecipient>()
            {
                recipient
            });
            message.Send(out List <string> smsErrors);

            if (!smsErrors.Any())
            {
                return(1); // No error, this should be counted as a sent reminder.
            }

            return(0);
        }
Exemple #3
0
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute(RockContext rockContext, WorkflowAction action, object entity, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var mergeFields = GetMergeFields(action);

            // Get the From value
            int? fromId   = null;
            Guid?fromGuid = GetAttributeValue(action, AttributeKey.FromFromDropDown).AsGuidOrNull();

            if (fromGuid.HasValue)
            {
                var fromValue = DefinedValueCache.Get(fromGuid.Value, rockContext);
                if (fromValue != null)
                {
                    fromId = fromValue.Id;
                }
            }

            if (!fromId.HasValue)
            {
                Guid fromGuidFromAttribute = GetAttributeValue(action, AttributeKey.FromFromAttribute).AsGuid();

                fromGuid = action.GetWorkflowAttributeValue(fromGuidFromAttribute).AsGuidOrNull();

                var fromValue = DefinedValueCache.Get(fromGuid.Value, rockContext);
                if (fromValue != null)
                {
                    fromId = fromValue.Id;
                }
            }

            var smsFromDefinedValues = DefinedTypeCache.Get(SystemGuid.DefinedType.COMMUNICATION_SMS_FROM.AsGuid()).DefinedValues;

            // Now can we do our final check to ensure the guid is a valid SMS From Defined Value
            if (!fromId.HasValue || !smsFromDefinedValues.Any(a => a.Id == fromId))
            {
                var msg = string.Format($"'From' could not be found for selected value ('{fromGuid}')");
                errorMessages.Add(msg);
                action.AddLogEntry(msg, true);
                return(false);
            }

            // Get the recipients
            var    recipients = new List <RockSMSMessageRecipient>();
            string toValue    = GetAttributeValue(action, "To");
            Guid   guid       = toValue.AsGuid();

            if (!guid.IsEmpty())
            {
                var attribute = AttributeCache.Get(guid, rockContext);
                if (attribute != null)
                {
                    string toAttributeValue = action.GetWorkflowAttributeValue(guid);
                    if (!string.IsNullOrWhiteSpace(toAttributeValue))
                    {
                        switch (attribute.FieldType.Class)
                        {
                        case "Rock.Field.Types.TextFieldType":
                        {
                            var smsNumber = toAttributeValue;
                            recipients.Add(RockSMSMessageRecipient.CreateAnonymous(smsNumber, mergeFields));
                            break;
                        }

                        case "Rock.Field.Types.PersonFieldType":
                        {
                            Guid personAliasGuid = toAttributeValue.AsGuid();
                            if (!personAliasGuid.IsEmpty())
                            {
                                var phoneNumber = new PersonAliasService(rockContext).Queryable()
                                                  .Where(a => a.Guid.Equals(personAliasGuid))
                                                  .SelectMany(a => a.Person.PhoneNumbers)
                                                  .Where(p => p.IsMessagingEnabled)
                                                  .FirstOrDefault();

                                if (phoneNumber == null)
                                {
                                    action.AddLogEntry("Invalid Recipient: Person or valid SMS phone number not found", true);
                                }
                                else
                                {
                                    var person = new PersonAliasService(rockContext).GetPerson(personAliasGuid);

                                    var recipient = new RockSMSMessageRecipient(person, phoneNumber.ToSmsNumber(), mergeFields);
                                    recipients.Add(recipient);
                                    recipient.MergeFields.Add(recipient.PersonMergeFieldKey, person);
                                }
                            }

                            break;
                        }

                        case "Rock.Field.Types.GroupFieldType":
                        case "Rock.Field.Types.SecurityRoleFieldType":
                        {
                            int? groupId   = toAttributeValue.AsIntegerOrNull();
                            Guid?groupGuid = toAttributeValue.AsGuidOrNull();
                            IQueryable <GroupMember> qry = null;

                            // Handle situations where the attribute value is the ID
                            if (groupId.HasValue)
                            {
                                qry = new GroupMemberService(rockContext).GetByGroupId(groupId.Value);
                            }
                            else if (groupGuid.HasValue)
                            {
                                // Handle situations where the attribute value stored is the Guid
                                qry = new GroupMemberService(rockContext).GetByGroupGuid(groupGuid.Value);
                            }
                            else
                            {
                                action.AddLogEntry("Invalid Recipient: No valid group id or Guid", true);
                            }

                            if (qry != null)
                            {
                                foreach (var person in qry
                                         .Where(m => m.GroupMemberStatus == GroupMemberStatus.Active)
                                         .Select(m => m.Person))
                                {
                                    var phoneNumber = person.PhoneNumbers
                                                      .Where(p => p.IsMessagingEnabled)
                                                      .FirstOrDefault();
                                    if (phoneNumber != null)
                                    {
                                        var recipientMergeFields = new Dictionary <string, object>(mergeFields);
                                        var recipient            = new RockSMSMessageRecipient(person, phoneNumber.ToSmsNumber(), recipientMergeFields);
                                        recipients.Add(recipient);
                                        recipient.MergeFields.Add(recipient.PersonMergeFieldKey, person);
                                    }
                                }
                            }

                            break;
                        }
                        }
                    }
                }
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(toValue))
                {
                    recipients.Add(RockSMSMessageRecipient.CreateAnonymous(toValue.ResolveMergeFields(mergeFields), mergeFields));
                }
            }

            // Get the message from the Message attribute.
            // NOTE: Passing 'true' as the checkWorkflowAttributeValue will also check the workflow AttributeValue
            // which allows us to remove the unneeded code.
            string message = GetAttributeValue(action, "Message", checkWorkflowAttributeValue: true);

            // Add the attachment (if one was specified)
            var        attachmentBinaryFileGuid = GetAttributeValue(action, "Attachment", true).AsGuidOrNull();
            BinaryFile binaryFile = null;

            if (attachmentBinaryFileGuid.HasValue && attachmentBinaryFileGuid != Guid.Empty)
            {
                binaryFile = new BinaryFileService(rockContext).Get(attachmentBinaryFileGuid.Value);
            }

            // Send the message
            if (recipients.Any() && (!string.IsNullOrWhiteSpace(message) || binaryFile != null))
            {
                var smsMessage = new RockSMSMessage();
                smsMessage.SetRecipients(recipients);
                smsMessage.FromNumber = DefinedValueCache.Get(fromId.Value);
                smsMessage.Message    = message;
                smsMessage.CreateCommunicationRecord = GetAttributeValue(action, "SaveCommunicationHistory").AsBoolean();
                smsMessage.CommunicationName         = action.ActionTypeCache.Name;

                if (binaryFile != null)
                {
                    smsMessage.Attachments.Add(binaryFile);
                }

                smsMessage.Send();
            }
            else
            {
                action.AddLogEntry("Warning: No text or attachment was supplied so nothing was sent.", true);
            }

            return(true);
        }
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var mergeFields = GetMergeFields(action);
            // Get the From value. Can be in the form of Text, Phone Number, Person or Defined type
            string fromValue = string.Empty;
            int?   fromId    = null;

            fromValue = GetAttributeValue(action, "From", true);


            if (!string.IsNullOrWhiteSpace(fromValue))
            {
                Guid?fromGuid = fromValue.AsGuidOrNull();

                DefinedTypeCache smsPhoneNumbers = DefinedTypeCache.Get(Rock.SystemGuid.DefinedType.COMMUNICATION_SMS_FROM);

                // If fromGuid is null but fromValue is not, then this is a phone number (match it up with the value from the DefinedType)
                if (fromGuid == null)
                {
                    try
                    {
                        fromValue = PhoneNumber.CleanNumber(fromValue);
                        fromGuid  = smsPhoneNumbers.DefinedValues.Where(dv => dv.Value.Right(10) == fromValue.Right(10)).Select(dv => dv.Guid).FirstOrDefault();
                        if (fromGuid == Guid.Empty)
                        {
                            action.AddLogEntry("Invalid sending number: Person or valid SMS phone number not found", true);
                        }
                    }
                    catch (Exception e)
                    {
                        action.AddLogEntry("Invalid sending number: Person or valid SMS phone number not found", true);
                    }
                }

                // At this point, fromGuid should either be a Person or a DefinedValue

                if (fromGuid.HasValue)
                {
                    fromId = smsPhoneNumbers.DefinedValues.Where(dv => dv.Guid == fromGuid || dv.GetAttributeValue("ResponseRecipient") == fromGuid.ToString()).Select(dv => dv.Id).FirstOrDefault();
                }
            }

            else
            {
                // The From number is required and was not entered
                action.AddLogEntry("Invalid sending number: Person or valid SMS phone number not found", true);
            }

            // Get the recipients, Can be in the form of Text, Phone Number, Person, Group or Security role
            var    recipients = new List <RockSMSMessageRecipient>();
            string toValue    = GetAttributeValue(action, "To");
            Guid   guid       = toValue.AsGuid();

            if (!guid.IsEmpty())
            {
                var attribute = AttributeCache.Get(guid, rockContext);
                if (attribute != null)
                {
                    string toAttributeValue = action.GetWorklowAttributeValue(guid);
                    if (!string.IsNullOrWhiteSpace(toAttributeValue))
                    {
                        switch (attribute.FieldType.Class)
                        {
                        case "Rock.Field.Types.TextFieldType":
                        case "Rock.Field.Types.PhoneNumberFieldType":
                        {
                            var smsNumber = toAttributeValue;
                            smsNumber = PhoneNumber.CleanNumber(smsNumber);
                            recipients.Add(RockSMSMessageRecipient.CreateAnonymous(smsNumber, mergeFields));
                            break;
                        }

                        case "Rock.Field.Types.PersonFieldType":
                        {
                            Guid personAliasGuid = toAttributeValue.AsGuid();
                            if (!personAliasGuid.IsEmpty())
                            {
                                var phoneNumber = new PersonAliasService(rockContext).Queryable()
                                                  .Where(a => a.Guid.Equals(personAliasGuid))
                                                  .SelectMany(a => a.Person.PhoneNumbers)
                                                  .Where(p => p.IsMessagingEnabled)
                                                  .FirstOrDefault();

                                if (phoneNumber == null)
                                {
                                    action.AddLogEntry("Invalid Recipient: Person or valid SMS phone number not found", true);
                                }
                                else
                                {
                                    var person = new PersonAliasService(rockContext).GetPerson(personAliasGuid);

                                    var recipient = new RockSMSMessageRecipient(person, phoneNumber.ToSmsNumber(), mergeFields);
                                    recipients.Add(recipient);
                                    recipient.MergeFields.Add(recipient.PersonMergeFieldKey, person);
                                }
                            }
                            break;
                        }

                        case "Rock.Field.Types.GroupFieldType":
                        case "Rock.Field.Types.SecurityRoleFieldType":
                        {
                            int? groupId   = toAttributeValue.AsIntegerOrNull();
                            Guid?groupGuid = toAttributeValue.AsGuidOrNull();
                            IQueryable <GroupMember> qry = null;

                            // Handle situations where the attribute value is the ID
                            if (groupId.HasValue)
                            {
                                qry = new GroupMemberService(rockContext).GetByGroupId(groupId.Value);
                            }

                            // Handle situations where the attribute value stored is the Guid
                            else if (groupGuid.HasValue)
                            {
                                qry = new GroupMemberService(rockContext).GetByGroupGuid(groupGuid.Value);
                            }
                            else
                            {
                                action.AddLogEntry("Invalid Recipient: No valid group id or Guid", true);
                            }

                            if (qry != null)
                            {
                                foreach (var person in qry
                                         .Where(m => m.GroupMemberStatus == GroupMemberStatus.Active)
                                         .Select(m => m.Person))
                                {
                                    var phoneNumber = person.PhoneNumbers
                                                      .Where(p => p.IsMessagingEnabled)
                                                      .FirstOrDefault();
                                    if (phoneNumber != null)
                                    {
                                        var recipientMergeFields = new Dictionary <string, object>(mergeFields);
                                        var recipient            = new RockSMSMessageRecipient(person, phoneNumber.ToSmsNumber(), recipientMergeFields);
                                        recipients.Add(recipient);
                                        recipient.MergeFields.Add(recipient.PersonMergeFieldKey, person);
                                    }
                                }
                            }
                            break;
                        }
                        }
                    }
                }
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(toValue))
                {
                    recipients.Add(RockSMSMessageRecipient.CreateAnonymous(toValue.ResolveMergeFields(mergeFields), mergeFields));
                }
            }

            // Get the message from the Message attribute.
            // NOTE: Passing 'true' as the checkWorkflowAttributeValue will also check the workflow AttributeValue
            // which allows us to remove the unneeded code.
            string message = GetAttributeValue(action, "Message", checkWorkflowAttributeValue: true);

            // Add the attachment (if one was specified)
            var        attachmentBinaryFileGuid = GetAttributeValue(action, "Attachment", true).AsGuidOrNull();
            BinaryFile binaryFile = null;

            if (attachmentBinaryFileGuid.HasValue && attachmentBinaryFileGuid != Guid.Empty)
            {
                binaryFile = new BinaryFileService(rockContext).Get(attachmentBinaryFileGuid.Value);
            }

            // Send the message
            if (recipients.Any() && (!string.IsNullOrWhiteSpace(message) || binaryFile != null))
            {
                var smsMessage = new RockSMSMessage();
                smsMessage.SetRecipients(recipients);
                smsMessage.FromNumber = DefinedValueCache.Get(fromId.Value);
                smsMessage.Message    = message;
                smsMessage.CreateCommunicationRecord = GetAttributeValue(action, "SaveCommunicationHistory").AsBoolean();
                smsMessage.communicationName         = action.ActionTypeCache.Name;

                if (binaryFile != null)
                {
                    smsMessage.Attachments.Add(binaryFile);
                }

                smsMessage.Send();
            }
            else
            {
                action.AddLogEntry("Warning: No text or attachment was supplied so nothing was sent.", true);
            }

            return(true);
        }
Exemple #5
0
        protected void btnGenerate_Click(object sender, EventArgs e)
        {
            if (!Page.IsValid)
            {
                return;
            }

            pnlPhoneNumber.Visible = false;
            RockContext        rockContext        = new RockContext();
            PhoneNumberService phoneNumberService = new PhoneNumberService(rockContext);
            var numberOwners = phoneNumberService.Queryable()
                               .Where(pn => pn.Number == PhoneNumber)
                               .Select(pn => pn.Person)
                               .DistinctBy(p => p.Id)
                               .ToList();

            if (numberOwners.Count == 0)
            {
                lbNoNumber.Text     = GetAttributeValue("NoNumberMessage");
                pnlNoNumber.Visible = true;
                return;
            }

            if (numberOwners.Count > 1)
            {
                if (GetAttributeValue("DuplicateNumberPage").AsGuidOrNull() == null)
                {
                    btnResolution.Visible = false;
                }
                lbDuplicateNumber.Text     = GetAttributeValue("DuplicateMessage");
                pnlDuplicateNumber.Visible = true;
                return;
            }

            var person = numberOwners.FirstOrDefault();

            UserLoginService userLoginService = new UserLoginService(rockContext);
            var userLogin = userLoginService.Queryable()
                            .Where(u => u.UserName == ("__PHONENUMBER__" + PhoneNumber))
                            .FirstOrDefault();

            if (userLogin == null)
            {
                var entityTypeId = EntityTypeCache.Get("Avalanche.Security.Authentication.PhoneNumber").Id;

                userLogin = new UserLogin()
                {
                    UserName     = "******" + PhoneNumber,
                    EntityTypeId = entityTypeId,
                };
                userLoginService.Add(userLogin);
            }

            userLogin.PersonId = person.Id;
            userLogin.LastPasswordChangedDateTime = Rock.RockDateTime.Now;
            userLogin.FailedPasswordAttemptWindowStartDateTime = Rock.RockDateTime.Now;
            userLogin.FailedPasswordAttemptCount = 0;
            userLogin.IsConfirmed = true;
            userLogin.Password    = new Random().Next(100000, 999999).ToString();

            rockContext.SaveChanges();

            var recipients = new List <RockMessageRecipient>();

            recipients.Add(RockSMSMessageRecipient.CreateAnonymous(PhoneNumber, null));

            var smsMessage = new RockSMSMessage();

            smsMessage.SetRecipients(recipients);

            // Get the From value
            Guid?fromGuid = GetAttributeValue("From").AsGuidOrNull();

            if (fromGuid.HasValue)
            {
                var fromValue = DefinedValueCache.Get(fromGuid.Value, rockContext);
                if (fromValue != null)
                {
                    smsMessage.FromNumber = DefinedValueCache.Get(fromValue.Id);
                }
            }

            var mergeObjects = new Dictionary <string, object> {
                { "password", userLogin.Password }
            };
            var message = GetAttributeValue("Message").ResolveMergeFields(mergeObjects, null);

            smsMessage.Message = message;

            var ipAddress = GetIpAddress();

            if (SMSRecords.ReserveItems(ipAddress, PhoneNumber))
            {
                pnlCode.Visible = true;
                var delay = SMSRecords.GetDelay(ipAddress, PhoneNumber);
                Task.Run(() => { SendSMS(smsMessage, ipAddress, PhoneNumber, delay); });
            }
            else
            {
                LogException(new Exception(string.Format("Unable to reserve for SMS message: IP: {0} PhoneNumber: {1}", ipAddress, PhoneNumber)));
                pnlRateLimited.Visible = true;
            }
        }
        /// <summary>
        /// Creates the user login for the SMS message and send the text message with the code
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <returns></returns>
        public bool SendSMSAuthentication(string phoneNumber)
        {
            RockContext rockContext = new RockContext();

            string error;
            var    person = GetNumberOwner(phoneNumber, rockContext, out error);

            if (person == null)
            {
                return(false);
            }

            UserLoginService userLoginService = new UserLoginService(rockContext);
            var userLogin = userLoginService.Queryable()
                            .Where(u => u.UserName == ("SMS_" + person.Id.ToString()))
                            .FirstOrDefault();

            //Create user login if does not exist
            if (userLogin == null)
            {
                var entityTypeId = EntityTypeCache.Get("Rock.Security.ExternalAuthentication.SMSAuthentication").Id;

                userLogin = new UserLogin()
                {
                    UserName     = "******" + person.Id.ToString(),
                    EntityTypeId = entityTypeId,
                };
                userLoginService.Add(userLogin);
            }

            //Update user login
            userLogin.PersonId = person.Id;
            userLogin.LastPasswordChangedDateTime = Rock.RockDateTime.Now;
            userLogin.FailedPasswordAttemptWindowStartDateTime = Rock.RockDateTime.Now;
            userLogin.FailedPasswordAttemptCount = 0;
            userLogin.IsConfirmed = true;
            var password = new Random().Next(100000, 999999).ToString();

            userLogin.Password = EncodeBcrypt(password);
            rockContext.SaveChanges();

            var recipients = new List <RockSMSMessageRecipient>();

            recipients.Add(RockSMSMessageRecipient.CreateAnonymous(phoneNumber, null));

            var smsMessage = new RockSMSMessage
            {
                CreateCommunicationRecord = false
            };

            smsMessage.SetRecipients(recipients);

            // Get the From value
            Guid?fromGuid = GetAttributeValue("From").AsGuidOrNull();

            if (fromGuid.HasValue)
            {
                var fromValue = DefinedValueCache.Get(fromGuid.Value, rockContext);
                if (fromValue != null)
                {
                    smsMessage.FromNumber = DefinedValueCache.Get(fromValue.Id, rockContext);
                }
            }

            smsMessage.AdditionalMergeFields = new Dictionary <string, object> {
                { "password", password }
            };

            smsMessage.Message = GetAttributeValue("Message");

            var ipAddress = GetIpAddress();

            //Reserve items rate limits the text messages
            if (SMSRecords.ReserveItems(ipAddress, phoneNumber))
            {
                var delay = SMSRecords.GetDelay(ipAddress, phoneNumber);
                Task.Run(() => { SendSMS(smsMessage, ipAddress, phoneNumber, delay); });
            }
            else
            {
                ExceptionLogService.LogException(new Exception(string.Format("Rate limiting reached for SMS authentication: IP: {0} PhoneNumber: {1}", ipAddress, phoneNumber)));
            }


            return(true);
        }