13
13
using Microsoft . AspNetCore . Http ;
14
14
using Microsoft . AspNetCore . Mvc ;
15
15
using Microsoft . AspNetCore . Routing ;
16
+ using Microsoft . Extensions . DependencyInjection ;
16
17
using Microsoft . Extensions . Logging ;
17
18
using Microsoft . Extensions . Options ;
18
19
using MimeKit ;
42
43
using Umbraco . Cms . Web . Common . ActionsResults ;
43
44
using Umbraco . Cms . Web . Common . Attributes ;
44
45
using Umbraco . Cms . Web . Common . Authorization ;
46
+ using Umbraco . Cms . Web . Common . DependencyInjection ;
45
47
using Umbraco . Cms . Web . Common . Security ;
46
48
using Umbraco . Extensions ;
47
49
using Constants = Umbraco . Cms . Core . Constants ;
@@ -75,7 +77,10 @@ public class UsersController : BackOfficeNotificationsController
75
77
private readonly UserEditorAuthorizationHelper _userEditorAuthorizationHelper ;
76
78
private readonly IPasswordChanger < BackOfficeIdentityUser > _passwordChanger ;
77
79
private readonly ILogger < UsersController > _logger ;
80
+ private readonly IHttpContextAccessor _httpContextAccessor ;
81
+ private readonly WebRoutingSettings _webRoutingSettings ;
78
82
83
+ [ ActivatorUtilitiesConstructor ]
79
84
public UsersController (
80
85
MediaFileManager mediaFileManager ,
81
86
IOptions < ContentSettings > contentSettings ,
@@ -96,7 +101,9 @@ public UsersController(
96
101
LinkGenerator linkGenerator ,
97
102
IBackOfficeExternalLoginProviders externalLogins ,
98
103
UserEditorAuthorizationHelper userEditorAuthorizationHelper ,
99
- IPasswordChanger < BackOfficeIdentityUser > passwordChanger )
104
+ IPasswordChanger < BackOfficeIdentityUser > passwordChanger ,
105
+ IHttpContextAccessor httpContextAccessor ,
106
+ IOptions < WebRoutingSettings > webRoutingSettings )
100
107
{
101
108
_mediaFileManager = mediaFileManager ;
102
109
_contentSettings = contentSettings . Value ;
@@ -119,6 +126,55 @@ public UsersController(
119
126
_userEditorAuthorizationHelper = userEditorAuthorizationHelper ;
120
127
_passwordChanger = passwordChanger ;
121
128
_logger = _loggerFactory . CreateLogger < UsersController > ( ) ;
129
+ _httpContextAccessor = httpContextAccessor ;
130
+ _webRoutingSettings = webRoutingSettings . Value ;
131
+ }
132
+
133
+ [ Obsolete ( "Use constructor that also takes IHttpAccessor and IOptions<WebRoutingSettings>, scheduled for removal in V11" ) ]
134
+ public UsersController (
135
+ MediaFileManager mediaFileManager ,
136
+ IOptions < ContentSettings > contentSettings ,
137
+ IHostingEnvironment hostingEnvironment ,
138
+ ISqlContext sqlContext ,
139
+ IImageUrlGenerator imageUrlGenerator ,
140
+ IOptions < SecuritySettings > securitySettings ,
141
+ IEmailSender emailSender ,
142
+ IBackOfficeSecurityAccessor backofficeSecurityAccessor ,
143
+ AppCaches appCaches ,
144
+ IShortStringHelper shortStringHelper ,
145
+ IUserService userService ,
146
+ ILocalizedTextService localizedTextService ,
147
+ IUmbracoMapper umbracoMapper ,
148
+ IOptions < GlobalSettings > globalSettings ,
149
+ IBackOfficeUserManager backOfficeUserManager ,
150
+ ILoggerFactory loggerFactory ,
151
+ LinkGenerator linkGenerator ,
152
+ IBackOfficeExternalLoginProviders externalLogins ,
153
+ UserEditorAuthorizationHelper userEditorAuthorizationHelper ,
154
+ IPasswordChanger < BackOfficeIdentityUser > passwordChanger )
155
+ : this ( mediaFileManager ,
156
+ contentSettings ,
157
+ hostingEnvironment ,
158
+ sqlContext ,
159
+ imageUrlGenerator ,
160
+ securitySettings ,
161
+ emailSender ,
162
+ backofficeSecurityAccessor ,
163
+ appCaches ,
164
+ shortStringHelper ,
165
+ userService ,
166
+ localizedTextService ,
167
+ umbracoMapper ,
168
+ globalSettings ,
169
+ backOfficeUserManager ,
170
+ loggerFactory ,
171
+ linkGenerator ,
172
+ externalLogins ,
173
+ userEditorAuthorizationHelper ,
174
+ passwordChanger ,
175
+ StaticServiceProvider . Instance . GetRequiredService < IHttpContextAccessor > ( ) ,
176
+ StaticServiceProvider . Instance . GetRequiredService < IOptions < WebRoutingSettings > > ( ) )
177
+ {
122
178
}
123
179
124
180
/// <summary>
@@ -421,20 +477,25 @@ public async Task<ActionResult<UserDisplay>> PostCreateUser(UserInvite userSave)
421
477
/// </remarks>
422
478
public async Task < ActionResult < UserDisplay > > PostInviteUser ( UserInvite userSave )
423
479
{
424
- if ( userSave == null ) throw new ArgumentNullException ( "userSave" ) ;
480
+ if ( userSave == null )
481
+ {
482
+ throw new ArgumentNullException ( "userSave" ) ;
483
+ }
425
484
426
485
if ( userSave . Message . IsNullOrWhiteSpace ( ) )
486
+ {
427
487
ModelState . AddModelError ( "Message" , "Message cannot be empty" ) ;
488
+ }
428
489
429
490
IUser user ;
430
491
if ( _securitySettings . UsernameIsEmail )
431
492
{
432
- //ensure it's the same
493
+ // ensure it's the same
433
494
userSave . Username = userSave . Email ;
434
495
}
435
496
else
436
497
{
437
- //first validate the username if we're showing it
498
+ // first validate the username if we're showing it
438
499
var userResult = CheckUniqueUsername ( userSave . Username , u => u . LastLoginDate != default || u . EmailConfirmedDate . HasValue ) ;
439
500
if ( ! ( userResult . Result is null ) )
440
501
{
@@ -443,6 +504,7 @@ public async Task<ActionResult<UserDisplay>> PostInviteUser(UserInvite userSave)
443
504
444
505
user = userResult . Value ;
445
506
}
507
+
446
508
user = CheckUniqueEmail ( userSave . Email , u => u . LastLoginDate != default || u . EmailConfirmedDate . HasValue ) ;
447
509
448
510
if ( ModelState . IsValid == false )
@@ -455,7 +517,7 @@ public async Task<ActionResult<UserDisplay>> PostInviteUser(UserInvite userSave)
455
517
return ValidationProblem ( "No Email server is configured" ) ;
456
518
}
457
519
458
- //Perform authorization here to see if the current user can actually save this user with the info being requested
520
+ // Perform authorization here to see if the current user can actually save this user with the info being requested
459
521
var canSaveUser = _userEditorAuthorizationHelper . IsAuthorized ( _backofficeSecurityAccessor . BackOfficeSecurity . CurrentUser , user , null , null , userSave . UserGroups ) ;
460
522
if ( canSaveUser == false )
461
523
{
@@ -464,8 +526,8 @@ public async Task<ActionResult<UserDisplay>> PostInviteUser(UserInvite userSave)
464
526
465
527
if ( user == null )
466
528
{
467
- //we want to create the user with the UserManager, this ensures the 'empty' (special) password
468
- //format is applied without us having to duplicate that logic
529
+ // we want to create the user with the UserManager, this ensures the 'empty' (special) password
530
+ // format is applied without us having to duplicate that logic
469
531
var identityUser = BackOfficeIdentityUser . CreateNew ( _globalSettings , userSave . Username , userSave . Email , _globalSettings . DefaultUILanguage ) ;
470
532
identityUser . Name = userSave . Name ;
471
533
@@ -475,21 +537,21 @@ public async Task<ActionResult<UserDisplay>> PostInviteUser(UserInvite userSave)
475
537
return ValidationProblem ( created . Errors . ToErrorMessage ( ) ) ;
476
538
}
477
539
478
- //now re-look the user back up
540
+ // now re-look the user back up
479
541
user = _userService . GetByEmail ( userSave . Email ) ;
480
542
}
481
543
482
- //map the save info over onto the user
544
+ // map the save info over onto the user
483
545
user = _umbracoMapper . Map ( userSave , user ) ;
484
546
485
- //ensure the invited date is set
547
+ // ensure the invited date is set
486
548
user . InvitedDate = DateTime . Now ;
487
549
488
- //Save the updated user (which will process the user groups too)
550
+ // Save the updated user (which will process the user groups too)
489
551
_userService . Save ( user ) ;
490
552
var display = _umbracoMapper . Map < UserDisplay > ( user ) ;
491
553
492
- //send the email
554
+ // send the email
493
555
await SendUserInviteEmailAsync ( display , _backofficeSecurityAccessor . BackOfficeSecurity . CurrentUser . Name , _backofficeSecurityAccessor . BackOfficeSecurity . CurrentUser . Email , user , userSave . Message ) ;
494
556
495
557
display . AddSuccessNotification ( _localizedTextService . Localize ( "speechBubbles" , "resendInviteHeader" ) , _localizedTextService . Localize ( "speechBubbles" , "resendInviteSuccess" , new [ ] { user . Name } ) ) ;
@@ -544,14 +606,14 @@ private async Task SendUserInviteEmailAsync(UserBasic userDisplay, string from,
544
606
} ) ;
545
607
546
608
// Construct full URL using configured application URL (which will fall back to request)
547
- var applicationUri = _hostingEnvironment . ApplicationMainUrl ;
609
+ Uri applicationUri = _httpContextAccessor . GetRequiredHttpContext ( ) . Request . GetApplicationUri ( _webRoutingSettings ) ;
548
610
var inviteUri = new Uri ( applicationUri , action ) ;
549
611
550
612
var emailSubject = _localizedTextService . Localize ( "user" , "inviteEmailCopySubject" ,
551
- //Ensure the culture of the found user is used for the email!
613
+ // Ensure the culture of the found user is used for the email!
552
614
UmbracoUserExtensions . GetUserCulture ( to . Language , _localizedTextService , _globalSettings ) ) ;
553
615
var emailBody = _localizedTextService . Localize ( "user" , "inviteEmailCopyFormat" ,
554
- //Ensure the culture of the found user is used for the email!
616
+ // Ensure the culture of the found user is used for the email!
555
617
UmbracoUserExtensions . GetUserCulture ( to . Language , _localizedTextService , _globalSettings ) ,
556
618
new [ ] { userDisplay . Name , from , message , inviteUri . ToString ( ) , senderEmail } ) ;
557
619
0 commit comments