예제 #1
0
    private static IEnumerable <EmailMessageEntity> CreateEmailMessage(EmailTemplateEntity template, ModifiableEntity?modifiableEntity, ref IEmailModel?model, CultureInfo?cultureInfo = null)
    {
        Entity?entity = null;

        if (template.Model != null)
        {
            if (model == null)
            {
                model = EmailModelLogic.CreateModel(template.Model, modifiableEntity);
            }
            else if (template.Model.ToType() != model.GetType())
            {
                throw new ArgumentException("model should be a {0} instead of {1}".FormatWith(template.Model.FullClassName, model.GetType().FullName));
            }
        }
        else
        {
            entity = modifiableEntity as Entity ?? throw new InvalidOperationException("Model should be an Entity");
        }

        using (template.DisableAuthorization ? ExecutionMode.Global() : null)
        {
            var emailBuilder = new EmailMessageBuilder(template, entity, model, cultureInfo);
            return(emailBuilder.CreateEmailMessageInternal().ToList());
        }
    }
예제 #2
0
        public static void Start(SchemaBuilder sb)
        {
            if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
            {
                sb.Include <ResetPasswordRequestEntity>()
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.RequestDate,
                    e.Code,
                    e.User,
                    e.User.Email
                });

                EmailLogic.AssertStarted(sb);

                EmailModelLogic.RegisterEmailModel <ResetPasswordRequestEmail>(() => new EmailTemplateEntity
                {
                    Messages = CultureInfoLogic.ForEachCulture(culture => new EmailTemplateMessageEmbedded(culture)
                    {
                        Text = "<p>{0}</p>".FormatWith(AuthEmailMessage.YouRecentlyRequestedANewPassword.NiceToString()) +
                               "<p>{0} @[User.UserName]</p>".FormatWith(AuthEmailMessage.YourUsernameIs.NiceToString()) +
                               "<p>{0}</p>".FormatWith(AuthEmailMessage.YouCanResetYourPasswordByFollowingTheLinkBelow.NiceToString()) +
                               "<p><a href=\"@[m:Url]\">@[m:Url]</a></p>",
                        Subject = AuthEmailMessage.ResetPasswordRequestSubject.NiceToString()
                    }).ToMList()
                });
            }
        }
        public static void Start(SchemaBuilder sb)
        {
            if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
            {
                sb.Include <ResetPasswordRequestEntity>()
                .WithQuery(() => e => new
                {
                    Entity = e,
                    e.Id,
                    e.RequestDate,
                    e.Code,
                    e.User,
                    e.User.Email
                });

                EmailLogic.AssertStarted(sb);

                EmailModelLogic.RegisterEmailModel <ResetPasswordRequestEmail>(() => new EmailTemplateEntity
                {
                    DisableAuthorization = true,
                    Messages             = CultureInfoLogic.ForEachCulture(culture => new EmailTemplateMessageEmbedded(culture)
                    {
                        Text = "<p>{0}</p>".FormatWith(AuthEmailMessage.YouRecentlyRequestedANewPassword.NiceToString()) +
                               "<p>{0} @[User.UserName]</p>".FormatWith(AuthEmailMessage.YourUsernameIs.NiceToString()) +
                               "<p>{0}</p>".FormatWith(AuthEmailMessage.YouCanResetYourPasswordByFollowingTheLinkBelow.NiceToString()) +
                               "<p><a href=\"@[m:Url]\">@[m:Url]</a></p>",
                        Subject = AuthEmailMessage.ResetPasswordRequestSubject.NiceToString()
                    }).ToMList()
                });



                new Graph <ResetPasswordRequestEntity> .Execute(ResetPasswordRequestOperation.Execute)
                {
                    CanBeNew      = false,
                    CanBeModified = false,
                    CanExecute    = (e) => e.Lapsed == false ? null : AuthEmailMessage.YourResetPasswordRequestHasExpired.NiceToString(),
                    Execute       = (e, args) =>
                    {
                        string password = args.GetArg <string>();
                        e.Lapsed = true;
                        var user = e.User;

                        var error = UserEntity.OnValidatePassword(password);
                        if (error != null)
                        {
                            throw new ApplicationException(error);
                        }

                        user.PasswordHash = Security.EncodePassword(password);
                        using (AuthLogic.Disable())
                            user.Execute(UserOperation.Save);
                    }
                }

                .Register();
            }
        }
