Kickuser çalışması
This commit is contained in:
parent
8234b1de2a
commit
6f3b20ffe2
7 changed files with 100 additions and 2 deletions
|
|
@ -7,6 +7,7 @@ using Sozsoft.Platform.Entities;
|
||||||
using Sozsoft.Platform.Extensions;
|
using Sozsoft.Platform.Extensions;
|
||||||
using Sozsoft.Platform.Identity.Dto;
|
using Sozsoft.Platform.Identity.Dto;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using OpenIddict.Abstractions;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
using Volo.Abp.Domain.Repositories;
|
using Volo.Abp.Domain.Repositories;
|
||||||
using Volo.Abp.Guids;
|
using Volo.Abp.Guids;
|
||||||
|
|
@ -20,6 +21,8 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
{
|
{
|
||||||
public IIdentityUserAppService IdentityUserAppService { get; }
|
public IIdentityUserAppService IdentityUserAppService { get; }
|
||||||
private readonly IIdentityUserRepository identityUserRepository;
|
private readonly IIdentityUserRepository identityUserRepository;
|
||||||
|
private readonly IIdentitySessionRepository identitySessionRepository;
|
||||||
|
private readonly IOpenIddictTokenManager openIddictTokenManager;
|
||||||
public IRepository<PermissionDefinitionRecord, Guid> permissionRepository { get; }
|
public IRepository<PermissionDefinitionRecord, Guid> permissionRepository { get; }
|
||||||
public IRepository<Branch, Guid> branchRepository { get; }
|
public IRepository<Branch, Guid> branchRepository { get; }
|
||||||
public IRepository<BranchUsers, Guid> branchUsersRepository { get; }
|
public IRepository<BranchUsers, Guid> branchUsersRepository { get; }
|
||||||
|
|
@ -31,6 +34,8 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
public PlatformIdentityAppService(
|
public PlatformIdentityAppService(
|
||||||
IIdentityUserAppService identityUserAppService,
|
IIdentityUserAppService identityUserAppService,
|
||||||
IIdentityUserRepository identityUserRepository,
|
IIdentityUserRepository identityUserRepository,
|
||||||
|
IIdentitySessionRepository identitySessionRepository,
|
||||||
|
IOpenIddictTokenManager openIddictTokenManager,
|
||||||
IRepository<PermissionDefinitionRecord, Guid> permissionRepository,
|
IRepository<PermissionDefinitionRecord, Guid> permissionRepository,
|
||||||
IRepository<Branch, Guid> branchRepository,
|
IRepository<Branch, Guid> branchRepository,
|
||||||
IRepository<BranchUsers, Guid> branchUsersRepository,
|
IRepository<BranchUsers, Guid> branchUsersRepository,
|
||||||
|
|
@ -41,6 +46,8 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
{
|
{
|
||||||
this.IdentityUserAppService = identityUserAppService;
|
this.IdentityUserAppService = identityUserAppService;
|
||||||
this.identityUserRepository = identityUserRepository;
|
this.identityUserRepository = identityUserRepository;
|
||||||
|
this.identitySessionRepository = identitySessionRepository;
|
||||||
|
this.openIddictTokenManager = openIddictTokenManager;
|
||||||
this.workHourRepository = workHourRepository;
|
this.workHourRepository = workHourRepository;
|
||||||
this.permissionRepository = permissionRepository;
|
this.permissionRepository = permissionRepository;
|
||||||
this.branchRepository = branchRepository;
|
this.branchRepository = branchRepository;
|
||||||
|
|
@ -231,4 +238,24 @@ public class PlatformIdentityAppService : ApplicationService
|
||||||
|
|
||||||
user.Claims.Remove(claim);
|
user.Claims.Remove(claim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kullanıcıyı anlık olarak oturumdan atar:
|
||||||
|
/// 1. AbpSessions kaydını siler → concurrent lisans slotunu serbest bırakır.
|
||||||
|
/// 2. OpenIddict tokenlarını revoke eder → access token anında geçersiz olur.
|
||||||
|
/// </summary>
|
||||||
|
public async Task KickUserAsync(Guid userId)
|
||||||
|
{
|
||||||
|
using (CurrentTenant.Change(CurrentTenant.Id))
|
||||||
|
{
|
||||||
|
// 1. AbpSessions temizle
|
||||||
|
var sessions = await identitySessionRepository.GetListAsync(userId: userId);
|
||||||
|
foreach (var session in sessions)
|
||||||
|
await identitySessionRepository.DeleteAsync(session);
|
||||||
|
|
||||||
|
// 2. OpenIddict tokenlarını revoke et
|
||||||
|
await foreach (var token in openIddictTokenManager.FindBySubjectAsync(userId.ToString()))
|
||||||
|
await openIddictTokenManager.TryRevokeAsync(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1038,6 +1038,12 @@
|
||||||
"en": "Hangfire Refresh",
|
"en": "Hangfire Refresh",
|
||||||
"tr": "Hangfire Yenile"
|
"tr": "Hangfire Yenile"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Platform.KickUser",
|
||||||
|
"en": "Kick User",
|
||||||
|
"tr": "Kullanıcıyı At"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "DeleteConfirmation",
|
"key": "DeleteConfirmation",
|
||||||
|
|
@ -3060,6 +3066,12 @@
|
||||||
"en": "Redis cache is being cleared.",
|
"en": "Redis cache is being cleared.",
|
||||||
"tr": "Redis önbelleği temizleniyor."
|
"tr": "Redis önbelleği temizleniyor."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.KickUser.Message",
|
||||||
|
"en": "User is being kicked.",
|
||||||
|
"tr": "Kullanıcı atılıyor."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "LoginEndDate",
|
"key": "LoginEndDate",
|
||||||
|
|
|
||||||
|
|
@ -2146,6 +2146,16 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
ColumnOptionJson = DefaultColumnOptionJson(),
|
ColumnOptionJson = DefaultColumnOptionJson(),
|
||||||
PermissionJson = DefaultPermissionJson(listFormName),
|
PermissionJson = DefaultPermissionJson(listFormName),
|
||||||
PagerOptionJson = DefaultPagerOptionJson,
|
PagerOptionJson = DefaultPagerOptionJson,
|
||||||
|
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
|
||||||
|
new() {
|
||||||
|
ButtonPosition= UiCommandButtonPositionTypeEnum.CommandColumn,
|
||||||
|
Hint = "App.Platform.KickUser",
|
||||||
|
Text = "App.Platform.KickUser",
|
||||||
|
AuthName=listFormName,
|
||||||
|
OnClick = "UiEvalService.ApiKickUser(e.row.data.UserId, gridRef);",
|
||||||
|
IsVisible = true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -2172,7 +2182,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
SourceDbType = DbType.Guid,
|
SourceDbType = DbType.Guid,
|
||||||
FieldName = "SessionId",
|
FieldName = "SessionId",
|
||||||
CaptionName = "App.Listform.ListformField.SessionId",
|
CaptionName = "App.Listform.ListformField.SessionId",
|
||||||
Width = 250,
|
Width = 275,
|
||||||
ListOrderNo = 2,
|
ListOrderNo = 2,
|
||||||
Visible = true,
|
Visible = true,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ public class PlatformHttpApiHostModule : AbpModule
|
||||||
options.AddAudiences(PlatformConsts.AppName);
|
options.AddAudiences(PlatformConsts.AppName);
|
||||||
options.UseLocalServer();
|
options.UseLocalServer();
|
||||||
options.UseAspNetCore();
|
options.UseAspNetCore();
|
||||||
|
options.EnableTokenEntryValidation();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { generateBackgroundWorkers } from '@/services/background-worker.service'
|
||||||
import { getLocalization } from '@/services/localization.service'
|
import { getLocalization } from '@/services/localization.service'
|
||||||
import { store } from '@/store'
|
import { store } from '@/store'
|
||||||
import { clearRedisCache } from './languageText.service'
|
import { clearRedisCache } from './languageText.service'
|
||||||
|
import { kickUser } from './identity.service'
|
||||||
|
|
||||||
export abstract class UiEvalService {
|
export abstract class UiEvalService {
|
||||||
static Init = () => {
|
static Init = () => {
|
||||||
|
|
@ -84,6 +85,47 @@ export abstract class UiEvalService {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ApiKickUser = (userId: string, gridRef?: any) => {
|
||||||
|
// Get store state directly instead of using hook
|
||||||
|
const state = store.getState()
|
||||||
|
const { texts, config } = state.abpConfig
|
||||||
|
|
||||||
|
// Create translate function similar to useLocalization hook
|
||||||
|
const translate = (
|
||||||
|
localizationKey: string,
|
||||||
|
params?: Record<string, string | number>,
|
||||||
|
defaultResourceName?: string,
|
||||||
|
): string => {
|
||||||
|
if (!texts) {
|
||||||
|
return localizationKey
|
||||||
|
}
|
||||||
|
return getLocalization(
|
||||||
|
texts,
|
||||||
|
defaultResourceName ?? config?.localization?.defaultResourceName,
|
||||||
|
localizationKey,
|
||||||
|
params,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const asyncCall = async () => {
|
||||||
|
await kickUser(userId)
|
||||||
|
if (gridRef?.current) {
|
||||||
|
gridRef.current.instance().refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncCall()
|
||||||
|
|
||||||
|
toast.push(
|
||||||
|
<Notification type="success" duration={2000}>
|
||||||
|
{translate('::App.KickUser.Message')}
|
||||||
|
</Notification>,
|
||||||
|
{
|
||||||
|
placement: 'top-end',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _global = (window || global) as any
|
const _global = (window || global) as any
|
||||||
|
|
|
||||||
|
|
@ -93,3 +93,9 @@ export const deleteClaimUser = (id: string, userId?: string) =>
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
url: `/api/app/platform-identity/${id}/claim-user/${userId}`,
|
url: `/api/app/platform-identity/${id}/claim-user/${userId}`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const kickUser = (userId: string) =>
|
||||||
|
apiService.fetchData({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/api/app/platform-identity/kick-user/${userId}`,
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -442,8 +442,8 @@ const useListFormColumns = ({
|
||||||
|
|
||||||
const item = {
|
const item = {
|
||||||
visible: visibleFunc,
|
visible: visibleFunc,
|
||||||
hint: action.hint,
|
|
||||||
icon: action.icon,
|
icon: action.icon,
|
||||||
|
hint: translate('::' + action.hint),
|
||||||
text: translate('::' + action.text),
|
text: translate('::' + action.text),
|
||||||
onClick: (e: any) => {
|
onClick: (e: any) => {
|
||||||
if (typeof e.event?.preventDefault === 'function') {
|
if (typeof e.event?.preventDefault === 'function') {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue