2462 changed files with 144460 additions and 155162 deletions
@ -0,0 +1,27 @@ |
|||
import { defHttp } from '/@/utils/http/axios'; |
|||
import { |
|||
IdentitySessionDto, |
|||
GetUserSessionsInput |
|||
} from './model'; |
|||
|
|||
/** |
|||
* 查询会话列表 |
|||
* @param { GetUserSessionsInput } input 查询参数 |
|||
* @returns { Promise<PagedResultDto<IdentitySessionDto>> } |
|||
*/ |
|||
export const getSessions = (input?: GetUserSessionsInput): Promise<PagedResultDto<IdentitySessionDto>> => { |
|||
return defHttp.get<PagedResultDto<IdentitySessionDto>>({ |
|||
url: '/api/identity/sessions', |
|||
params: input, |
|||
}); |
|||
}; |
|||
/** |
|||
* 撤销会话 |
|||
* @param { string } sessionId 会话id |
|||
* @returns { Promise<void> } |
|||
*/ |
|||
export const revokeSession = (sessionId: string): Promise<void> => { |
|||
return defHttp.delete<void>({ |
|||
url: `/api/identity/sessions/${sessionId}/revoke`, |
|||
}); |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
export interface IdentitySessionDto extends EntityDto<string> { |
|||
sessionId: string; |
|||
device: string; |
|||
deviceInfo: string; |
|||
userId: string; |
|||
clientId?: string; |
|||
ipAddresses?: string; |
|||
signedIn: Date; |
|||
lastAccessed?: Date; |
|||
} |
|||
|
|||
export interface GetUserSessionsInput extends PagedAndSortedResultRequestDto { |
|||
userId?: string; |
|||
device?: string; |
|||
clientId?: string; |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
<template> |
|||
<BasicModal |
|||
v-bind="$attrs" |
|||
@register="registerModal" |
|||
:width="800" |
|||
:height="500" |
|||
:title="L('IdentitySessions')" |
|||
:mask-closable="false" |
|||
:can-fullscreen="false" |
|||
:show-ok-btn="false" |
|||
> |
|||
<div :style="getContentStyle" ref="contentWrapRef" class="session"> |
|||
<ScrollContainer ref="contentScrollRef"> |
|||
<template v-for="identitySession in identitySessions" :key="identitySession.id"> |
|||
<Card style="height: 100%"> |
|||
<template #title> |
|||
<div class="session__tile"> |
|||
<span>{{ identitySession.device }}</span> |
|||
<div style="padding-left: 5px;"> |
|||
<Tag |
|||
v-if="identitySession.sessionId === abpStore.getApplication.currentUser.sessionId" |
|||
color="#87d068" |
|||
>{{ L('CurrentSession') }}</Tag> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<Descriptions bordered size="small" :column="1"> |
|||
<DescriptionItem :label="L('DisplayName:SessionId')">{{ identitySession.sessionId }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:Device')">{{ identitySession.device }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:DeviceInfo')">{{ identitySession.deviceInfo }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:ClientId')">{{ identitySession.clientId }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:IpAddresses')">{{ identitySession.ipAddresses }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:SignedIn')">{{ formatToDateTime(identitySession.signedIn) }}</DescriptionItem> |
|||
<DescriptionItem v-if="identitySession.lastAccessed" :label="L('DisplayName:LastAccessed')">{{ formatToDateTime(identitySession.lastAccessed) }}</DescriptionItem> |
|||
</Descriptions> |
|||
<template #extra> |
|||
<Button |
|||
v-if="identitySession.sessionId !== abpStore.getApplication.currentUser.sessionId" |
|||
danger |
|||
@click="handleRevokeSession(identitySession)" |
|||
>{{ L('RevokeSession') }}</Button> |
|||
</template> |
|||
</Card> |
|||
</template> |
|||
</ScrollContainer> |
|||
</div> |
|||
<template #footer> |
|||
<APagination |
|||
ref="paginationRef" |
|||
:pageSizeOptions="['10', '25', '50', '100']" |
|||
:total="identitySessionTotal" |
|||
@change="fetchSessions" |
|||
@showSizeChange="fetchSessions" |
|||
/> |
|||
</template> |
|||
</BasicModal> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import type { CSSProperties } from 'vue'; |
|||
import { computed, ref } from 'vue'; |
|||
import { Button, Card, Descriptions, Pagination, Tag } from 'ant-design-vue'; |
|||
import { BasicModal, useModalInner } from '/@/components/Modal'; |
|||
import { ScrollContainer } from '/@/components/Container'; |
|||
import { useMessage } from '/@/hooks/web/useMessage'; |
|||
import { useLocalization } from '/@/hooks/abp/useLocalization'; |
|||
import { useContentHeight } from '/@/hooks/web/useContentHeight'; |
|||
import { useAbpStoreWithOut } from '/@/store/modules/abp'; |
|||
import { getSessions, revokeSession } from '/@/api/account/profiles'; |
|||
import { IdentitySessionDto } from '/@/api/identity/sessions/model'; |
|||
import { formatPagedRequest } from '/@/utils/http/abp/helper'; |
|||
import { formatToDateTime } from '/@/utils/dateUtil'; |
|||
|
|||
const DescriptionItem = Descriptions.Item; |
|||
const APagination = Pagination; |
|||
|
|||
const props = defineProps({ |
|||
autoContentHeight: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
}); |
|||
|
|||
const contentWrapRef = ref<any>(); |
|||
const contentScrollRef = ref<any>(); |
|||
const paginationRef = ref<any>(); |
|||
const getContentHeight = computed(() => props.autoContentHeight); |
|||
const { contentHeight } = useContentHeight(getContentHeight, contentWrapRef, [paginationRef], []); |
|||
const getContentStyle = computed((): CSSProperties => { |
|||
return { |
|||
width: '100%', |
|||
height: `${contentHeight.value}px`, |
|||
}; |
|||
}); |
|||
const identitySessions = ref<IdentitySessionDto[]>([]); |
|||
const identitySessionTotal = ref(0); |
|||
const abpStore = useAbpStoreWithOut(); |
|||
const { createConfirm, createMessage } = useMessage(); |
|||
const { L } = useLocalization(['AbpIdentity', 'AbpUi']); |
|||
const [registerModal] = useModalInner(() => { |
|||
fetchSessions(); |
|||
}); |
|||
|
|||
function fetchSessions(page: number = 1, pageSize: number = 10) { |
|||
const request = { |
|||
skipCount: page, |
|||
maxResultCount: pageSize, |
|||
}; |
|||
formatPagedRequest(request); |
|||
getSessions({ |
|||
skipCount: request.skipCount, |
|||
maxResultCount: request.maxResultCount, |
|||
}).then((res) => { |
|||
identitySessions.value = res.items; |
|||
identitySessionTotal.value = res.totalCount; |
|||
}); |
|||
} |
|||
|
|||
function handleRevokeSession(session: IdentitySessionDto) { |
|||
createConfirm({ |
|||
iconType: 'warning', |
|||
title: L('AreYouSure'), |
|||
content: L('SessionWillBeRevokedMessage'), |
|||
onOk: async () => { |
|||
await revokeSession(session.sessionId); |
|||
createMessage.success(L('SuccessfullyRevoked')); |
|||
fetchSessions(); |
|||
}, |
|||
}); |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.session { |
|||
.session__tile { |
|||
display: flex; |
|||
flex-direction: row; |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
@ -0,0 +1,150 @@ |
|||
<template> |
|||
<BasicModal |
|||
v-bind="$attrs" |
|||
@register="registerModal" |
|||
:width="800" |
|||
:height="500" |
|||
:title="L('IdentitySessions')" |
|||
:mask-closable="false" |
|||
:can-fullscreen="false" |
|||
:show-ok-btn="false" |
|||
> |
|||
<div v-if="identitySessions.length <= 0"> |
|||
<Empty /> |
|||
</div> |
|||
<div v-else :style="getContentStyle" ref="contentWrapRef" class="session"> |
|||
<ScrollContainer ref="contentScrollRef"> |
|||
<template v-for="identitySession in identitySessions" :key="identitySession.id"> |
|||
<Card style="height: 100%"> |
|||
<template #title> |
|||
<div class="session__tile"> |
|||
<span>{{ identitySession.device }}</span> |
|||
<div style="padding-left: 5px;"> |
|||
<Tag |
|||
v-if="identitySession.sessionId === abpStore.getApplication.currentUser.sessionId" |
|||
color="#87d068" |
|||
>{{ L('CurrentSession') }}</Tag> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<Descriptions bordered size="small" :column="1"> |
|||
<DescriptionItem :label="L('DisplayName:SessionId')">{{ identitySession.sessionId }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:Device')">{{ identitySession.device }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:DeviceInfo')">{{ identitySession.deviceInfo }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:ClientId')">{{ identitySession.clientId }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:IpAddresses')">{{ identitySession.ipAddresses }}</DescriptionItem> |
|||
<DescriptionItem :label="L('DisplayName:SignedIn')">{{ formatToDateTime(identitySession.signedIn) }}</DescriptionItem> |
|||
<DescriptionItem v-if="identitySession.lastAccessed" :label="L('DisplayName:LastAccessed')">{{ formatToDateTime(identitySession.lastAccessed) }}</DescriptionItem> |
|||
</Descriptions> |
|||
<template #extra> |
|||
<Button |
|||
v-auth="['AbpIdentity.IdentitySessions.Revoke']" |
|||
v-if="identitySession.sessionId !== abpStore.getApplication.currentUser.sessionId" |
|||
danger |
|||
@click="handleRevokeSession(identitySession)" |
|||
>{{ L('RevokeSession') }}</Button> |
|||
</template> |
|||
</Card> |
|||
</template> |
|||
</ScrollContainer> |
|||
</div> |
|||
<template #footer> |
|||
<APagination |
|||
v-if="identitySessions.length > 0" |
|||
ref="paginationRef" |
|||
:pageSizeOptions="['10', '25', '50', '100']" |
|||
:total="identitySessionTotal" |
|||
@change="fetchSessions" |
|||
@showSizeChange="fetchSessions" |
|||
/> |
|||
</template> |
|||
</BasicModal> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import type { CSSProperties } from 'vue'; |
|||
import { computed, ref } from 'vue'; |
|||
import { Button, Card, Descriptions, Empty, Pagination, Tag } from 'ant-design-vue'; |
|||
import { BasicModal, useModalInner } from '/@/components/Modal'; |
|||
import { ScrollContainer } from '/@/components/Container'; |
|||
import { useMessage } from '/@/hooks/web/useMessage'; |
|||
import { useLocalization } from '/@/hooks/abp/useLocalization'; |
|||
import { useContentHeight } from '/@/hooks/web/useContentHeight'; |
|||
import { useAbpStoreWithOut } from '/@/store/modules/abp'; |
|||
import { getSessions, revokeSession } from '/@/api/identity/sessions'; |
|||
import { IdentitySessionDto } from '/@/api/identity/sessions/model'; |
|||
import { formatPagedRequest } from '/@/utils/http/abp/helper'; |
|||
import { formatToDateTime } from '/@/utils/dateUtil'; |
|||
|
|||
const DescriptionItem = Descriptions.Item; |
|||
const APagination = Pagination; |
|||
|
|||
const props = defineProps({ |
|||
autoContentHeight: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
}); |
|||
|
|||
const userId = ref(''); |
|||
const contentWrapRef = ref<any>(); |
|||
const contentScrollRef = ref<any>(); |
|||
const paginationRef = ref<any>(); |
|||
const getContentHeight = computed(() => props.autoContentHeight); |
|||
const { contentHeight } = useContentHeight(getContentHeight, contentWrapRef, [paginationRef], []); |
|||
const getContentStyle = computed((): CSSProperties => { |
|||
return { |
|||
width: '100%', |
|||
height: `${contentHeight.value}px`, |
|||
}; |
|||
}); |
|||
const identitySessions = ref<IdentitySessionDto[]>([]); |
|||
const identitySessionTotal = ref(0); |
|||
const abpStore = useAbpStoreWithOut(); |
|||
const { createConfirm, createMessage } = useMessage(); |
|||
const { L } = useLocalization(['AbpIdentity', 'AbpUi']); |
|||
const [registerModal] = useModalInner((data: { userId: string }) => { |
|||
userId.value = data.userId; |
|||
identitySessions.value = []; |
|||
fetchSessions(); |
|||
}); |
|||
|
|||
function fetchSessions(page: number = 1, pageSize: number = 10) { |
|||
const request = { |
|||
skipCount: page, |
|||
maxResultCount: pageSize, |
|||
}; |
|||
formatPagedRequest(request); |
|||
getSessions({ |
|||
userId: userId.value, |
|||
skipCount: request.skipCount, |
|||
maxResultCount: request.maxResultCount, |
|||
}).then((res) => { |
|||
identitySessions.value = res.items; |
|||
identitySessionTotal.value = res.totalCount; |
|||
}); |
|||
} |
|||
|
|||
function handleRevokeSession(session: IdentitySessionDto) { |
|||
createConfirm({ |
|||
iconType: 'warning', |
|||
title: L('AreYouSure'), |
|||
content: L('SessionWillBeRevokedMessage'), |
|||
onOk: async () => { |
|||
await revokeSession(session.sessionId); |
|||
createMessage.success(L('SuccessfullyRevoked')); |
|||
fetchSessions(); |
|||
}, |
|||
}); |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.session { |
|||
.session__tile { |
|||
display: flex; |
|||
flex-direction: row; |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
@ -1,10 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Auditing; |
|||
|
|||
namespace LINGYUN.Abp.AuditLogging |
|||
namespace LINGYUN.Abp.AuditLogging; |
|||
|
|||
public interface IAuditLogInfoToAuditLogConverter |
|||
{ |
|||
public interface IAuditLogInfoToAuditLogConverter |
|||
{ |
|||
Task<AuditLog> ConvertAsync(AuditLogInfo auditLogInfo); |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.AuditLogging.Elasticsearch |
|||
namespace LINGYUN.Abp.AuditLogging.Elasticsearch; |
|||
|
|||
public interface IIndexInitializer |
|||
{ |
|||
public interface IIndexInitializer |
|||
{ |
|||
Task InitializeAsync(); |
|||
} |
|||
} |
|||
|
|||
@ -1,7 +1,6 @@ |
|||
namespace LINGYUN.Abp.AuditLogging.Elasticsearch |
|||
namespace LINGYUN.Abp.AuditLogging.Elasticsearch; |
|||
|
|||
public interface IIndexNameNormalizer |
|||
{ |
|||
public interface IIndexNameNormalizer |
|||
{ |
|||
string NormalizeIndex(string index); |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
namespace LINGYUN.Abp.AuditLogging |
|||
namespace LINGYUN.Abp.AuditLogging; |
|||
|
|||
public class EntityChangeWithUsername |
|||
{ |
|||
public class EntityChangeWithUsername |
|||
{ |
|||
public EntityChange EntityChange { get; set; } |
|||
|
|||
public string UserName { get; set; } |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
namespace LINGYUN.Abp.Aliyun.SettingManagement |
|||
namespace LINGYUN.Abp.Aliyun.SettingManagement; |
|||
|
|||
public class AliyunSettingPermissionNames |
|||
{ |
|||
public class AliyunSettingPermissionNames |
|||
{ |
|||
public const string GroupName = "Abp.Aliyun"; |
|||
|
|||
public const string Settings = GroupName + ".Settings"; |
|||
} |
|||
} |
|||
|
|||
@ -1,8 +1,7 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
|
|||
namespace LINGYUN.Abp.Aliyun.SettingManagement |
|||
namespace LINGYUN.Abp.Aliyun.SettingManagement; |
|||
|
|||
public interface IAliyunSettingAppService : IReadonlySettingAppService |
|||
{ |
|||
public interface IAliyunSettingAppService : IReadonlySettingAppService |
|||
{ |
|||
} |
|||
} |
|||
|
|||
@ -1,15 +1,14 @@ |
|||
using Aliyun.Acs.Core; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Aliyun |
|||
namespace LINGYUN.Abp.Aliyun; |
|||
|
|||
public interface IAcsClientFactory |
|||
{ |
|||
public interface IAcsClientFactory |
|||
{ |
|||
/// <summary>
|
|||
/// 构造一个通用的Acs客户端调用
|
|||
/// 通过CommonRequest调用可以不需要集成其他SDK包
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
Task<IAcsClient> CreateAsync(); |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.Aliyun.Localization |
|||
namespace LINGYUN.Abp.Aliyun.Localization; |
|||
|
|||
[LocalizationResourceName("Aliyun")] |
|||
public class AliyunResource |
|||
{ |
|||
[LocalizationResourceName("Aliyun")] |
|||
public class AliyunResource |
|||
{ |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,8 @@ |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Tencent |
|||
namespace LINGYUN.Abp.BlobStoring.Tencent; |
|||
|
|||
public interface ITencentBlobNameCalculator |
|||
{ |
|||
public interface ITencentBlobNameCalculator |
|||
{ |
|||
string Calculate(BlobProviderArgs args); |
|||
} |
|||
} |
|||
|
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue