Implement cli and web token revoking

This commit is contained in:
Johannes Zellner
2025-01-14 15:52:12 +01:00
parent 99b2140838
commit 467921dbf6
5 changed files with 119 additions and 24 deletions

View File

@@ -51,6 +51,20 @@
</div>
</div>
</Card>
<h2>{{ $t('profile.appPasswords.title') }}</h2>
<Card>
</Card>
<h2 v-show="user.isAtLeastAdmin">{{ $t('profile.apiTokens.title') }}</h2>
<Card v-show="user.isAtLeastAdmin">
</Card>
<h2>{{ $t('profile.loginTokens.title') }}</h2>
<Card>
<p>{{ $t('profile.loginTokens.description', { webadminTokenCount: webadminTokens.length, cliTokenCount: cliTokens.length }) }}</p>
<Button danger :loading="revokeTokensBusy" :disabled="revokeTokensBusy" @click="onRevokeAllWebAndCliTokens()">{{ $t('profile.loginTokens.logoutAll') }}</Button>
</Card>
</div>
</template>
@@ -59,9 +73,11 @@
import { useI18n } from 'vue-i18n';
import { ref, onMounted, useTemplateRef } from 'vue';
import { Button, Dropdown, InputDialog } from 'pankow';
import { TOKEN_TYPES } from '../constants.js';
import Card from './Card.vue';
import ProfileModel from '../models/ProfileModel.js';
import CloudronModel from '../models/CloudronModel.js';
import TokensModel from '../models/TokensModel.js';
const i18n = useI18n();
const t = i18n.t;
@@ -70,33 +86,15 @@ const API_ORIGIN = import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_OR
const profileModel = ProfileModel.create(API_ORIGIN, localStorage.token);
const cloudronModel = CloudronModel.create(API_ORIGIN, localStorage.token);
const tokensModel = TokensModel.create(API_ORIGIN, localStorage.token);
// TODO what is this?
const config = ref({});
const config = ref({}); // TODO what is this?
const user = ref({});
const inputDialog = useTemplateRef('inputDialog');
const languages = ref([]);
const language = ref('');
const inputDialog = useTemplateRef('inputDialog');
const avatarFileInput = useTemplateRef('avatarFileInput');
onMounted(async () => {
user.value = await profileModel.get();
const langs = await cloudronModel.languages();
languages.value = langs.map(l => {
return {
id: l,
display: t(`lang.${l}`)
};
}).sort((a, b) => {
return a.display.localeCompare(b.display);
});
const usedLang = window.localStorage.NG_TRANSLATE_LANG_KEY || 'en';
language.value = languages.value.find(l => l.id === usedLang).id;
});
async function onSelectLanguage(lang) {
window.localStorage.NG_TRANSLATE_LANG_KEY = lang.id;
@@ -190,6 +188,7 @@ async function onLogout() {
await profileModel.logout();
}
const avatarFileInput = useTemplateRef('avatarFileInput');
async function onAvatarChanged() {
if (!avatarFileInput.value.files[0]) return;
await profileModel.setAvatar(avatarFileInput.value.files[0]);
@@ -200,6 +199,47 @@ async function onAvatarChanged() {
user.value.avatarUrl = u.toString();
}
// Tokens
const webadminTokens = ref([]);
const cliTokens = ref([]);
const apiTokens = ref([]);
const revokeTokensBusy = ref(false);
async function onRevokeAllWebAndCliTokens() {
revokeTokensBusy.value = true;
// filter current access token to be able to logout still
const tokens = webadminTokens.value.concat(cliTokens.value).filter(t => t.accessToken !== localStorage.token);
for (const token of tokens) {
await tokensModel.remove(token.id);
}
await profileModel.logout();
}
onMounted(async () => {
user.value = await profileModel.get();
const langs = await cloudronModel.languages();
languages.value = langs.map(l => {
return {
id: l,
display: t(`lang.${l}`)
};
}).sort((a, b) => {
return a.display.localeCompare(b.display);
});
const usedLang = window.localStorage.NG_TRANSLATE_LANG_KEY || 'en';
language.value = languages.value.find(l => l.id === usedLang).id;
const tokens = await tokensModel.list();
// dashboard and development clientIds were issued with 7.5.0
webadminTokens.value = tokens.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_WEBADMIN || c.clientId === TOKEN_TYPES.ID_DEVELOPMENT || c.clientId === 'dashboard' || c.clientId === 'development'; });
cliTokens.value = tokens.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_CLI; });
apiTokens.value = tokens.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_SDK; });
});
</script>