2023-09-25 03:30:14 +00:00
|
|
|
<script lang="ts" setup>
|
|
|
|
import { formatDatetime, relativeTimeTo } from "@/utils/date";
|
|
|
|
import type { PersonalAccessToken } from "@halo-dev/api-client";
|
2024-06-26 10:42:50 +00:00
|
|
|
import { ucApiClient } from "@halo-dev/api-client";
|
2023-09-25 03:30:14 +00:00
|
|
|
import {
|
|
|
|
Dialog,
|
|
|
|
Toast,
|
|
|
|
VDropdownDivider,
|
|
|
|
VDropdownItem,
|
|
|
|
VEntity,
|
|
|
|
VEntityField,
|
|
|
|
VStatusDot,
|
|
|
|
} from "@halo-dev/components";
|
|
|
|
import { useQueryClient } from "@tanstack/vue-query";
|
|
|
|
import { computed } from "vue";
|
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
|
|
|
|
|
const props = withDefaults(
|
|
|
|
defineProps<{
|
|
|
|
token: PersonalAccessToken;
|
|
|
|
}>(),
|
|
|
|
{}
|
|
|
|
);
|
|
|
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
|
|
|
function handleDelete() {
|
|
|
|
Dialog.warning({
|
2023-11-30 10:56:10 +00:00
|
|
|
title: t("core.uc_profile.pat.operations.delete.title"),
|
|
|
|
description: t("core.uc_profile.pat.operations.delete.description"),
|
2023-09-25 03:30:14 +00:00
|
|
|
async onConfirm() {
|
2024-06-25 04:31:44 +00:00
|
|
|
await ucApiClient.security.personalAccessToken.deletePat({
|
2023-09-25 03:30:14 +00:00
|
|
|
name: props.token.metadata.name,
|
|
|
|
});
|
|
|
|
|
|
|
|
Toast.success(t("core.common.toast.delete_success"));
|
|
|
|
queryClient.invalidateQueries({ queryKey: ["personal-access-tokens"] });
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleRevoke() {
|
|
|
|
Dialog.warning({
|
2023-11-30 10:56:10 +00:00
|
|
|
title: t("core.uc_profile.pat.operations.revoke.title"),
|
|
|
|
description: t("core.uc_profile.pat.operations.revoke.description"),
|
2023-09-25 03:30:14 +00:00
|
|
|
async onConfirm() {
|
2024-06-25 04:31:44 +00:00
|
|
|
await ucApiClient.security.personalAccessToken.revokePat({
|
2023-09-25 03:30:14 +00:00
|
|
|
name: props.token.metadata.name,
|
|
|
|
});
|
|
|
|
|
2023-11-30 10:56:10 +00:00
|
|
|
Toast.success(t("core.uc_profile.pat.operations.revoke.toast_success"));
|
2023-09-25 03:30:14 +00:00
|
|
|
queryClient.invalidateQueries({ queryKey: ["personal-access-tokens"] });
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function handleRestore() {
|
2024-06-25 04:31:44 +00:00
|
|
|
await ucApiClient.security.personalAccessToken.restorePat({
|
|
|
|
name: props.token.metadata.name,
|
|
|
|
});
|
2023-09-25 03:30:14 +00:00
|
|
|
|
2023-11-30 10:56:10 +00:00
|
|
|
Toast.success(t("core.uc_profile.pat.operations.restore.toast_success"));
|
2023-09-25 03:30:14 +00:00
|
|
|
queryClient.invalidateQueries({ queryKey: ["personal-access-tokens"] });
|
|
|
|
}
|
|
|
|
|
|
|
|
const statusText = computed(() => {
|
|
|
|
const { expiresAt } = props.token.spec || {};
|
|
|
|
if (expiresAt && new Date(expiresAt) < new Date()) {
|
2023-11-30 10:56:10 +00:00
|
|
|
return t("core.uc_profile.pat.list.fields.status.expired");
|
2023-09-25 03:30:14 +00:00
|
|
|
}
|
|
|
|
return t(
|
|
|
|
props.token.spec?.revoked
|
2023-11-30 10:56:10 +00:00
|
|
|
? "core.uc_profile.pat.list.fields.status.revoked"
|
|
|
|
: "core.uc_profile.pat.list.fields.status.normal"
|
2023-09-25 03:30:14 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
const statusTheme = computed(() => {
|
|
|
|
const { expiresAt } = props.token.spec || {};
|
|
|
|
if (expiresAt && new Date(expiresAt) < new Date()) {
|
|
|
|
return "warning";
|
|
|
|
}
|
|
|
|
return props.token.spec?.revoked ? "default" : "success";
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<VEntity>
|
|
|
|
<template #start>
|
|
|
|
<VEntityField
|
|
|
|
:title="token.spec?.name || token.metadata.name"
|
|
|
|
:description="token.spec?.description"
|
|
|
|
></VEntityField>
|
|
|
|
</template>
|
|
|
|
<template #end>
|
|
|
|
<VEntityField v-if="token.metadata.deletionTimestamp">
|
|
|
|
<template #description>
|
|
|
|
<VStatusDot
|
|
|
|
v-tooltip="$t('core.common.status.deleting')"
|
|
|
|
state="warning"
|
|
|
|
animate
|
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
</VEntityField>
|
|
|
|
<VEntityField v-if="!token.spec?.revoked">
|
|
|
|
<template #description>
|
|
|
|
<div class="truncate text-xs tabular-nums text-gray-500">
|
|
|
|
<span
|
|
|
|
v-if="token.spec?.expiresAt"
|
|
|
|
v-tooltip="formatDatetime(token.spec.expiresAt)"
|
|
|
|
>
|
|
|
|
{{
|
2023-11-30 10:56:10 +00:00
|
|
|
$t("core.uc_profile.pat.list.fields.expiresAt.dynamic", {
|
2023-09-25 03:30:14 +00:00
|
|
|
expiresAt: relativeTimeTo(token.spec?.expiresAt),
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
</span>
|
|
|
|
<span v-else>
|
2023-11-30 10:56:10 +00:00
|
|
|
{{ $t("core.uc_profile.pat.list.fields.expiresAt.forever") }}
|
2023-09-25 03:30:14 +00:00
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</VEntityField>
|
|
|
|
<VEntityField>
|
|
|
|
<template #description>
|
|
|
|
<VStatusDot :text="statusText" :state="statusTheme" />
|
|
|
|
</template>
|
|
|
|
</VEntityField>
|
|
|
|
<VEntityField
|
|
|
|
:description="formatDatetime(token.metadata.creationTimestamp)"
|
|
|
|
></VEntityField>
|
|
|
|
</template>
|
|
|
|
<template #dropdownItems>
|
|
|
|
<VDropdownItem
|
|
|
|
v-if="!token.spec?.revoked"
|
|
|
|
type="danger"
|
|
|
|
@click="handleRevoke"
|
|
|
|
>
|
2023-11-30 10:56:10 +00:00
|
|
|
{{ $t("core.uc_profile.pat.operations.revoke.button") }}
|
2023-09-25 03:30:14 +00:00
|
|
|
</VDropdownItem>
|
|
|
|
<VDropdownItem v-else @click="handleRestore">
|
2023-11-30 10:56:10 +00:00
|
|
|
{{ $t("core.uc_profile.pat.operations.restore.button") }}
|
2023-09-25 03:30:14 +00:00
|
|
|
</VDropdownItem>
|
|
|
|
<VDropdownDivider />
|
|
|
|
<VDropdownItem type="danger" @click="handleDelete">
|
|
|
|
{{ $t("core.common.buttons.delete") }}
|
|
|
|
</VDropdownItem>
|
|
|
|
</template>
|
|
|
|
</VEntity>
|
|
|
|
</template>
|