252 lines
6.9 KiB
Vue
252 lines
6.9 KiB
Vue
<template>
|
|
<div id="oauth2-app" class="description-list">
|
|
<Modal
|
|
v-if="displayModal"
|
|
:title="$t('common.CONFIRMATION')"
|
|
:message="$t(messageToDisplay)"
|
|
@confirmAction="confirmAction(client.id)"
|
|
@cancelAction="updateDisplayModal(false)"
|
|
/>
|
|
<div v-if="client && client.client_id">
|
|
<div
|
|
class="info-box success-message"
|
|
v-if="afterCreation || revocationSuccessful"
|
|
>
|
|
{{
|
|
$t(
|
|
afterCreation
|
|
? 'oauth2.APP_CREATED_SUCCESSFULLY'
|
|
: 'oauth2.TOKENS_REVOKED'
|
|
)
|
|
}}
|
|
</div>
|
|
<dl>
|
|
<dt>{{ $t('oauth2.APP.CLIENT_ID') }}:</dt>
|
|
<dd>
|
|
{{ client.client_id }}
|
|
<i
|
|
v-if="afterCreation && clipboardSupport"
|
|
:class="`fa fa-${idCopied ? 'check' : 'copy'}`"
|
|
aria-hidden="true"
|
|
:title="$t('oauth2.COPY_TO_CLIPBOARD')"
|
|
@click="copyIdToClipboard"
|
|
>
|
|
</i>
|
|
</dd>
|
|
<dt v-if="afterCreation && client.client_secret">
|
|
{{ $t('oauth2.APP.CLIENT_SECRET') }}:
|
|
</dt>
|
|
<dd v-if="afterCreation && client.client_secret" class="app-secret">
|
|
{{ client.client_secret }}
|
|
<i
|
|
v-if="clipboardSupport"
|
|
:class="`fa fa-${secretCopied ? 'check' : 'copy'}`"
|
|
aria-hidden="true"
|
|
:title="$t('oauth2.COPY_TO_CLIPBOARD')"
|
|
@click="copySecretToClipboard"
|
|
>
|
|
</i>
|
|
</dd>
|
|
<dt>{{ capitalize($t('oauth2.APP.ISSUE_AT')) }}:</dt>
|
|
<dd>
|
|
{{
|
|
formatDate(
|
|
client.issued_at,
|
|
authUser.timezone,
|
|
authUser.date_format
|
|
)
|
|
}}
|
|
</dd>
|
|
<dt>{{ $t('oauth2.APP.NAME') }}:</dt>
|
|
<dd>{{ client.name }}</dd>
|
|
<dt>{{ $t('oauth2.APP.DESCRIPTION') }}:</dt>
|
|
<dd :class="{ 'no-description': !client.client_description }">
|
|
{{
|
|
client.client_description
|
|
? client.client_description
|
|
: $t('oauth2.NO_DESCRIPTION')
|
|
}}
|
|
</dd>
|
|
<dt>{{ $t('oauth2.APP.URL') }}:</dt>
|
|
<dd>{{ client.website }}</dd>
|
|
<dt>{{ $t('oauth2.APP.REDIRECT_URL') }}:</dt>
|
|
<dd>
|
|
{{ client.redirect_uris.length > 0 ? client.redirect_uris[0] : '' }}
|
|
</dd>
|
|
<dt>{{ $t('oauth2.APP.SCOPE.LABEL') }}:</dt>
|
|
<dd class="client-scopes">
|
|
<span
|
|
class="client-scope"
|
|
v-for="scope in client.scope.split(' ')"
|
|
:key="scope"
|
|
>
|
|
<code>{{ scope }}</code>
|
|
</span>
|
|
</dd>
|
|
</dl>
|
|
<div class="app-buttons">
|
|
<button class="danger" @click="updateMessageToDisplay(false)">
|
|
{{ $t('oauth2.REVOKE_ALL_TOKENS') }}
|
|
</button>
|
|
<button class="danger" @click="updateMessageToDisplay(true)">
|
|
{{ $t('oauth2.DELETE_APP') }}
|
|
</button>
|
|
<button @click="$router.push('/profile/apps')">
|
|
{{ $t('buttons.BACK') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
<p class="no-app">{{ $t('oauth2.NO_APP') }}</p>
|
|
<button @click="$router.push('/profile/apps')">
|
|
{{ $t('buttons.BACK') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {
|
|
ComputedRef,
|
|
Ref,
|
|
capitalize,
|
|
computed,
|
|
onBeforeMount,
|
|
toRefs,
|
|
ref,
|
|
onUnmounted,
|
|
withDefaults,
|
|
watch,
|
|
} from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
import { OAUTH2_STORE, ROOT_STORE } from '@/store/constants'
|
|
import { IOAuth2Client } from '@/types/oauth'
|
|
import { IAuthUserProfile } from '@/types/user'
|
|
import { useStore } from '@/use/useStore'
|
|
import { formatDate } from '@/utils/dates'
|
|
|
|
interface Props {
|
|
authUser: IAuthUserProfile
|
|
afterCreation?: boolean
|
|
}
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
afterCreation: false,
|
|
})
|
|
const route = useRoute()
|
|
const store = useStore()
|
|
|
|
const { afterCreation, authUser } = toRefs(props)
|
|
const client: ComputedRef<IOAuth2Client> = computed(
|
|
() => store.getters[OAUTH2_STORE.GETTERS.CLIENT]
|
|
)
|
|
const revocationSuccessful: ComputedRef<boolean> = computed(
|
|
() => store.getters[OAUTH2_STORE.GETTERS.REVOCATION_SUCCESSFUL]
|
|
)
|
|
const displayModal: Ref<boolean> = ref(false)
|
|
const messageToDisplay: Ref<string | null> = ref(null)
|
|
const idCopied: Ref<boolean> = ref(false)
|
|
const secretCopied: Ref<boolean> = ref(false)
|
|
const clipboardSupport: Ref<boolean> = ref(false)
|
|
|
|
onBeforeMount(() => {
|
|
loadClient()
|
|
if (navigator.clipboard) {
|
|
clipboardSupport.value = true
|
|
}
|
|
})
|
|
|
|
function loadClient() {
|
|
// after creation, client is already in store
|
|
if (
|
|
!afterCreation.value &&
|
|
route.params.id &&
|
|
typeof route.params.id === 'string'
|
|
) {
|
|
store.dispatch(OAUTH2_STORE.ACTIONS.GET_CLIENT_BY_ID, +route.params.id)
|
|
}
|
|
}
|
|
function updateMessageToDisplay(forDelete: boolean) {
|
|
messageToDisplay.value = forDelete
|
|
? 'oauth2.APP_DELETION_CONFIRMATION'
|
|
: 'oauth2.TOKENS_REVOCATION_CONFIRMATION'
|
|
updateDisplayModal(true)
|
|
}
|
|
function updateDisplayModal(value: boolean) {
|
|
displayModal.value = value
|
|
if (!value) {
|
|
messageToDisplay.value = null
|
|
}
|
|
}
|
|
function confirmAction(clientId: number) {
|
|
if (messageToDisplay.value === 'oauth2.APP_DELETION_CONFIRMATION') {
|
|
store.dispatch(OAUTH2_STORE.ACTIONS.DELETE_CLIENT, clientId)
|
|
} else {
|
|
store.dispatch(OAUTH2_STORE.ACTIONS.REVOKE_ALL_TOKENS, clientId)
|
|
}
|
|
}
|
|
function copyIdToClipboard() {
|
|
navigator.clipboard.writeText(client.value.client_id)
|
|
idCopied.value = true
|
|
secretCopied.value = false
|
|
setTimeout(() => {
|
|
idCopied.value = false
|
|
}, 3000)
|
|
}
|
|
function copySecretToClipboard() {
|
|
if (client.value.client_secret) {
|
|
navigator.clipboard.writeText(client.value.client_secret)
|
|
secretCopied.value = true
|
|
idCopied.value = false
|
|
setTimeout(() => {
|
|
secretCopied.value = false
|
|
}, 3000)
|
|
}
|
|
}
|
|
onUnmounted(() => {
|
|
store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
|
store.commit(OAUTH2_STORE.MUTATIONS.EMPTY_CLIENT)
|
|
store.commit(OAUTH2_STORE.MUTATIONS.SET_REVOCATION_SUCCESSFUL, false)
|
|
})
|
|
|
|
watch(
|
|
() => revocationSuccessful.value,
|
|
(newValue) => {
|
|
if (newValue) {
|
|
updateDisplayModal(false)
|
|
}
|
|
}
|
|
)
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import '~@/scss/vars.scss';
|
|
#oauth2-app {
|
|
.app-buttons {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: $default-padding;
|
|
}
|
|
.app-secret {
|
|
word-break: break-word;
|
|
}
|
|
.client-scopes {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
.client-scope {
|
|
padding-right: $default-padding * 1.5;
|
|
}
|
|
}
|
|
.fa-copy {
|
|
font-size: 0.9em;
|
|
}
|
|
.no-description {
|
|
font-style: italic;
|
|
}
|
|
.no-app {
|
|
font-style: italic;
|
|
padding: $default-padding 0;
|
|
}
|
|
}
|
|
</style>
|