예제 #4
0
    static SqlPreCommand?Schema_Synchronizing_DefaultTemplates(Replacements replacements)
    {
        if (AvoidSynchronizeDefaultTemplates)
        {
            return(null);
        }

        var table = Schema.Current.Table(typeof(EmailTemplateEntity));

        var emailModels = Database.Query <EmailModelEntity>().Where(se => !se.EmailTemplates().Any()).ToList();

        string cis = Database.Query <CultureInfoEntity>().Select(a => a.Name).ToString(", ").Etc(60);

        if (!emailModels.Any())
        {
            return(null);
        }

        if (!replacements.Interactive || !SafeConsole.Ask("{0}\r\n have no EmailTemplates. Create in {1}?".FormatWith(emailModels.ToString("\r\n"), cis.DefaultText("No CultureInfos registered!"))))
        {
            return(null);
        }

        using (replacements.WithReplacedDatabaseName())
        {
            var cmd = emailModels.Select(se =>
            {
                try
                {
                    return(table.InsertSqlSync(EmailModelLogic.CreateDefaultTemplateInternal(se), includeCollections: true));
                }
                catch (Exception e)
                {
                    return(new SqlPreCommandSimple("Exception on SystemEmail {0}: {1}".FormatWith(se, e.Message)));
                }
            }).Combine(Spacing.Double);

            if (cmd != null)
            {
                return(SqlPreCommand.Combine(Spacing.Double, new SqlPreCommandSimple("DECLARE @parentId INT"), cmd));
            }

            return(cmd);
        }
    }
예제 #5
0
    public static bool IsVisible(EmailTemplateEntity et, EmailTemplateVisibleOn visibleOn)
    {
        if (et.Model == null)
        {
            return(visibleOn == EmailTemplateVisibleOn.Single);
        }

        if (EmailModelLogic.HasDefaultTemplateConstructor(et.Model))
        {
            return(false);
        }

        var entityType = EmailModelLogic.GetEntityType(et.Model.ToType());

        if (entityType.IsEntity())
        {
            return(visibleOn == EmailTemplateVisibleOn.Single);
        }

        var should = VisibleOnDictionary.TryGet(entityType, EmailTemplateVisibleOn.Single);

        return((should & visibleOn) != 0);
    }
예제 #6
0
    public static void GenerateDefaultTemplates()
    {
        var systemEmails = Database.Query <EmailModelEntity>().Where(se => !se.EmailTemplates().Any()).ToList();

        List <string> exceptions = new List <string>();

        foreach (var se in systemEmails)
        {
            try
            {
                EmailModelLogic.CreateDefaultTemplateInternal(se).Save();
            }
            catch (Exception ex)
            {
                exceptions.Add("{0} in {1}:\r\n{2}".FormatWith(ex.GetType().Name, se.FullClassName, ex.Message.Indent(4)));
            }
        }

        if (exceptions.Any())
        {
            throw new Exception(exceptions.ToString("\r\n\r\n"));
        }
    }
예제 #7
0
 public EmailModelEntity GetEmailModel(string fullClassName)
 {
     return(EmailModelLogic.GetEmailModelEntity(fullClassName));
 }
