Last active
March 20, 2020 07:10
-
-
Save hikalkan/8862d9f7ae8b4874976d to your computer and use it in GitHub Desktop.
Revisions
-
hikalkan revised this gist
Dec 29, 2015 . No changes.There are no files selected for viewing
-
hikalkan created this gist
Dec 29, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,130 @@ /* SAMPLE AJAX CALL to this action: (This is enough since it's automatically redirected to the target tenant's ImpersonateSignIn action) abp.ajax({ url: abp.appPath + 'Account/Impersonate', data: JSON.stringify({ tenantId: 1, //Target tenant id (can be null if target user is a host user) userId: 2 //Target user id }) }); */ [AbpMvcAuthorize(AppPermissions.Pages_Administration_Users_Impersonation)] public virtual async Task<JsonResult> Impersonate(ImpersonateModel model) { CheckModelState(); if (AbpSession.ImpersonatorUserId.HasValue) { throw new UserFriendlyException(L("CascadeImpersonationErrorMessage")); } if (AbpSession.TenantId.HasValue) { if (!model.TenantId.HasValue) { throw new UserFriendlyException(L("FromTenantToHostImpersonationErrorMessage")); } if (model.TenantId.Value != AbpSession.TenantId.Value) { throw new UserFriendlyException(L("DifferentTenantImpersonationErrorMessage")); } } return await SaveImpersonationTokenAndGetTargetUrl(model.TenantId, model.UserId, false); } [UnitOfWork] public virtual async Task<ActionResult> ImpersonateSignIn(string tokenId) { var cacheItem = await _cacheManager.GetImpersonationCache().GetOrDefaultAsync(tokenId); if (cacheItem == null) { throw new UserFriendlyException(L("ImpersonationTokenErrorMessage")); } //Switch to requested tenant using (_unitOfWorkManager.Current.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, cacheItem.TargetTenantId)) { //Get the user from tenant var user = await _userManager.FindByIdAsync(cacheItem.TargetUserId); //Create identity var identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); if (!cacheItem.IsBackToImpersonator) { //Add claims for audit logging if (cacheItem.ImpersonatorTenantId.HasValue) { identity.AddClaim(new Claim(AbpClaimTypes.ImpersonatorTenantId, cacheItem.ImpersonatorTenantId.Value.ToString(CultureInfo.InvariantCulture))); } identity.AddClaim(new Claim(AbpClaimTypes.ImpersonatorUserId, cacheItem.ImpersonatorUserId.ToString(CultureInfo.InvariantCulture))); } //Sign in with the target user AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = false }, identity); //Remove the cache item to prevent re-use await _cacheManager.GetImpersonationCache().RemoveAsync(tokenId); return RedirectToAction("Index", "Application"); } } /* SAMPLE AJAX CALL to this action: (This is enough since it's automatically redirected to the host's ImpersonateSignIn action) abp.ajax({ url: abp.appPath + 'Account/BackToImpersonator' }); */ public virtual async Task<JsonResult> BackToImpersonator() { if (!AbpSession.ImpersonatorUserId.HasValue) { throw new UserFriendlyException(L("NotImpersonatedLoginErrorMessage")); } return await SaveImpersonationTokenAndGetTargetUrl(AbpSession.ImpersonatorTenantId, AbpSession.ImpersonatorUserId.Value, true); } private async Task<JsonResult> SaveImpersonationTokenAndGetTargetUrl(int? tenantId, long userId, bool isBackToImpersonator) { //Create a cache item var cacheItem = new ImpersonationCacheItem( tenantId, userId, isBackToImpersonator ); if (!isBackToImpersonator) { cacheItem.ImpersonatorTenantId = AbpSession.TenantId; cacheItem.ImpersonatorUserId = AbpSession.GetUserId(); } //Create a random token and save to the cache var tokenId = Guid.NewGuid().ToString(); await _cacheManager .GetImpersonationCache() .SetAsync(tokenId, cacheItem, TimeSpan.FromMinutes(1)); //Find tenancy name string tenancyName = null; if (tenantId.HasValue) { tenancyName = (await _tenantManager.GetByIdAsync(tenantId.Value)).TenancyName; } //Create target URL var targetUrl = _webUrlService.GetSiteRootAddress(tenancyName) + "Account/ImpersonateSignIn?tokenId=" + tokenId; return Json(new MvcAjaxResponse { TargetUrl = targetUrl }); } #endregion This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,27 @@ [Serializable] public class ImpersonationCacheItem { public const string CacheName = "AppImpersonationCache"; public int? ImpersonatorTenantId { get; set; } public long ImpersonatorUserId { get; set; } public int? TargetTenantId { get; set; } public long TargetUserId { get; set; } public bool IsBackToImpersonator { get; set; } public ImpersonationCacheItem() { } public ImpersonationCacheItem(int? targetTenantId, long targetUserId, bool isBackToImpersonator) { TargetTenantId = targetTenantId; TargetUserId = targetUserId; IsBackToImpersonator = isBackToImpersonator; } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,7 @@ public static class ImpersonationCacheManagerExtensions { public static ITypedCache<string, ImpersonationCacheItem> GetImpersonationCache(this ICacheManager cacheManager) { return cacheManager.GetCache<string, ImpersonationCacheItem>(ImpersonationCacheItem.CacheName); } }