RegisterUserTask.cs 7.3 KB
Newer Older
M
Michael Petrinolis 已提交
1
using System.Collections.Generic;
2
using System.Text.Encodings.Web;
M
Michael Petrinolis 已提交
3 4 5 6
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Localization;
7
using Microsoft.AspNetCore.Routing;
M
Michael Petrinolis 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using OrchardCore.DisplayManagement.ModelBinding;
using OrchardCore.Email;
using OrchardCore.Users.Models;
using OrchardCore.Users.Services;
using OrchardCore.Workflows.Abstractions.Models;
using OrchardCore.Workflows.Activities;
using OrchardCore.Workflows.Models;
using OrchardCore.Workflows.Services;

namespace OrchardCore.Users.Workflows.Activities
{
    public class RegisterUserTask : TaskActivity
    {
        private readonly IUserService _userService;
        private readonly UserManager<IUser> _userManager;
        private readonly IWorkflowExpressionEvaluator _expressionEvaluator;
26
        private readonly LinkGenerator _linkGenerator;
M
Michael Petrinolis 已提交
27 28
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IUpdateModelAccessor _updateModelAccessor;
29
        private readonly IStringLocalizer S;
30
        private readonly HtmlEncoder _htmlEncoder;
M
Michael Petrinolis 已提交
31

32 33 34 35 36 37 38
        public RegisterUserTask(
            IUserService userService,
            UserManager<IUser> userManager,
            IWorkflowExpressionEvaluator expressionEvaluator,
            LinkGenerator linkGenerator,
            IHttpContextAccessor httpContextAccessor,
            IUpdateModelAccessor updateModelAccessor,
39 40
            IStringLocalizer<RegisterUserTask> localizer,
            HtmlEncoder htmlEncoder)
M
Michael Petrinolis 已提交
41 42 43 44
        {
            _userService = userService;
            _userManager = userManager;
            _expressionEvaluator = expressionEvaluator;
45
            _linkGenerator = linkGenerator;
M
Michael Petrinolis 已提交
46 47
            _httpContextAccessor = httpContextAccessor;
            _updateModelAccessor = updateModelAccessor;
48
            S = localizer;
49
            _htmlEncoder = htmlEncoder;
M
Michael Petrinolis 已提交
50 51 52 53
        }

        // The technical name of the activity. Activities on a workflow definition reference this name.
        public override string Name => nameof(RegisterUserTask);
A
Antoine Griffard 已提交
54

55
        public override LocalizedString DisplayText => S["Register User Task"];
M
Michael Petrinolis 已提交
56 57

        // The category to which this activity belongs. The activity picker groups activities by this category.
58
        public override LocalizedString Category => S["User"];
M
Michael Petrinolis 已提交
59 60 61 62 63 64 65 66

        // The message to display.
        public bool SendConfirmationEmail
        {
            get => GetProperty(() => true);
            set => SetProperty(value);
        }

67 68 69 70 71 72
        public WorkflowExpression<string> ConfirmationEmailSubject
        {
            get => GetProperty(() => new WorkflowExpression<string>());
            set => SetProperty(value);
        }

M
Michael Petrinolis 已提交
73 74 75 76 77 78
        // The message to display.
        public WorkflowExpression<string> ConfirmationEmailTemplate
        {
            get => GetProperty(() => new WorkflowExpression<string>());
            set => SetProperty(value);
        }
79 80 81 82 83
        public bool RequireModeration
        {
            get => GetProperty(() => false);
            set => SetProperty(value);
        }
M
Michael Petrinolis 已提交
84 85 86 87

        // Returns the possible outcomes of this activity.
        public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
        {
88
            return Outcomes(S["Done"], S["Valid"], S["Invalid"]);
M
Michael Petrinolis 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
        }

        // This is the heart of the activity and actually performs the work to be done.
        public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
        {
            bool isValid = false;
            IFormCollection form = null;
            string email = null;
            if (_httpContextAccessor.HttpContext != null)
            {
                form = _httpContextAccessor.HttpContext.Request.Form;
                email = form["Email"];
                isValid = !string.IsNullOrWhiteSpace(email);
            }
            var outcome = isValid ? "Valid" : "Invalid";

            if (isValid)
            {
                var userName = form["UserName"];
                if (string.IsNullOrWhiteSpace(userName))
109 110 111
                {
                    userName = email.Replace('@', '+');
                }
M
Michael Petrinolis 已提交
112 113

                var errors = new Dictionary<string, string>();
114
                var user = (User)await _userService.CreateUserAsync(new User() { UserName = userName, Email = email, IsEnabled = !RequireModeration }, null, (key, message) => errors.Add(key, message));
M
Michael Petrinolis 已提交
115 116 117 118 119 120 121
                if (errors.Count > 0)
                {
                    var updater = _updateModelAccessor.ModelUpdater;
                    if (updater != null)
                    {
                        foreach (var item in errors)
                        {
122
                            updater.ModelState.TryAddModelError(item.Key, S[item.Value]);
M
Michael Petrinolis 已提交
123 124 125 126 127 128 129
                        }
                    }
                    outcome = "Invalid";
                }
                else if (SendConfirmationEmail)
                {
                    var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
130

131
                    var uri = _linkGenerator.GetUriByAction(_httpContextAccessor.HttpContext, "ConfirmEmail",
D
Dean Marcussen 已提交
132
                        "Registration", new { area = "OrchardCore.Users", userId = user.UserId, code });
M
Michael Petrinolis 已提交
133

134
                    workflowContext.Properties["EmailConfirmationUrl"] = uri;
M
Michael Petrinolis 已提交
135

136
                    var subject = await _expressionEvaluator.EvaluateAsync(ConfirmationEmailSubject, workflowContext, null);
137

138
                    var body = await _expressionEvaluator.EvaluateAsync(ConfirmationEmailTemplate, workflowContext, _htmlEncoder);
139

140 141 142
                    var message = new MailMessage()
                    {
                        To = email,
143 144
                        Subject = subject,
                        Body = body,
145 146
                        IsBodyHtml = true
                    };
M
Michael Petrinolis 已提交
147 148 149 150 151 152 153
                    var smtpService = _httpContextAccessor.HttpContext.RequestServices.GetService<ISmtpService>();

                    if (smtpService == null)
                    {
                        var updater = _updateModelAccessor.ModelUpdater;
                        if (updater != null)
                        {
154
                            updater.ModelState.TryAddModelError("", S["No email service is available"]);
M
Michael Petrinolis 已提交
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
                        }
                        outcome = "Invalid";
                    }
                    else
                    {
                        var result = await smtpService.SendAsync(message);
                        if (!result.Succeeded)
                        {
                            var updater = _updateModelAccessor.ModelUpdater;
                            if (updater != null)
                            {
                                foreach (var item in result.Errors)
                                {
                                    updater.ModelState.TryAddModelError(item.Name, item.Value);
                                }
                            }
                            outcome = "Invalid";
                        }
                    }
                }
            }

            return Outcomes("Done", outcome);
        }
    }
}