예제 #8
0
    public static void Start(SchemaBuilder sb, string?systemUserName, string?anonymousUserName)
    {
        if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
        {
            SystemUserName    = systemUserName;
            AnonymousUserName = anonymousUserName;

            CultureInfoLogic.AssertStarted(sb);

            sb.Include <UserEntity>()
            .WithExpressionFrom((RoleEntity r) => r.Users())
            .WithQuery(() => e => new
            {
                Entity = e,
                e.Id,
                e.UserName,
                e.Email,
                e.Role,
                e.State,
                e.CultureInfo,
            });

            sb.Include <RoleEntity>()
            .WithSave(RoleOperation.Save)
            .WithDelete(RoleOperation.Delete)
            .WithQuery(() => r => new
            {
                Entity = r,
                r.Id,
                r.Name,
            });

            roles           = sb.GlobalLazy(CacheRoles, new InvalidateWith(typeof(RoleEntity)), AuthLogic.NotifyRulesChanged);
            rolesInverse    = sb.GlobalLazy(() => roles.Value.Inverse(), new InvalidateWith(typeof(RoleEntity)));
            rolesByName     = sb.GlobalLazy(() => roles.Value.ToDictionaryEx(a => a.ToString() !), new InvalidateWith(typeof(RoleEntity)));
            mergeStrategies = sb.GlobalLazy(() =>
            {
                var strategies = Database.Query <RoleEntity>().Select(r => KeyValuePair.Create(r.ToLite(), r.MergeStrategy)).ToDictionary();

                var graph = roles.Value;

                Dictionary <Lite <RoleEntity>, RoleData> result = new Dictionary <Lite <RoleEntity>, RoleData>();
                foreach (var r in graph.CompilationOrder())
                {
                    var strat = strategies.GetOrThrow(r);

                    var baseValues = graph.RelatedTo(r).Select(r2 => result[r2].DefaultAllowed);

                    result.Add(r, new RoleData
                    {
                        MergeStrategy  = strat,
                        DefaultAllowed = strat == MergeStrategy.Union ? baseValues.Any(a => a) : baseValues.All(a => a)
                    });
                }

                return(result);
            }, new InvalidateWith(typeof(RoleEntity)), AuthLogic.NotifyRulesChanged);

            sb.Schema.EntityEvents <RoleEntity>().Saving += Schema_Saving;

            UserGraph.Register();

            EmailModelLogic.RegisterEmailModel <UserLockedMail>(() => new EmailTemplateEntity
            {
                Messages = CultureInfoLogic.ForEachCulture(culture => new EmailTemplateMessageEmbedded(culture)
                {
                    Text =
                        "<p>{0}</p>".FormatWith(AuthEmailMessage.YourAccountHasBeenLockedDueToSeveralFailedLogins.NiceToString()) +
                        "<p>{0}</p>".FormatWith(AuthEmailMessage.YouCanResetYourPasswordByFollowingTheLinkBelow.NiceToString()) +
                        "<p><a href=\"@[m:Url]\">@[m:Url]</a></p>",
                    Subject = AuthEmailMessage.YourAccountHasBeenLocked.NiceToString()
                }).ToMList()
            });
        }
    }
