Ejemplo n.º 1
0
        public async Task <WebStatus> RegisterAsync(RegisterInputModel model)
        {
            var genericSuccessMessage = _localizer["Please check your email to complete the sign up process."];

            _logger.LogDebug("Begin registration for {0}", model.Email);

            if (!ApplicationIdIsNullOrValid(model.ApplicationId))
            {
                return(WebStatus.Error(_localizer["Invalid application id."], HttpStatusCode.BadRequest));
            }

            if (!await _userStore.UsernameIsAvailable(model.Email))
            {
                _logger.LogDebug("Existing user found.");

                var sendStatus = await _messageService.SendAccountAlreadyExistsMessageAsync(model.ApplicationId, model.Email);

                // Return a generic success message to prevent account discovery. Only the owner of
                // the email address will get a customized message.
                return(sendStatus.IsOk ? WebStatus.Success(genericSuccessMessage) : new WebStatus(sendStatus));
            }

            if (await _oneTimeCodeService.UnexpiredOneTimeCodeExistsAsync(model.Email))
            {
                // Although the username is available, there is a valid one time code
                // that can be used to cancel an email address change, so we can't
                // reuse the address quite yet
                return(WebStatus.Error(_localizer["Email address is temporarily reserved."], HttpStatusCode.Conflict));
            }

            _logger.LogDebug("Email address not used by an existing user. Creating a new user.");
            // consider: in some cases may want to restricting claims to a list predefined by the system administrator

            var status = new WebStatus();

            if (model.Claims == null)
            {
                model.Claims = new Dictionary <string, string>();
            }
            var internalClaims = new KeyValuePair <string, string>[]
            {
                new KeyValuePair <string, string>(
                    PasswordlessLoginConstants.Security.EmailNotConfirmedClaimType, "!")
            };
            var newUser = new User()
            {
                Email  = model.Email,
                Claims = model.Claims
                         .Where(x =>
                                !PasswordlessLoginConstants.Security.ForbiddenClaims.Contains(x.Key) &&
                                !PasswordlessLoginConstants.Security.ProtectedClaims.Contains(x.Key))
                         .Union(internalClaims)
                         .Select(x => new UserClaim()
                {
                    Type = x.Key, Value = x.Value
                })
            };
            var newUserResponse = await _userStore.AddUserAsync(newUser);

            if (newUserResponse.HasError)
            {
                return(new WebStatus(newUserResponse.Status));
            }
            newUser = newUserResponse.Result;
            await _eventNotificationService.NotifyEventAsync(newUser.Email, EventType.Register);

            if (!string.IsNullOrEmpty(model.Password))
            {
                var setPasswordStatus = await _passwordService.SetPasswordAsync(newUser.SubjectId, model.Password);

                if (setPasswordStatus.IsOk)
                {
                    await _eventNotificationService.NotifyEventAsync(newUser.Email, EventType.SetPassword);
                }
                else
                {
                    status.AddWarning(_localizer["Password was not set."]);
                }
            }

            status.AddSuccess(genericSuccessMessage);

            var nextUrl = !string.IsNullOrEmpty(model.NextUrl) ? model.NextUrl : _urlService.GetDefaultRedirectUrl();

            if (model.SetPassword)
            {
                _logger.LogTrace("The user will be asked to set their password after confirming the account.");
                nextUrl = SendToSetPasswordFirst(nextUrl);
            }

            var oneTimeCodeResponse = await _oneTimeCodeService.GetOneTimeCodeAsync(model.Email, TimeSpan.FromMinutes(_options.ConfirmAccountLinkValidityMinutes), nextUrl);

            switch (oneTimeCodeResponse.Status.StatusCode)
            {
            case GetOneTimeCodeStatusCode.Success:
                var result = await _messageService.SendWelcomeMessageAsync(model.ApplicationId, model.Email,
                                                                           oneTimeCodeResponse.Result.ShortCode, oneTimeCodeResponse.Result.LongCode, model.Claims);

                SetNonce(oneTimeCodeResponse.Result.ClientNonce);
                return(new WebStatus(status));

            case GetOneTimeCodeStatusCode.TooManyRequests:
                return(WebStatus.Error(_localizer["Please wait a few minutes and try again."], HttpStatusCode.TooManyRequests));

            case GetOneTimeCodeStatusCode.ServiceFailure:
            default:
                return(ServerError(_localizer["Hmm. Something went wrong. Please try again."]));
            }
        }