예제 #9
0
        public static void RegisterAlertNotificationMail(SchemaBuilder sb)
        {
            EmailModelLogic.RegisterEmailModel <AlertNotificationMail>(() => new EmailTemplateEntity
            {
                Messages = CultureInfoLogic.ForEachCulture(culture => new EmailTemplateMessageEmbedded(culture)
                {
                    Text    = @"
<p>Hi @[m:Entity],</p>
<p>You have some pending alerts:</p>
<ul>
 @foreach[m:Alerts] as $a
    <li>
        <strong>@[$a.AlertType]:</strong><br/>
        @[m:TextFormatted]<br/>
        <small>@[$a.AlertDate] @[$a.CreatedBy]</small>
    </li>
 @endforeach
</ul>
<p>Please visit <a href=""@[g:UrlLeft]"">@[g:UrlLeft]</a></p>",
                    Subject = AlertMessage.NewUnreadNotifications.NiceToString(),
                }).ToMList()
            });

            sb.Include <SendNotificationEmailTaskEntity>()
            .WithSave(SendNotificationEmailTaskOperation.Save)
            .WithQuery(() => e => new
            {
                Entity = e,
                e.Id,
                e.SendNotificationsOlderThan,
                e.SendBehavior,
            });

            SchedulerLogic.ExecuteTask.Register((SendNotificationEmailTaskEntity task, ScheduledTaskContext ctx) =>
            {
                var limit = DateTime.Now.AddMinutes(-task.SendNotificationsOlderThan);

                var query = Database.Query <AlertEntity>()
                            .Where(a => a.State == AlertState.Saved && a.EmailNotificationsSent == 0 && a.Recipient != null && a.CreationDate < limit)
                            .Where(a => task.SendBehavior == SendAlertTypeBehavior.All ||
                                   task.SendBehavior == SendAlertTypeBehavior.Include && task.AlertTypes.Contains(a.AlertType !) ||
                                   task.SendBehavior == SendAlertTypeBehavior.Exclude && !task.AlertTypes.Contains(a.AlertType !));

                if (!query.Any())
                {
                    return(null);
                }

                var alerts = query
                             .Select(a => new { Alert = a, Recipient = a.Recipient !.Entity })
                             .ToList();

                EmailPackageEntity emailPackage = new EmailPackageEntity().Save();

                var emails = alerts.GroupBy(a => a.Recipient, a => a.Alert).SelectMany(gr => new AlertNotificationMail((UserEntity)gr.Key, gr.ToList()).CreateEmailMessage()).ToList();

                emails.ForEach(a =>
                {
                    a.State   = EmailMessageState.ReadyToSend;
                    a.Package = emailPackage.ToLite();
                });

                emails.BulkInsertQueryIds(a => a.Target !);

                query.UnsafeUpdate().Set(a => a.EmailNotificationsSent, a => 1).Execute();

                return(emailPackage.ToLite());
            });
예제 #10
0
        public string GetConstructorType([Required, FromBody] EmailModelEntity model)
        {
            var type = EmailModelLogic.GetEntityType(model.ToType());

            return(ReflectionServer.GetTypeName(type));
        }
예제 #11
0
    public static void Start(SchemaBuilder sb, Func <EmailTemplateEntity, Lite <Entity>?, EmailMessageEntity?, EmailSenderConfigurationEntity?>?getSmtpConfiguration)
    {
        if (sb.NotDefined(MethodInfo.GetCurrentMethod()))
        {
            CultureInfoLogic.AssertStarted(sb);
            TemplatingLogic.Start(sb);


            GetSmtpConfiguration = getSmtpConfiguration;

            sb.Include <EmailTemplateEntity>()
            .WithQuery(() => t => new
            {
                Entity = t,
                t.Id,
                t.Name,
                t.IsBodyHtml
            });

            EmailTemplatesLazy = sb.GlobalLazy(() =>
                                               Database.Query <EmailTemplateEntity>().ToDictionary(et => et.ToLite())
                                               , new InvalidateWith(typeof(EmailTemplateEntity)));

            TemplatesByQueryName = sb.GlobalLazy(() =>
            {
                return(EmailTemplatesLazy.Value.Values.SelectCatch(et => KeyValuePair.Create(et.Query.ToQueryName(), et)).GroupToDictionary());
            }, new InvalidateWith(typeof(EmailTemplateEntity)));

            EmailModelLogic.Start(sb);
            EmailMasterTemplateLogic.Start(sb);

            sb.Schema.EntityEvents <EmailTemplateEntity>().PreSaving += new PreSavingEventHandler <EmailTemplateEntity>(EmailTemplate_PreSaving);
            sb.Schema.EntityEvents <EmailTemplateEntity>().Retrieved += EmailTemplateLogic_Retrieved;
            sb.Schema.Table <EmailModelEntity>().PreDeleteSqlSync    += e =>
                                                                        Administrator.UnsafeDeletePreCommand(Database.Query <EmailTemplateEntity>()
                                                                                                             .Where(a => a.Model.Is(e)));

            Validator.OverridePropertyValidator((EmailTemplateMessageEmbedded m) => m.Text).StaticPropertyValidation +=
                EmailTemplateMessageText_StaticPropertyValidation;

            Validator.OverridePropertyValidator((EmailTemplateMessageEmbedded m) => m.Subject).StaticPropertyValidation +=
                EmailTemplateMessageSubject_StaticPropertyValidation;

            EmailTemplateGraph.Register();

            GlobalValueProvider.RegisterGlobalVariable("UrlLeft", _ => EmailLogic.Configuration.UrlLeft);
            GlobalValueProvider.RegisterGlobalVariable("Now", _ => Clock.Now);
            GlobalValueProvider.RegisterGlobalVariable("Today", _ => Clock.Now.Date, "d");

            sb.Schema.Synchronizing += Schema_Synchronizing_Tokens;
            sb.Schema.Synchronizing += Schema_Synchronizing_DefaultTemplates;

            sb.Schema.Table <EmailModelEntity>().PreDeleteSqlSync += EmailTemplateLogic_PreDeleteSqlSync;

            Validator.PropertyValidator <EmailTemplateEntity>(et => et.Messages).StaticPropertyValidation += (et, pi) =>
            {
                var dc = EmailLogic.Configuration.DefaultCulture;

                if (!et.Messages.Any(m => m.CultureInfo != null && dc.Name.StartsWith(m.CultureInfo.Name)))
                {
                    return(EmailTemplateMessage.ThereMustBeAMessageFor0.NiceToString().FormatWith(CultureInfoLogic.EntityToCultureInfo.Value.Keys.Where(c => dc.Name.StartsWith(c.Name)).CommaOr(a => a.EnglishName)));
                }

                return(null);
            };
        }
    }
예제 #12
0
        public static void Register()
        {
            GetState = m => m.State;

            new Construct(EmailMessageOperation.CreateMail)
            {
                ToStates  = { EmailMessageState.Created },
                Construct = _ => new EmailMessageEntity
                {
                    State = EmailMessageState.Created,
                }
            }.Register();

            new ConstructFrom <EmailTemplateEntity>(EmailMessageOperation.CreateEmailFromTemplate)
            {
                ToStates     = { EmailMessageState.Created },
                CanConstruct = et =>
                {
                    if (et.Model != null && EmailModelLogic.RequiresExtraParameters(et.Model))
                    {
                        return(EmailMessageMessage._01requiresExtraParameters.NiceToString(typeof(EmailModelEntity).NiceName(), et.Model));
                    }

                    return(null);
                },
                Construct = (et, args) =>
                {
                    var entity = args.TryGetArgC <ModifiableEntity>() ?? args.GetArg <Lite <Entity> >().RetrieveAndRemember();

                    var emailMessageEntity = et.ToLite().CreateEmailMessage(entity).FirstOrDefault();
                    if (emailMessageEntity == null)
                    {
                        throw new InvalidOperationException("No suitable recipients were found");
                    }
                    return(emailMessageEntity);
                }
            }.Register();

            new Execute(EmailMessageOperation.Save)
            {
                CanBeNew      = true,
                CanBeModified = true,
                FromStates    = { EmailMessageState.Created, EmailMessageState.Outdated },
                ToStates      = { EmailMessageState.Draft },
                Execute       = (m, _) =>
                {
                    m.State = EmailMessageState.Draft;
                }
            }.Register();

            new Execute(EmailMessageOperation.ReadyToSend)
            {
                CanBeNew      = true,
                CanBeModified = true,
                FromStates    = { EmailMessageState.Created, EmailMessageState.Draft, EmailMessageState.SentException, EmailMessageState.RecruitedForSending, EmailMessageState.Outdated },
                ToStates      = { EmailMessageState.ReadyToSend },
                Execute       = (m, _) =>
                {
                    m.SendRetries = 0;
                    m.Exception   = null;
                    m.State       = EmailMessageState.ReadyToSend;
                }
            }.Register();

            new Execute(EmailMessageOperation.Send)
            {
                CanExecute = m => m.State == EmailMessageState.Created || m.State == EmailMessageState.Draft ||
                             m.State == EmailMessageState.ReadyToSend || m.State == EmailMessageState.RecruitedForSending ||
                             m.State == EmailMessageState.Outdated ? null : EmailMessageMessage.TheEmailMessageCannotBeSentFromState0.NiceToString().FormatWith(m.State.NiceToString()),
                CanBeNew      = true,
                CanBeModified = true,
                FromStates    = { EmailMessageState.Created, EmailMessageState.Draft, EmailMessageState.ReadyToSend, EmailMessageState.Outdated },
                ToStates      = { EmailMessageState.Sent },
                Execute       = (m, _) => EmailLogic.SenderManager.Send(m)
            }.Register();


            new ConstructFrom <EmailMessageEntity>(EmailMessageOperation.ReSend)
            {
                ToStates  = { EmailMessageState.Created },
                Construct = (m, _) =>
                {
                    return(new EmailMessageEntity
                    {
                        From = m.From.Clone(),
                        Recipients = m.Recipients.Select(r => r.Clone()).ToMList(),
                        Target = m.Target,
                        Subject = m.Subject,
                        Body = new BigStringEmbedded(m.Body.Text),
                        IsBodyHtml = m.IsBodyHtml,
                        Template = m.Template,
                        EditableMessage = m.EditableMessage,
                        State = EmailMessageState.Created,
                        Attachments = m.Attachments.Select(a => a.Clone()).ToMList()
                    });
                }
            }.Register();

            new Graph <EmailMessageEntity> .Delete(EmailMessageOperation.Delete)
            {
                Delete = (m, _) => m.Delete()
            }

            .Register();
        }